diff --git a/.backportrc.json b/.backportrc.json index 3f1d639e9a480..a97c82ca0efa9 100644 --- a/.backportrc.json +++ b/.backportrc.json @@ -3,6 +3,7 @@ "targetBranchChoices": [ { "name": "master", "checked": true }, { "name": "7.x", "checked": true }, + "7.10", "7.9", "7.8", "7.7", @@ -27,7 +28,7 @@ "targetPRLabels": ["backport"], "branchLabelMapping": { "^v8.0.0$": "master", - "^v7.10.0$": "7.x", + "^v7.11.0$": "7.x", "^v(\\d+).(\\d+).\\d+$": "$1.$2" } } diff --git a/.ci/Jenkinsfile_baseline_capture b/.ci/Jenkinsfile_baseline_capture index 33ecfcd84fd3e..791cacf7abb4c 100644 --- a/.ci/Jenkinsfile_baseline_capture +++ b/.ci/Jenkinsfile_baseline_capture @@ -12,12 +12,12 @@ kibanaPipeline(timeoutMinutes: 120) { ]) { parallel([ 'oss-baseline': { - workers.ci(name: 'oss-baseline', size: 's-highmem', ramDisk: true, runErrorReporter: false) { + workers.ci(name: 'oss-baseline', size: 'l', ramDisk: true, runErrorReporter: false) { kibanaPipeline.functionalTestProcess('oss-baseline', './test/scripts/jenkins_baseline.sh')() } }, 'xpack-baseline': { - workers.ci(name: 'xpack-baseline', size: 's-highmem', ramDisk: true, runErrorReporter: false) { + workers.ci(name: 'xpack-baseline', size: 'l', ramDisk: true, runErrorReporter: false) { kibanaPipeline.functionalTestProcess('xpack-baseline', './test/scripts/jenkins_xpack_baseline.sh')() } }, diff --git a/.ci/Jenkinsfile_coverage b/.ci/Jenkinsfile_coverage index ebb9c3dc86dd2..1c1d21024ce91 100644 --- a/.ci/Jenkinsfile_coverage +++ b/.ci/Jenkinsfile_coverage @@ -12,8 +12,12 @@ kibanaPipeline(timeoutMinutes: 240) { ]) { workers.base(name: 'coverage-worker', size: 'l', ramDisk: false, bootstrapped: false) { catchError { + + kibanaPipeline.bash(""" + echo '${TIME_STAMP}' + """, "### Print Canonical Time Stamp") + kibanaCoverage.runTests() - kibanaTeamAssign.load('team_assignment', "### Upload Team Assignment JSON") handleIngestion(TIME_STAMP) } handleFail() @@ -30,8 +34,8 @@ def handleIngestion(timestamp) { kibanaCoverage.collectVcsInfo("### Collect VCS Info") kibanaCoverage.generateReports("### Merge coverage reports") kibanaCoverage.uploadCombinedReports() - kibanaCoverage.ingest(env.JOB_NAME, BUILD_NUMBER, BUILD_URL, timestamp, previousSha, '### Ingest && Upload') kibanaCoverage.uploadCoverageStaticSite(timestamp) + kibanaCoverage.ingest(env.JOB_NAME, BUILD_NUMBER, BUILD_URL, timestamp, previousSha, teamAssignmentsPath(), '### Generate Team Assignments && Ingest') } def handlePreviousSha() { @@ -42,7 +46,7 @@ def handlePreviousSha() { def handleFail() { def buildStatus = buildUtils.getBuildStatus() - if(params.NOTIFY_ON_FAILURE && buildStatus != 'SUCCESS' && buildStatus != 'ABORTED' && buildStatus != 'UNSTABLE') { + if (params.NOTIFY_ON_FAILURE && buildStatus != 'SUCCESS' && buildStatus != 'ABORTED' && buildStatus != 'UNSTABLE') { slackNotifications.sendFailedBuild( channel: '#kibana-qa', username: 'Kibana QA' @@ -50,3 +54,7 @@ def handleFail() { } } +def teamAssignmentsPath() { + return 'src/dev/code_coverage/ingest_coverage/team_assignment/team_assignments.txt' +} + diff --git a/.eslintrc.js b/.eslintrc.js index 3161a25b70870..27dacd51be6f2 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -17,9 +17,6 @@ * under the License. */ -const { readdirSync } = require('fs'); -const { resolve } = require('path'); - const APACHE_2_0_LICENSE_HEADER = ` /* * Licensed to Elasticsearch B.V. under one or more contributor @@ -288,7 +285,7 @@ module.exports = { }, { target: [ - '(src|x-pack)/legacy/**/*', + 'src/legacy/**/*', '(src|x-pack)/plugins/**/(public|server)/**/*', 'examples/**/*', ], @@ -319,14 +316,11 @@ module.exports = { }, { target: [ - '(src|x-pack)/legacy/**/*', + 'src/legacy/**/*', '(src|x-pack)/plugins/**/(public|server)/**/*', 'examples/**/*', '!(src|x-pack)/**/*.test.*', '!(x-pack/)?test/**/*', - // next folder contains legacy browser tests which can't be migrated to jest - // which import np files - '!src/legacy/core_plugins/kibana/public/__tests__/**/*', ], from: [ '(src|x-pack)/plugins/**/(public|server)/**/*', @@ -341,14 +335,6 @@ module.exports = { '(src|x-pack)/plugins/**/*', '!(src|x-pack)/plugins/**/server/**/*', - 'src/legacy/core_plugins/**/*', - '!src/legacy/core_plugins/**/server/**/*', - '!src/legacy/core_plugins/**/index.{js,mjs,ts,tsx}', - - 'x-pack/legacy/plugins/**/*', - '!x-pack/legacy/plugins/**/server/**/*', - '!x-pack/legacy/plugins/**/index.{js,mjs,ts,tsx}', - 'examples/**/*', '!examples/**/server/**/*', ], @@ -370,12 +356,7 @@ module.exports = { }, { target: ['src/core/**/*'], - from: [ - 'plugins/**/*', - 'src/plugins/**/*', - 'src/legacy/core_plugins/**/*', - 'src/legacy/ui/**/*', - ], + from: ['plugins/**/*', 'src/plugins/**/*', 'src/legacy/ui/**/*'], errorMessage: 'The core cannot depend on any plugins.', }, { @@ -388,12 +369,6 @@ module.exports = { target: [ 'test/plugin_functional/plugins/**/public/np_ready/**/*', 'test/plugin_functional/plugins/**/server/np_ready/**/*', - 'src/legacy/core_plugins/**/public/np_ready/**/*', - 'src/legacy/core_plugins/vis_type_*/public/**/*', - '!src/legacy/core_plugins/vis_type_*/public/legacy*', - 'src/legacy/core_plugins/**/server/np_ready/**/*', - 'x-pack/legacy/plugins/**/public/np_ready/**/*', - 'x-pack/legacy/plugins/**/server/np_ready/**/*', ], allowSameFolder: true, errorMessage: @@ -413,6 +388,7 @@ module.exports = { */ { files: [ + '**/*.stories.tsx', 'x-pack/test/apm_api_integration/**/*.ts', 'x-pack/test/functional/apps/**/*.js', 'x-pack/plugins/apm/**/*.js', @@ -443,22 +419,14 @@ module.exports = { settings: { // instructs import/no-extraneous-dependencies to treat certain modules // as core modules, even if they aren't listed in package.json - 'import/core-modules': ['plugins', 'legacy/ui'], + 'import/core-modules': ['plugins'], 'import/resolver': { '@kbn/eslint-import-resolver-kibana': { forceNode: false, rootPackageName: 'kibana', kibanaPath: '.', - pluginMap: readdirSync(resolve(__dirname, 'x-pack/legacy/plugins')).reduce( - (acc, name) => { - if (!name.startsWith('_')) { - acc[name] = `x-pack/legacy/plugins/${name}`; - } - return acc; - }, - {} - ), + pluginMap: {}, }, }, }, @@ -764,16 +732,6 @@ module.exports = { }, }, - /** - * GIS overrides - */ - { - files: ['x-pack/legacy/plugins/maps/**/*.js'], - rules: { - 'react/prefer-stateless-function': [0, { ignorePureComponents: false }], - }, - }, - /** * ML overrides */ @@ -812,7 +770,7 @@ module.exports = { }, { // typescript only for front and back end - files: ['x-pack/{,legacy/}plugins/security_solution/**/*.{ts,tsx}'], + files: ['x-pack/plugins/security_solution/**/*.{ts,tsx}'], rules: { // This will be turned on after bug fixes are complete // '@typescript-eslint/explicit-member-accessibility': 'warn', @@ -858,7 +816,7 @@ module.exports = { // }, { // typescript and javascript for front and back end - files: ['x-pack/{,legacy/}plugins/security_solution/**/*.{js,mjs,ts,tsx}'], + files: ['x-pack/plugins/security_solution/**/*.{js,mjs,ts,tsx}'], plugins: ['eslint-plugin-node', 'react'], env: { mocha: true, @@ -1088,9 +1046,7 @@ module.exports = { */ { // typescript only for front and back end - files: [ - 'x-pack/{,legacy/}plugins/{alerts,alerting_builtins,actions,task_manager,event_log}/**/*.{ts,tsx}', - ], + files: ['x-pack/plugins/{alerts,stack_alerts,actions,task_manager,event_log}/**/*.{ts,tsx}'], rules: { '@typescript-eslint/no-explicit-any': 'error', }, @@ -1238,10 +1194,7 @@ module.exports = { * TSVB overrides */ { - files: [ - 'src/plugins/vis_type_timeseries/**/*.{js,mjs,ts,tsx}', - 'src/legacy/core_plugins/vis_type_timeseries/**/*.{js,mjs,ts,tsx}', - ], + files: ['src/plugins/vis_type_timeseries/**/*.{js,mjs,ts,tsx}'], rules: { 'import/no-default-export': 'error', }, @@ -1275,5 +1228,20 @@ module.exports = { '@typescript-eslint/prefer-ts-expect-error': 'error', }, }, + { + files: [ + '**/public/**/*.{js,mjs,ts,tsx}', + '**/common/**/*.{js,mjs,ts,tsx}', + 'packages/**/*.{js,mjs,ts,tsx}', + ], + rules: { + 'no-restricted-imports': [ + 'error', + { + patterns: ['lodash/*', '!lodash/fp'], + }, + ], + }, + }, ], }; diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index ef8dbf2d25600..5dd41581914ed 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -2,15 +2,22 @@ # Identify which groups will be pinged by changes to different parts of the codebase. # For more info, see https://help.github.com/articles/about-codeowners/ +# The #CC# prefix delineates Code Coverage, +# used for the 'team' designator within Kibana Stats + # App /x-pack/plugins/dashboard_enhanced/ @elastic/kibana-app /x-pack/plugins/discover_enhanced/ @elastic/kibana-app /x-pack/plugins/lens/ @elastic/kibana-app /x-pack/plugins/graph/ @elastic/kibana-app +/src/plugins/advanced_settings/ @elastic/kibana-app +/src/plugins/charts/ @elastic/kibana-app /src/plugins/dashboard/ @elastic/kibana-app /src/plugins/discover/ @elastic/kibana-app /src/plugins/input_control_vis/ @elastic/kibana-app +/src/plugins/management/ @elastic/kibana-app /src/plugins/kibana_legacy/ @elastic/kibana-app +/src/plugins/timelion/ @elastic/kibana-app /src/plugins/vis_default_editor/ @elastic/kibana-app /src/plugins/vis_type_markdown/ @elastic/kibana-app /src/plugins/vis_type_metric/ @elastic/kibana-app @@ -22,6 +29,25 @@ /src/plugins/vis_type_vislib/ @elastic/kibana-app /src/plugins/vis_type_xy/ @elastic/kibana-app /src/plugins/visualize/ @elastic/kibana-app +/src/plugins/visualizations/ @elastic/kibana-app +#CC# /src/legacy/core_plugins/kibana/public/local_application_service/ @elastic/kibana-app +#CC# /src/legacy/core_plugins/kibana/ @elastic/kibana-app +#CC# /src/legacy/core_plugins/kibana/common/utils @elastic/kibana-app +#CC# /src/legacy/core_plugins/kibana/migrations @elastic/kibana-app +#CC# /src/legacy/core_plugins/kibana/public @elastic/kibana-app +#CC# /src/legacy/core_plugins/kibana/public/dashboard/ @elastic/kibana-app +#CC# /src/legacy/core_plugins/kibana/public/discover/ @elastic/kibana-app +#CC# /src/legacy/core_plugins/kibana/public/local_application_service/ @elastic/kibana-app +#CC# /src/legacy/core_plugins/input_control_vis @elastic/kibana-app +#CC# /src/legacy/core_plugins/timelion @elastic/kibana-app +#CC# /src/legacy/core_plugins/vis_type_tagcloud @elastic/kibana-app +#CC# /src/legacy/core_plugins/vis_type_vega @elastic/kibana-app +#CC# /src/legacy/core_plugins/vis_type_vislib/ @elastic/kibana-app +#CC# /src/legacy/server/url_shortening/ @elastic/kibana-app +#CC# /src/legacy/ui/public/state_management @elastic/kibana-app +#CC# /src/plugins/index_pattern_management/public @elastic/kibana-app +#CC# /x-pack/legacy/plugins/dashboard_mode/ @elastic/kibana-app +#CC# /x-pack/plugins/dashboard_mode @elastic/kibana-app # App Architecture /examples/bfetch_explorer/ @elastic/kibana-app-arch @@ -37,7 +63,6 @@ /examples/url_generators_explorer/ @elastic/kibana-app-arch /packages/elastic-datemath/ @elastic/kibana-app-arch /packages/kbn-interpreter/ @elastic/kibana-app-arch -/src/plugins/advanced_settings/ @elastic/kibana-app-arch /src/plugins/bfetch/ @elastic/kibana-app-arch /src/plugins/data/ @elastic/kibana-app-arch /src/plugins/embeddable/ @elastic/kibana-app-arch @@ -46,55 +71,90 @@ /src/plugins/kibana_react/ @elastic/kibana-app-arch /src/plugins/kibana_react/public/code_editor @elastic/kibana-canvas /src/plugins/kibana_utils/ @elastic/kibana-app-arch -/src/plugins/management/ @elastic/kibana-app-arch /src/plugins/navigation/ @elastic/kibana-app-arch /src/plugins/share/ @elastic/kibana-app-arch /src/plugins/ui_actions/ @elastic/kibana-app-arch -/src/plugins/visualizations/ @elastic/kibana-app-arch /x-pack/examples/ui_actions_enhanced_examples/ @elastic/kibana-app-arch /x-pack/plugins/data_enhanced/ @elastic/kibana-app-arch /x-pack/plugins/embeddable_enhanced/ @elastic/kibana-app-arch /x-pack/plugins/ui_actions_enhanced/ @elastic/kibana-app-arch +#CC# /src/legacy/core_plugins/kibana/public/management/ @elastic/kibana-app-arch +#CC# /src/legacy/core_plugins/kibana/server/routes/api/management/ @elastic/kibana-app-arch +#CC# /src/legacy/core_plugins/embeddable_api/ @elastic/kibana-app-arch +#CC# /src/legacy/core_plugins/interpreter/ @elastic/kibana-app-arch +#CC# /src/legacy/core_plugins/kibana_react/ @elastic/kibana-app-arch +#CC# /src/legacy/core_plugins/status_page/public @elastic/kibana-app-arch +#CC# /src/legacy/server/index_patterns/ @elastic/kibana-app-arch +#CC# /src/legacy/ui/public/field_editor @elastic/kibana-app-arch +#CC# /src/legacy/ui/public/management @elastic/kibana-app-arch +#CC# /src/plugins/advanced_settings/ @elastic/kibana-app-arch +#CC# /src/plugins/bfetch/ @elastic/kibana-app-arch +#CC# /src/plugins/charts/ @elastic/kibana-app-arch +#CC# /src/plugins/index_pattern_management/public/service @elastic/kibana-app-arch +#CC# /src/plugins/inspector/ @elastic/kibana-app-arch +#CC# /src/plugins/saved_objects/ @elastic/kibana-app-arch +#CC# /src/plugins/share/ @elastic/kibana-app-arch +#CC# /src/plugins/vis_default_editor @elastic/kibana-app-arch +#CC# /x-pack/plugins/advanced_ui_actions/ @elastic/kibana-app-arch +#CC# /x-pack/plugins/drilldowns/ @elastic/kibana-app-arch +#CC# /packages/kbn-interpreter/ @elastic/kibana-app-arch # APM /x-pack/plugins/apm/ @elastic/apm-ui /x-pack/test/functional/apps/apm/ @elastic/apm-ui /src/plugins/apm_oss/ @elastic/apm-ui /src/apm.js @watson @vigneshshanmugam +#CC# /src/plugins/apm_oss/ @elastic/apm-ui +#CC# /src/legacy/core_plugins/apm_oss/ @elastic/apm-ui +#CC# /src/legacy/ui/public/apm @elastic/apm-ui +#CC# /x-pack/legacy/plugins/apm/ @elastic/apm-ui +#CC# /x-pack/plugins/observability/ @elastic/apm-ui # Client Side Monitoring (lives in APM directories but owned by Uptime) /x-pack/plugins/apm/e2e/cypress/support/step_definitions/csm @elastic/uptime +/x-pack/plugins/apm/e2e/cypress/integration/csm_dashboard.feature @elastic/uptime /x-pack/plugins/apm/public/application/csmApp.tsx @elastic/uptime /x-pack/plugins/apm/public/components/app/RumDashboard @elastic/uptime /x-pack/plugins/apm/server/lib/rum_client @elastic/uptime /x-pack/plugins/apm/server/routes/rum_client.ts @elastic/uptime +/x-pack/plugins/apm/server/projections/rum_page_load_transactions.ts @elastic/uptime /x-pack/plugins/apm/server/projections/rum_overview.ts @elastic/uptime +#CC# /x-pack/legacy/plugins/uptime @elastic/uptime # Beats +/x-pack/plugins/beats_management/ @elastic/beats /x-pack/legacy/plugins/beats_management/ @elastic/beats +#CC# /x-pack/plugins/beats_management/ @elastic/beats # Canvas /x-pack/plugins/canvas/ @elastic/kibana-canvas /x-pack/test/functional/apps/canvas/ @elastic/kibana-canvas +#CC# /src/plugins/kibana_react/public/code_editor/ @elastic/kibana-canvas +#CC# /x-pack/legacy/plugins/canvas/ @elastic/kibana-canvas # Core UI # Exclude tutorials folder for now because they are not owned by Kibana app and most will move out soon /src/plugins/home/public @elastic/kibana-core-ui /src/plugins/home/server/*.ts @elastic/kibana-core-ui /src/plugins/home/server/services/ @elastic/kibana-core-ui +/src/plugins/kibana_overview/ @elastic/kibana-core-ui /x-pack/plugins/global_search_bar/ @elastic/kibana-core-ui +#CC# /src/legacy/core_plugins/newsfeed @elastic/kibana-core-ui +#CC# /src/legacy/server/sample_data/ @elastic/kibana-core-ui +#CC# /src/plugins/newsfeed @elastic/kibana-core-ui +#CC# /src/plugins/home/public @elastic/kibana-core-ui +#CC# /src/plugins/home/server/services/ @elastic/kibana-core-ui +#CC# /src/plugins/home/ @elastic/kibana-core-ui +#CC# /x-pack/plugins/global_search_providers/ @elastic/kibana-core-ui # Observability UIs -/x-pack/legacy/plugins/infra/ @elastic/logs-metrics-ui /x-pack/plugins/infra/ @elastic/logs-metrics-ui /x-pack/plugins/ingest_manager/ @elastic/ingest-management -/x-pack/legacy/plugins/ingest_manager/ @elastic/ingest-management /x-pack/plugins/observability/ @elastic/observability-ui /x-pack/plugins/monitoring/ @elastic/stack-monitoring-ui /x-pack/plugins/uptime @elastic/uptime # Machine Learning -/x-pack/legacy/plugins/ml/ @elastic/ml-ui /x-pack/plugins/ml/ @elastic/ml-ui /x-pack/test/functional/apps/machine_learning/ @elastic/ml-ui /x-pack/test/functional/services/machine_learning/ @elastic/ml-ui @@ -106,12 +166,19 @@ /x-pack/test/functional/services/transform.ts @elastic/ml-ui # Maps -/x-pack/legacy/plugins/maps/ @elastic/kibana-gis /x-pack/plugins/maps/ @elastic/kibana-gis /x-pack/test/api_integration/apis/maps/ @elastic/kibana-gis /x-pack/test/functional/apps/maps/ @elastic/kibana-gis /x-pack/test/functional/es_archives/maps/ @elastic/kibana-gis /x-pack/test/visual_regression/tests/maps/index.js @elastic/kibana-gis +#CC# /src/legacy/core_plugins/region_map @elastic/kibana-gis +#CC# /src/legacy/core_plugins/tile_map @elastic/kibana-gis +#CC# /src/plugins/maps_legacy/ @elastic/kibana-gis +#CC# /x-pack/plugins/file_upload @elastic/kibana-gis +#CC# /x-pack/plugins/maps_legacy_licensing @elastic/kibana-gis +#CC# /src/plugins/home/server/tutorials @elastic/kibana-gis +#CC# /src/plugins/tile_map/ @elastic/kibana-gis +#CC# /src/plugins/region_map/ @elastic/kibana-gis # Operations /src/dev/ @elastic/kibana-operations @@ -134,6 +201,7 @@ /src/legacy/server/warnings/ @elastic/kibana-operations /.ci/es-snapshots/ @elastic/kibana-operations /vars/ @elastic/kibana-operations +#CC# /packages/kbn-expect/ @elastic/kibana-operations # Quality Assurance /src/dev/code_coverage @elastic/kibana-qa @@ -160,9 +228,36 @@ /src/plugins/status_page/ @elastic/kibana-platform /src/plugins/saved_objects_management/ @elastic/kibana-platform /src/dev/run_check_published_api_changes.ts @elastic/kibana-platform +#CC# /src/core/server/csp/ @elastic/kibana-platform +#CC# /src/legacy/core_plugins/kibana/server/lib @elastic/kibana-platform +#CC# /src/legacy/core_plugins/kibana/server/lib/management/saved_objects @elastic/kibana-platform +#CC# /src/legacy/core_plugins/kibana/server/routes/api/import/ @elastic/kibana-platform +#CC# /src/legacy/core_plugins/kibana/server/routes/api/export/ @elastic/kibana-platform +#CC# /src/legacy/core_plugins/elasticsearch @elastic/kibana-platform +#CC# /src/legacy/core_plugins/testbed @elastic/kibana-platform +#CC# /src/legacy/server/config/ @elastic/kibana-platform +#CC# /src/legacy/server/http/ @elastic/kibana-platform +#CC# /src/legacy/server/status/ @elastic/kibana-platform +#CC# /src/legacy/ui/public/new_platform @elastic/kibana-platform +#CC# /src/legacy/ui/public/plugin_discovery @elastic/kibana-platform +#CC# /src/legacy/ui/public/chrome @elastic/kibana-platform +#CC# /src/legacy/ui/public/notify @elastic/kibana-platform +#CC# /src/legacy/ui/public/documentation_links @elastic/kibana-platform +#CC# /src/legacy/ui/public/autoload @elastic/kibana-platform +#CC# /src/plugins/legacy_export/ @elastic/kibana-platform +#CC# /src/plugins/status_page/ @elastic/kibana-platform +#CC# /src/plugins/testbed/server/ @elastic/kibana-platform +#CC# /x-pack/legacy/plugins/xpack_main/server/ @elastic/kibana-platform +#CC# /x-pack/legacy/server/lib/ @elastic/kibana-platform +#CC# /x-pack/plugins/cloud/ @elastic/kibana-platform +#CC# /x-pack/plugins/features/ @elastic/kibana-platform +#CC# /x-pack/plugins/global_search/ @elastic/kibana-platform +#CC# /src/legacy/plugin_discovery/ @elastic/kibana-platform # Security /src/core/server/csp/ @elastic/kibana-security @elastic/kibana-platform +/src/plugins/security_oss/ @elastic/kibana-security +/test/security_functional/ @elastic/kibana-security /x-pack/plugins/spaces/ @elastic/kibana-security /x-pack/plugins/encrypted_saved_objects/ @elastic/kibana-security /x-pack/plugins/security/ @elastic/kibana-security @@ -171,20 +266,25 @@ /x-pack/test/encrypted_saved_objects_api_integration/ @elastic/kibana-security /x-pack/test/functional/apps/security/ @elastic/kibana-security /x-pack/test/kerberos_api_integration/ @elastic/kibana-security -/x-pack/test/login_selector_api_integration/ @elastic/kibana-security /x-pack/test/oidc_api_integration/ @elastic/kibana-security /x-pack/test/pki_api_integration/ @elastic/kibana-security -/x-pack/test/saml_api_integration/ @elastic/kibana-security /x-pack/test/security_api_integration/ @elastic/kibana-security /x-pack/test/security_functional/ @elastic/kibana-security /x-pack/test/spaces_api_integration/ @elastic/kibana-security /x-pack/test/token_api_integration/ @elastic/kibana-security +#CC# /src/legacy/ui/public/capabilities @elastic/kibana-security +#CC# /x-pack/legacy/plugins/encrypted_saved_objects/ @elastic/kibana-security +#CC# /x-pack/plugins/security_solution/ @elastic/kibana-security +#CC# /x-pack/plugins/security/ @elastic/kibana-security +#CC# /x-pack/plugins/audit_trail/ @elastic/kibana-security # Kibana Localization /src/dev/i18n/ @elastic/kibana-localization /src/legacy/server/i18n/ @elastic/kibana-localization /src/core/public/i18n/ @elastic/kibana-localization /packages/kbn-i18n/ @elastic/kibana-localization +#CC# /src/legacy/server/i18n/ @elastic/kibana-localization +#CC# /x-pack/plugins/translations/ @elastic/kibana-localization # Kibana Telemetry /packages/kbn-analytics/ @elastic/kibana-telemetry @@ -213,33 +313,23 @@ x-pack/plugins/telemetry_collection_xpack/schema/xpack_plugins.json @elastic/kib /x-pack/plugins/triggers_actions_ui/ @elastic/kibana-alerting-services /x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/ @elastic/kibana-alerting-services /x-pack/test/functional_with_es_ssl/fixtures/plugins/alerts/ @elastic/kibana-alerting-services +#CC# /x-pack/legacy/plugins/actions/ @elastic/kibana-alerting-services +#CC# /x-pack/legacy/plugins/alerting/ @elastic/kibana-alerting-services +#CC# /x-pack/legacy/plugins/task_manager @elastic/kibana-alerting-services +#CC# /x-pack/legacy/plugins/triggers_actions_ui/ @elastic/kibana-alerting-services +#CC# /x-pack/plugins/stack_alerts @elastic/kibana-alerting-services # Enterprise Search # Shared /x-pack/plugins/enterprise_search/ @elastic/enterprise-search-frontend /x-pack/test/functional_enterprise_search/ @elastic/enterprise-search-frontend -# App Search -/x-pack/plugins/enterprise_search/public/applications/app_search @elastic/app-search-frontend -/x-pack/plugins/enterprise_search/server/routes/app_search @elastic/app-search-frontend -/x-pack/plugins/enterprise_search/server/collectors/app_search @elastic/app-search-frontend -/x-pack/plugins/enterprise_search/server/saved_objects/app_search @elastic/app-search-frontend -# Workplace Search -/x-pack/plugins/enterprise_search/public/applications/workplace_search @elastic/workplace-search-frontend -/x-pack/plugins/enterprise_search/server/routes/workplace_search @elastic/workplace-search-frontend -/x-pack/plugins/enterprise_search/server/collectors/workplace_search @elastic/workplace-search-frontend -/x-pack/plugins/enterprise_search/server/saved_objects/workplace_search @elastic/workplace-search-frontend # Elasticsearch UI /src/plugins/dev_tools/ @elastic/es-ui /src/plugins/console/ @elastic/es-ui /src/plugins/es_ui_shared/ @elastic/es-ui -/x-pack/legacy/plugins/cross_cluster_replication/ @elastic/es-ui +/x-pack/plugins/cross_cluster_replication/ @elastic/es-ui /x-pack/plugins/index_lifecycle_management/ @elastic/es-ui -/x-pack/legacy/plugins/index_management/ @elastic/es-ui -/x-pack/legacy/plugins/license_management/ @elastic/es-ui -/x-pack/legacy/plugins/rollup/ @elastic/es-ui -/x-pack/legacy/plugins/snapshot_restore/ @elastic/es-ui -/x-pack/legacy/plugins/upgrade_assistant/ @elastic/es-ui /x-pack/plugins/console_extensions/ @elastic/es-ui /x-pack/plugins/es_ui_shared/ @elastic/es-ui /x-pack/plugins/grokdebugger/ @elastic/es-ui @@ -253,6 +343,16 @@ x-pack/plugins/telemetry_collection_xpack/schema/xpack_plugins.json @elastic/kib /x-pack/plugins/upgrade_assistant/ @elastic/es-ui /x-pack/plugins/watcher/ @elastic/es-ui /x-pack/plugins/ingest_pipelines/ @elastic/es-ui +/packages/kbn-ace/ @elastic/es-ui +/packages/kbn-monaco/ @elastic/es-ui +#CC# /src/legacy/core_plugins/kibana/public/dev_tools/ @elastic/es-ui +#CC# /src/legacy/core_plugins/console_legacy @elastic/es-ui +#CC# /x-pack/legacy/plugins/rollup/ @elastic/es-ui +#CC# /x-pack/legacy/server/lib/create_router/ @elastic/es-ui +#CC# /x-pack/legacy/server/lib/check_license/ @elastic/es-ui +#CC# /x-pack/plugins/console_extensions/ @elastic/es-ui +#CC# /x-pack/plugins/cross_cluster_replication/ @elastic/es-ui +#CC# /x-pack/plugins/es_ui_shared/ @elastic/es-u # Endpoint /x-pack/plugins/endpoint/ @elastic/endpoint-app-team @elastic/siem @@ -262,6 +362,9 @@ x-pack/plugins/telemetry_collection_xpack/schema/xpack_plugins.json @elastic/kib /x-pack/test/functional/es_archives/endpoint/ @elastic/endpoint-app-team @elastic/siem /x-pack/test/plugin_functional/plugins/resolver_test/ @elastic/endpoint-app-team @elastic/siem /x-pack/test/plugin_functional/test_suites/resolver/ @elastic/endpoint-app-team @elastic/siem +#CC# /x-pack/legacy/plugins/siem/ @elastic/siem +#CC# /x-pack/plugins/siem/ @elastic/siem +#CC# /x-pack/plugins/security_solution/ @elastic/siem # Security Solution /x-pack/plugins/security_solution/ @elastic/siem @elastic/endpoint-app-team @@ -276,6 +379,7 @@ x-pack/plugins/telemetry_collection_xpack/schema/xpack_plugins.json @elastic/kib # Design (at the bottom for specificity of SASS files) **/*.scss @elastic/kibana-design +#CC# /packages/kbn-ui-framework/ @elastic/kibana-design # Core design /src/plugins/dashboard/**/*.scss @elastic/kibana-core-ui-designers @@ -297,3 +401,9 @@ x-pack/plugins/telemetry_collection_xpack/schema/xpack_plugins.json @elastic/kib /x-pack/plugins/endpoint/**/*.scss @elastic/security-design /x-pack/plugins/security_solution/**/*.scss @elastic/security-design +# Logstash +#CC# /x-pack/plugins/logstash/ @elastic/logstash + +# Reporting +#CC# /x-pack/plugins/reporting/ @elastic/kibana-reporting-services + diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 534b1cea6242f..c366819c49dde 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -9,8 +9,9 @@ Delete any items that are not applicable to this PR. - [ ] Any text added follows [EUI's writing guidelines](https://elastic.github.io/eui/#/guidelines/writing), uses sentence case text and includes [i18n support](https://github.com/elastic/kibana/blob/master/packages/kbn-i18n/README.md) - [ ] [Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html) was added for features that require explanation or tutorials - [ ] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios -- [ ] This was checked for [keyboard-only and screenreader accessibility](https://developer.mozilla.org/en-US/docs/Learn/Tools_and_testing/Cross_browser_testing/Accessibility#Accessibility_testing_checklist) -- [ ] This renders correctly on smaller devices using a responsive layout. (You can test this [in your browser](https://www.browserstack.com/guide/responsive-testing-on-local-server) +- [ ] Any UI touched in this PR is usable by keyboard only (learn more about [keyboard accessibility](https://webaim.org/techniques/keyboard/)) +- [ ] Any UI touched in this PR does not create any new axe failures (run axe in browser: [FF](https://addons.mozilla.org/en-US/firefox/addon/axe-devtools/), [Chrome](https://chrome.google.com/webstore/detail/axe-web-accessibility-tes/lhdoppojpmngadmnindnejefpokejbdd?hl=en-US)) +- [ ] This renders correctly on smaller devices using a responsive layout. (You can test this [in your browser](https://www.browserstack.com/guide/responsive-testing-on-local-server)) - [ ] This was checked for [cross-browser compatibility](https://www.elastic.co/support/matrix#matrix_browsers) ### For maintainers diff --git a/.i18nrc.json b/.i18nrc.json index 153a5a6cafece..e0281b0a5bc21 100644 --- a/.i18nrc.json +++ b/.i18nrc.json @@ -29,6 +29,7 @@ "indexPatternManagement": "src/plugins/index_pattern_management", "advancedSettings": "src/plugins/advanced_settings", "kibana_legacy": "src/plugins/kibana_legacy", + "kibanaOverview": "src/plugins/kibana_overview", "kibana_react": "src/legacy/core_plugins/kibana_react", "kibana-react": "src/plugins/kibana_react", "kibana_utils": "src/plugins/kibana_utils", @@ -37,6 +38,7 @@ "regionMap": "src/plugins/region_map", "savedObjects": "src/plugins/saved_objects", "savedObjectsManagement": "src/plugins/saved_objects_management", + "security": "src/plugins/security_oss", "server": "src/legacy/server", "statusPage": "src/legacy/core_plugins/status_page", "telemetry": [ diff --git a/.telemetryrc.json b/.telemetryrc.json index 818f9805628e1..3d1b0df1d8f93 100644 --- a/.telemetryrc.json +++ b/.telemetryrc.json @@ -5,11 +5,7 @@ "exclude": [ "src/plugins/kibana_react/", "src/plugins/testbed/", - "src/plugins/kibana_utils/", - "src/plugins/kibana_usage_collection/server/collectors/kibana/kibana_usage_collector.ts", - "src/plugins/kibana_usage_collection/server/collectors/management/telemetry_management_collector.ts", - "src/plugins/kibana_usage_collection/server/collectors/ui_metric/telemetry_ui_metric_collector.ts", - "src/plugins/telemetry/server/collectors/usage/telemetry_usage_collector.ts" + "src/plugins/kibana_utils/" ] } ] diff --git a/NOTICE.txt b/NOTICE.txt index d689abf4c4e05..24940e232e88f 100644 --- a/NOTICE.txt +++ b/NOTICE.txt @@ -118,6 +118,212 @@ THE SOFTWARE. This product uses Noto fonts that are licensed under the SIL Open Font License, Version 1.1. +--- +We include the `firstValueFrom()` and `lastValueFrom()` helpers +extracted from the v7-beta.7 version of the RxJS library. + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + +Copyright (c) 2015-2018 Google, Inc., Netflix, Inc., Microsoft Corp. and contributors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + --- Based on the scroll-into-view-if-necessary module from npm https://github.com/stipsan/compute-scroll-into-view/blob/master/src/index.ts#L269-L340 @@ -208,6 +414,30 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +--- +MIT License + +Copyright (c) 2014-present Sebastian McKenzie and other contributors + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + --- This product bundles bootstrap@3.3.6 which is available under a "MIT" license. diff --git a/config/kibana.yml b/config/kibana.yml index 72e0764f849a0..58ae8b9346f51 100644 --- a/config/kibana.yml +++ b/config/kibana.yml @@ -27,11 +27,6 @@ # The URLs of the Elasticsearch instances to use for all your queries. #elasticsearch.hosts: ["http://localhost:9200"] -# When this setting's value is true Kibana uses the hostname specified in the server.host -# setting. When the value of this setting is false, Kibana uses the hostname of the host -# that connects to this Kibana instance. -#elasticsearch.preserveHost: true - # Kibana uses an index in Elasticsearch to store saved searches, visualizations and # dashboards. Kibana creates a new index if the index doesn't already exist. #kibana.index: ".kibana" @@ -81,9 +76,6 @@ # Time in milliseconds for Elasticsearch to wait for responses from shards. Set to 0 to disable. #elasticsearch.shardTimeout: 30000 -# Time in milliseconds to wait for Elasticsearch at Kibana startup before retrying. -#elasticsearch.startupTimeout: 5000 - # Logs queries sent to Elasticsearch. Requires logging.verbose set to true. #elasticsearch.logQueries: false diff --git a/docs/api/saved-objects/bulk_create.asciidoc b/docs/api/saved-objects/bulk_create.asciidoc index 4f572b49ee5ff..267ab3891d700 100644 --- a/docs/api/saved-objects/bulk_create.asciidoc +++ b/docs/api/saved-objects/bulk_create.asciidoc @@ -41,6 +41,11 @@ experimental[] Create multiple {kib} saved objects. `references`:: (Optional, array) Objects with `name`, `id`, and `type` properties that describe the other saved objects in the referenced object. To refer to the other saved object, use `name` in the attributes. Never use `id` to refer to the other saved object. `id` can be automatically updated during migrations, import, or export. +`initialNamespaces`:: + (Optional, string array) Identifiers for the <> in which this object is created. If this is provided, the + object is created only in the explicitly defined spaces. If this is not provided, the object is created in the current space + (default behavior). + `version`:: (Optional, number) Specifies the version. diff --git a/docs/api/saved-objects/create.asciidoc b/docs/api/saved-objects/create.asciidoc index 900f87ec29d8a..50809a1bd5d4e 100644 --- a/docs/api/saved-objects/create.asciidoc +++ b/docs/api/saved-objects/create.asciidoc @@ -13,7 +13,7 @@ experimental[] Create {kib} saved objects. `POST :/api/saved_objects//` -`POST :/s//api/saved_objects/` +`POST :/s//saved_objects/` [[saved-objects-api-create-path-params]] ==== Path parameters @@ -46,6 +46,11 @@ any data that you send to the API is properly formed. `references`:: (Optional, array) Objects with `name`, `id`, and `type` properties that describe the other saved objects that this object references. Use `name` in attributes to refer to the other saved object, but never the `id`, which can update automatically during migrations or import/export. +`initialNamespaces`:: + (Optional, string array) Identifiers for the <> in which this object is created. If this is provided, the + object is created only in the explicitly defined spaces. If this is not provided, the object is created in the current space + (default behavior). + [[saved-objects-api-create-request-codes]] ==== Response code diff --git a/docs/api/saved-objects/delete.asciidoc b/docs/api/saved-objects/delete.asciidoc index af587b0e7af10..9c342cb4d843e 100644 --- a/docs/api/saved-objects/delete.asciidoc +++ b/docs/api/saved-objects/delete.asciidoc @@ -27,6 +27,14 @@ WARNING: Once you delete a saved object, _it cannot be recovered_. `id`:: (Required, string) The object ID that you want to remove. +[[saved-objects-api-delete-query-params]] +==== Query parameters + +`force`:: + (Optional, boolean) When true, forces an object to be deleted if it exists in multiple namespaces. ++ +TIP: Use this if you attempted to delete an object and received an HTTP 400 error with the following message: _"Unable to delete saved object that exists in multiple namespaces, use the `force` option to delete it anyway"_ + [[saved-objects-api-delete-response-codes]] ==== Response code diff --git a/docs/apm/service-maps.asciidoc b/docs/apm/service-maps.asciidoc index db2f85c54c762..d629a95073a74 100644 --- a/docs/apm/service-maps.asciidoc +++ b/docs/apm/service-maps.asciidoc @@ -2,11 +2,6 @@ [[service-maps]] === Service maps -beta::[] - -WARNING: Service map support for Internet Explorer 11 is extremely limited. -Please use Chrome or Firefox if available. - A service map is a real-time visual representation of the instrumented services in your application's architecture. It shows you how these services are connected, along with high-level metrics like average transaction duration, requests per minute, and errors per minute. diff --git a/docs/canvas/canvas-edit-workpads.asciidoc b/docs/canvas/canvas-edit-workpads.asciidoc index 6558def8a7474..6ad2d89be4a42 100644 --- a/docs/canvas/canvas-edit-workpads.asciidoc +++ b/docs/canvas/canvas-edit-workpads.asciidoc @@ -25,12 +25,12 @@ For example, to change the index pattern for a set of charts: Specify the variable options. [role="screenshot"] -image::images/specify_variable_syntax.png[Specify the variable syntax] +image::images/specify_variable_syntax.png[Image describing how to specify the variable syntax] Copy the variable, then apply it to each element you want to update in the *Expression editor*. [role="screenshot"] -image::images/copy_variable_syntax.png[Copy the variable syntax] +image::images/copy_variable_syntax.png[Image demonstrating expression editor] [float] [[apply-changes-to-the-entire-workpad]] @@ -85,7 +85,7 @@ To use an element with the same functionality and appearance in multiple places, Select the element, then click *Edit > Clone*. [role="screenshot"] -image::images/clone_element.gif[Clone elements] +image::images/clone_element.gif[Image showing how to clone elements] [float] [[move-and-resize-elements]] diff --git a/docs/canvas/canvas-expression-lifecycle.asciidoc b/docs/canvas/canvas-expression-lifecycle.asciidoc index 895c1382c4d36..7d48c593f9e18 100644 --- a/docs/canvas/canvas-expression-lifecycle.asciidoc +++ b/docs/canvas/canvas-expression-lifecycle.asciidoc @@ -30,7 +30,7 @@ The filtered <> becomes the _context_ of the next functi Let’s look at another expression, which uses the same <> function, but instead produces a pie chart. -image::images/canvas-functions-can-take-arguments-pie-chart.png[Pie Chart, height=400] +image::images/canvas-functions-can-take-arguments-pie-chart.png[Pie chart showing output of demodata function] [source,text] ---- filters @@ -47,7 +47,7 @@ If the expression stopped there, it would produce a `pointseries` data type as t The end result is a simple pie chart that uses the default color palette, but the <> function can take additional arguments that control how it gets rendered. For example, you can provide a `hole` argument to turn your pie chart into a donut chart by changing the expression to: -image::images/canvas-functions-can-take-arguments-donut-chart.png[Donut Chart, height=400] +image::images/canvas-functions-can-take-arguments-donut-chart.png[Alternative output as donut chart] [source,text] ---- filters @@ -83,7 +83,7 @@ You can substitute one function for another to change the output. For example, y Let’s change that last pie chart into a bubble chart by replacing the <> function with the <> function. This is possible because both functions can accept a `pointseries` data type as their _context_. Switching the functions will work, but it won’t produce a useful visualization on its own since you don’t have the x-axis and y-axis defined. You will also need to modify the <> function to change its output. In this case, you can change the `size` argument to `y`, so the maximum price values are plotted on the y-axis, and add an `x` argument using the `@timestamp` field in the data to plot those values over time. This leaves you with the following expression and produces a bubble chart showing the max price of each state over time: -image::images/canvas-change-your-expression-chart.png[Bubble Chart, height=400] +image::images/canvas-change-your-expression-chart.png[Bubble Chart, with price along x axis, and time along y axis] [source,text] ---- filters @@ -95,7 +95,7 @@ filters Similar to the <> function, the <> function takes arguments that control the design elements of the visualization. As one example, passing a `legend` argument with a value of `false` to the function will hide the legend on the chart. -image::images/canvas-change-your-expression-chart-no-legend.png[Bubble Chart Without Legend, height=400] +image::images/canvas-change-your-expression-chart-no-legend.png[Bubble Chart Without Legend] [source,text,subs=+quotes] ---- filters diff --git a/docs/canvas/canvas-present-workpad.asciidoc b/docs/canvas/canvas-present-workpad.asciidoc index a6d801b74fce1..b1492f57e46f8 100644 --- a/docs/canvas/canvas-present-workpad.asciidoc +++ b/docs/canvas/canvas-present-workpad.asciidoc @@ -18,7 +18,7 @@ image::images/canvas-autoplay-interval.png[Element autoplay interval] . To start your presentation, click *View > Enter fullscreen mode*. + [role="screenshot"] -image::images/canvas-fullscreen.png[Fullscreen mode] +image::images/canvas-fullscreen.png[Image showing how to enter fullscreen mode from view dropdown] . When you are ready to exit fullscreen mode, press the Esc (Escape) key. @@ -33,7 +33,7 @@ To get a closer look at a portion of your workpad, use the zoom options. . Select the zoom option. + [role="screenshot"] -image::images/canvas-zoom-controls.png[Zoom controls] +image::images/canvas-zoom-controls.png[Zoom controls, also in view dropdown] [float] [[configure-auto-refresh-interval]] diff --git a/docs/canvas/canvas-share-workpad.asciidoc b/docs/canvas/canvas-share-workpad.asciidoc index f6cd2d93a9372..f49e2a944c900 100644 --- a/docs/canvas/canvas-share-workpad.asciidoc +++ b/docs/canvas/canvas-share-workpad.asciidoc @@ -10,10 +10,10 @@ When you've finished your workpad, you can share it outside of {kib}. Create a JSON file of your workpad that you can export outside of {kib}. -Click *Share > Download as JSON*. +To begin, click *Share > Download as JSON*. [role="screenshot"] -image::images/canvas-export-workpad.png[Export single workpad] +image::images/canvas-export-workpad.png[Export single workpad through JSON, from Share dropdown] Want to export multiple workpads? Go to the *Canvas* home page, select the workpads you want to export, then click *Export*. @@ -23,10 +23,10 @@ Want to export multiple workpads? Go to the *Canvas* home page, select the workp If you have a subscription that supports the {report-features}, you can create a PDF copy of your workpad that you can save and share outside {kib}. -Click *Share > PDF reports > Generate PDF*. +To begin, click *Share > PDF reports > Generate PDF*. [role="screenshot"] -image::images/canvas-generate-pdf.gif[Generate PDF] +image::images/canvas-generate-pdf.gif[Image showing how to generate a PDF] For more information, refer to <>. @@ -36,10 +36,10 @@ For more information, refer to <> or a script. -Click *Share > PDF reports > Copy POST URL*. +To begin, click *Share > PDF reports > Copy POST URL*. [role="screenshot"] -image::images/canvas-create-URL.gif[Create POST URL] +image::images/canvas-create-URL.gif[Image showing how to create POST URL] For more information, refer to <>. @@ -58,7 +58,7 @@ beta[] Canvas allows you to create _shareables_, which are workpads that you dow To make sure that your data remains secure, the data in the JSON file is not connected to {kib}. Canvas does not display elements that manipulate the data on the workpad. + [role="screenshot"] -image::canvas/images/canvas-embed_workpad.gif[Share the workpad on a website] +image::canvas/images/canvas-embed_workpad.gif[Image showing how to share the workpad on a website] + NOTE: Shareable workpads encode the current state of the workpad in a JSON file. When you make changes to the workpad, the changes do not appear in the shareable workpad on your website. diff --git a/docs/canvas/canvas-tutorial.asciidoc b/docs/canvas/canvas-tutorial.asciidoc index a861b30db784f..312391541a777 100644 --- a/docs/canvas/canvas-tutorial.asciidoc +++ b/docs/canvas/canvas-tutorial.asciidoc @@ -2,7 +2,7 @@ [[canvas-tutorial]] == Tutorial: Create a workpad for monitoring sales -To get up and running with Canvas, use the following tutorial where you'll create a workpad for monitoring sales at an eCommerce store. +To get up and running with Canvas, add the Sample eCommerce orders data, then use the data to create a workpad for monitoring sales at an eCommerce store. [float] === Before you begin @@ -30,7 +30,7 @@ The default Elastic logo image appears on the page. . To replace the Elastic logo with your own image, select the image, then use the editor. [role="screenshot"] -image::images/canvas-image-element.png[] +image::images/canvas-image-element.png[Image showing how to add the image element] [float] === Customize your data with metrics @@ -70,7 +70,7 @@ You're now looking at the raw data syntax that Canvas uses to display the elemen .. Click *Run*. [role="screenshot"] -image::images/canvas-metric-element.png[] +image::images/canvas-metric-element.png[Image showing changes to the Canvas workpad] [float] === Show off your data with charts @@ -96,7 +96,7 @@ To show what your data can do, add charts, graphs, progress monitors, and more t .. From the *Y-axis* drop-down lists, select *Value*, then select *taxless_total_price*. [role="screenshot"] -image::images/canvas-chart-element.png[] +image::images/canvas-chart-element.png[Image showing Canvas workpad with sample data graph] [float] === Show how your data changes over time @@ -110,22 +110,20 @@ To focus your data on a specific time range, add the time filter. . To use the date time field from the sample data, enter `order_date` in the *Column* field, then click *Set*. [role="screenshot"] -image::images/canvas-timefilter-element.png[] +image::images/canvas-timefilter-element.png[Image showing Canvas workpad with filtered sample data graph] To see how the data changes, set the time filter to *Last 7 days*. As you change the time filter options, the elements automatically update. -Your workpad is now complete! +Your workpad is complete! [float] -=== Next steps +=== What's next? Now that you know the Canvas basics, you're ready to explore on your own. Here are some things to try: * Play with the {kibana-ref}/add-sample-data.html[sample Canvas workpads]. -* Build presentations of your own live data with <>. - -* Learn more about <> — the building blocks of your workpad. +* Build presentations of your own data with <>. * Deep dive into the {kibana-ref}/canvas-function-reference.html[expression language and functions] that drive Canvas. diff --git a/docs/canvas/images/canvas-autoplay-interval.png b/docs/canvas/images/canvas-autoplay-interval.png index 68a7ca248d9ee..a7b1251efc808 100644 Binary files a/docs/canvas/images/canvas-autoplay-interval.png and b/docs/canvas/images/canvas-autoplay-interval.png differ diff --git a/docs/canvas/images/canvas-gs-example.png b/docs/canvas/images/canvas-gs-example.png index 90beccd322aa4..a9b960342709f 100644 Binary files a/docs/canvas/images/canvas-gs-example.png and b/docs/canvas/images/canvas-gs-example.png differ diff --git a/docs/canvas/images/canvas-refresh-interval.png b/docs/canvas/images/canvas-refresh-interval.png index 62e88ad4bf7d0..c097d950a7ec7 100644 Binary files a/docs/canvas/images/canvas-refresh-interval.png and b/docs/canvas/images/canvas-refresh-interval.png differ diff --git a/docs/canvas/images/canvas-zoom-controls.png b/docs/canvas/images/canvas-zoom-controls.png index 5c72d118041e4..1407ca3cd8627 100644 Binary files a/docs/canvas/images/canvas-zoom-controls.png and b/docs/canvas/images/canvas-zoom-controls.png differ diff --git a/docs/developer/advanced/development-basepath.asciidoc b/docs/developer/advanced/development-basepath.asciidoc index cb341b9591174..30086288de834 100644 --- a/docs/developer/advanced/development-basepath.asciidoc +++ b/docs/developer/advanced/development-basepath.asciidoc @@ -7,11 +7,11 @@ You can set this explicitly using `server.basePath` in <>. Use the server.rewriteBasePath setting to tell {kib} if it should remove the basePath from requests it receives, and to prevent a deprecation warning at startup. This setting cannot end in a slash (/). -If you want to turn off the basepath when in development mode, start {kib} with the `--no-basepath` flag +If you want to turn off the basepath when in development mode, start {kib} with the `--no-base-path` flag [source,bash] ---- -yarn start --no-basepath +yarn start --no-base-path ---- diff --git a/docs/developer/architecture/code-exploration.asciidoc b/docs/developer/architecture/code-exploration.asciidoc deleted file mode 100644 index 4a390336da34f..0000000000000 --- a/docs/developer/architecture/code-exploration.asciidoc +++ /dev/null @@ -1,598 +0,0 @@ -//// - -NOTE: - This is an automatically generated file. Please do not edit directly. Instead, run the - following from within the kibana repository: - - node scripts/build_plugin_list_docs - - You can update the template within packages/kbn-dev-utils/target/plugin_list/generate_plugin_list.js - -//// - -[[code-exploration]] -== Exploring Kibana code - -The goals of our folder heirarchy are: - -- Easy for developers to know where to add new services, plugins and applications. -- Easy for developers to know where to find the code from services, plugins and applications. -- Easy to browse and understand our folder structure. - -To that aim, we strive to: - -- Avoid too many files in any given folder. -- Choose clear, unambigious folder names. -- Organize by domain. -- Every folder should contain a README that describes the contents of that folder. - -[discrete] -[[kibana-services-applications]] -=== Services and Applications - -[discrete] -==== src/plugins - -- {kib-repo}blob/{branch}/src/plugins/advanced_settings[advancedSettings] - -WARNING: Missing README. - - -- {kib-repo}blob/{branch}/src/plugins/apm_oss[apmOss] - -WARNING: Missing README. - - -- {kib-repo}blob/{branch}/src/plugins/bfetch/README.md[bfetch] - -bfetch allows to batch HTTP requests and streams responses back. - - -- {kib-repo}blob/{branch}/src/plugins/charts/README.md[charts] - -The Charts plugin is a way to create easier integration of shared colors, themes, types and other utilities across all Kibana charts and visualizations. - - -- {kib-repo}blob/{branch}/src/plugins/console[console] - -WARNING: Missing README. - - -- {kib-repo}blob/{branch}/src/plugins/dashboard/README.md[dashboard] - -Contains the dashboard application. - - -- {kib-repo}blob/{branch}/src/plugins/data/README.md[data] - -data plugin provides common data access services. - - -- {kib-repo}blob/{branch}/src/plugins/dev_tools/README.md[devTools] - -The ui/registry/dev_tools is removed in favor of the devTools plugin which exposes a register method in the setup contract. -Registering app works mostly the same as registering apps in core.application.register. -Routing will be handled by the id of the dev tool - your dev tool will be mounted when the URL matches /app/dev_tools#/. -This API doesn't support angular, for registering angular dev tools, bootstrap a local module on mount into the given HTML element. - - -- {kib-repo}blob/{branch}/src/plugins/discover/README.md[discover] - -Contains the Discover application and the saved search embeddable. - - -- {kib-repo}blob/{branch}/src/plugins/embeddable/README.md[embeddable] - -Embeddables are re-usable widgets that can be rendered in any environment or plugin. Developers can embed them directly in their plugin. End users can dynamically add them to any embeddable containers. - - -- {kib-repo}blob/{branch}/src/plugins/es_ui_shared/README.md[esUiShared] - -This plugin contains reusable code in the form of self-contained modules (or libraries). Each of these modules exports a set of functionality relevant to the domain of the module. - - -- {kib-repo}blob/{branch}/src/plugins/expressions/README.md[expressions] - -This plugin provides methods which will parse & execute an expression pipeline -string for you, as well as a series of registries for advanced users who might -want to incorporate their own functions, types, and renderers into the service -for use in their own application. - - -- {kib-repo}blob/{branch}/src/plugins/home/README.md[home] - -Moves the legacy ui/registry/feature_catalogue module for registering "features" that should be shown in the home page's feature catalogue to a service within a "home" plugin. The feature catalogue refered to here should not be confused with the "feature" plugin for registering features used to derive UI capabilities for feature controls. - - -- {kib-repo}blob/{branch}/src/plugins/index_pattern_management[indexPatternManagement] - -WARNING: Missing README. - - -- {kib-repo}blob/{branch}/src/plugins/input_control_vis/README.md[inputControlVis] - -Contains the input control visualization allowing to place custom filter controls on a dashboard. - - -- {kib-repo}blob/{branch}/src/plugins/inspector/README.md[inspector] - -The inspector is a contextual tool to gain insights into different elements -in Kibana, e.g. visualizations. It has the form of a flyout panel. - - -- {kib-repo}blob/{branch}/src/plugins/kibana_legacy/README.md[kibanaLegacy] - -This plugin will contain several helpers and services to integrate pieces of the legacy Kibana app with the new Kibana platform. - - -- {kib-repo}blob/{branch}/src/plugins/kibana_react/README.md[kibanaReact] - -Tools for building React applications in Kibana. - - -- {kib-repo}blob/{branch}/src/plugins/kibana_usage_collection/README.md[kibanaUsageCollection] - -This plugin registers the basic usage collectors from Kibana: - - -- {kib-repo}blob/{branch}/src/plugins/kibana_utils/README.md[kibanaUtils] - -Utilities for building Kibana plugins. - - -- {kib-repo}blob/{branch}/src/plugins/legacy_export[legacyExport] - -WARNING: Missing README. - - -- {kib-repo}blob/{branch}/src/plugins/management[management] - -WARNING: Missing README. - - -- {kib-repo}blob/{branch}/src/plugins/maps_legacy[mapsLegacy] - -WARNING: Missing README. - - -- {kib-repo}blob/{branch}/src/plugins/navigation/README.md[navigation] - -The navigation plugins exports the TopNavMenu component. -It also provides a stateful version of it on the start contract. - - -- {kib-repo}blob/{branch}/src/plugins/newsfeed[newsfeed] - -WARNING: Missing README. - - -- {kib-repo}blob/{branch}/src/plugins/region_map[regionMap] - -WARNING: Missing README. - - -- {kib-repo}blob/{branch}/src/plugins/saved_objects[savedObjects] - -WARNING: Missing README. - - -- {kib-repo}blob/{branch}/src/plugins/saved_objects_management[savedObjectsManagement] - -WARNING: Missing README. - - -- {kib-repo}blob/{branch}/src/plugins/share/README.md[share] - -Replaces the legacy ui/share module for registering share context menus. - - -- {kib-repo}blob/{branch}/src/plugins/telemetry/README.md[telemetry] - -Telemetry allows Kibana features to have usage tracked in the wild. The general term "telemetry" refers to multiple things: - - -- {kib-repo}blob/{branch}/src/plugins/telemetry_collection_manager/README.md[telemetryCollectionManager] - -Telemetry's collection manager to go through all the telemetry sources when fetching it before reporting. - - -- {kib-repo}blob/{branch}/src/plugins/telemetry_management_section/README.md[telemetryManagementSection] - -This plugin adds the Advanced Settings section for the Usage Data collection (aka Telemetry). - - -- {kib-repo}blob/{branch}/src/plugins/tile_map[tileMap] - -WARNING: Missing README. - - -- {kib-repo}blob/{branch}/src/plugins/timelion/README.md[timelion] - -Contains the deprecated timelion application. For the timelion visualization, -which also contains the timelion APIs and backend, look at the vis_type_timelion plugin. - - -- {kib-repo}blob/{branch}/src/plugins/ui_actions/README.md[uiActions] - -An API for: - - -- {kib-repo}blob/{branch}/src/plugins/usage_collection/README.md[usageCollection] - -Usage Collection allows collecting usage data for other services to consume (telemetry and monitoring). -To integrate with the telemetry services for usage collection of your feature, there are 2 steps: - - -- {kib-repo}blob/{branch}/src/plugins/vis_type_markdown/README.md[visTypeMarkdown] - -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_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_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_vega/README.md[visTypeVega] - -Contains the Vega visualization. - - -- {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_xy/README.md[visTypeXy] - -Contains the new xy-axis chart using the elastic-charts library, which will eventually -replace the vislib xy-axis (bar, area, line) charts. - - -- {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/visualize/README.md[visualize] - -Contains the visualize application which includes the listing page and the app frame, -which will load the visualization's editor. - - -[discrete] -==== x-pack/plugins - -- {kib-repo}blob/{branch}/x-pack/plugins/actions/README.md[actions] - -The Kibana actions plugin provides a framework to create executable actions. You can: - - -- {kib-repo}blob/{branch}/x-pack/plugins/alerting_builtins/README.md[alertingBuiltins] - -This plugin provides alertTypes shipped with Kibana for use with the -the alerts plugin. When enabled, it will register -the built-in alertTypes with the alerting plugin, register associated HTTP -routes, etc. - - -- {kib-repo}blob/{branch}/x-pack/plugins/alerts/README.md[alerts] - -The Kibana alerting plugin provides a common place to set up alerts. You can: - - -- {kib-repo}blob/{branch}/x-pack/plugins/apm/readme.md[apm] - -To access an elasticsearch instance that has live data you have two options: - - -- {kib-repo}blob/{branch}/x-pack/plugins/audit_trail[auditTrail] - -WARNING: Missing README. - - -- {kib-repo}blob/{branch}/x-pack/plugins/beats_management/readme.md[beatsManagement] - -Notes: -Failure to have auth enabled in Kibana will make for a broken UI. UI-based errors not yet in place - - -- {kib-repo}blob/{branch}/x-pack/plugins/canvas/README.md[canvas] - -"Never look back. The past is done. The future is a blank canvas." ― Suzy Kassem, Rise Up and Salute the Sun - - -- {kib-repo}blob/{branch}/x-pack/plugins/case/README.md[case] - -Experimental Feature - - -- {kib-repo}blob/{branch}/x-pack/plugins/cloud[cloud] - -WARNING: Missing README. - - -- {kib-repo}blob/{branch}/x-pack/plugins/code[code] - -WARNING: Missing README. - - -- {kib-repo}blob/{branch}/x-pack/plugins/console_extensions[consoleExtensions] - -WARNING: Missing README. - - -- {kib-repo}blob/{branch}/x-pack/plugins/cross_cluster_replication/README.md[crossClusterReplication] - -You can run a local cluster and simulate a remote cluster within a single Kibana directory. - - -- {kib-repo}blob/{branch}/x-pack/plugins/dashboard_enhanced/README.md[dashboardEnhanced] - -Contains the enhancements to the OSS dashboard app. - - -- {kib-repo}blob/{branch}/x-pack/plugins/dashboard_mode/README.md[dashboardMode] - -The deprecated dashboard only mode. - - -- {kib-repo}blob/{branch}/x-pack/plugins/data_enhanced[dataEnhanced] - -WARNING: Missing README. - - -- {kib-repo}blob/{branch}/x-pack/plugins/discover_enhanced/README.md[discoverEnhanced] - -Contains the enhancements to the OSS discover app. - - -- {kib-repo}blob/{branch}/x-pack/plugins/embeddable_enhanced[embeddableEnhanced] - -WARNING: Missing README. - - -- {kib-repo}blob/{branch}/x-pack/plugins/encrypted_saved_objects/README.md[encryptedSavedObjects] - -The purpose of this plugin is to provide a way to encrypt/decrypt attributes on the custom Saved Objects that works with -security and spaces filtering as well as performing audit logging. - - -- {kib-repo}blob/{branch}/x-pack/plugins/enterprise_search/README.md[enterpriseSearch] - -This plugin's goal is to provide a Kibana user interface to the Enterprise Search solution's products (App Search and Workplace Search). In it's current MVP state, the plugin provides the following with the goal of gathering user feedback and raising product awareness: - - -- {kib-repo}blob/{branch}/x-pack/plugins/event_log/README.md[eventLog] - -The purpose of this plugin is to provide a way to persist a history of events -occuring in Kibana, initially just for the Make It Action project - alerts -and actions. - - -- {kib-repo}blob/{branch}/x-pack/plugins/features[features] - -WARNING: Missing README. - - -- {kib-repo}blob/{branch}/x-pack/plugins/file_upload[fileUpload] - -WARNING: Missing README. - - -- {kib-repo}blob/{branch}/x-pack/plugins/global_search/README.md[globalSearch] - -The GlobalSearch plugin provides an easy way to search for various objects, such as applications -or dashboards from the Kibana instance, from both server and client-side plugins - - -- {kib-repo}blob/{branch}/x-pack/plugins/global_search_bar/README.md[globalSearchBar] - -The GlobalSearchBar plugin provides a search interface for navigating Kibana. (It is the UI to the GlobalSearch plugin.) - - -- {kib-repo}blob/{branch}/x-pack/plugins/global_search_providers[globalSearchProviders] - -WARNING: Missing README. - - -- {kib-repo}blob/{branch}/x-pack/plugins/graph/README.md[graph] - -This is the main source folder of the Graph plugin. It contains all of the Kibana server and client source code. x-pack/test/functional/apps/graph contains additional functional tests. - - -- {kib-repo}blob/{branch}/x-pack/plugins/grokdebugger/README.md[grokdebugger] - -- {kib-repo}blob/{branch}/x-pack/plugins/index_lifecycle_management/README.md[indexLifecycleManagement] - -You can test that the Frozen badge, phase filtering, and lifecycle information is surfaced in -Index Management by running this series of requests in Console: - - -- {kib-repo}blob/{branch}/x-pack/plugins/index_management[indexManagement] - -WARNING: Missing README. - - -- {kib-repo}blob/{branch}/x-pack/plugins/infra/README.md[infra] - -This is the home of the infra plugin, which aims to provide a solution for -the infrastructure monitoring use-case within Kibana. - - -- {kib-repo}blob/{branch}/x-pack/plugins/ingest_manager/README.md[ingestManager] - -Fleet needs to have Elasticsearch API keys enabled, and also to have TLS enabled on kibana, (if you want to run Kibana without TLS you can provide the following config flag --xpack.ingestManager.fleet.tlsCheckDisabled=false) - - -- {kib-repo}blob/{branch}/x-pack/plugins/ingest_pipelines/README.md[ingestPipelines] - -The ingest_pipelines plugin provides Kibana support for Elasticsearch's ingest nodes. Please refer to the Elasticsearch documentation for more details. - - -- {kib-repo}blob/{branch}/x-pack/plugins/lens/readme.md[lens] - -Run all tests from the x-pack root directory - - -- {kib-repo}blob/{branch}/x-pack/plugins/license_management[licenseManagement] - -WARNING: Missing README. - - -- {kib-repo}blob/{branch}/x-pack/plugins/licensing/README.md[licensing] - -The licensing plugin retrieves license data from Elasticsearch at regular configurable intervals. - - -- {kib-repo}blob/{branch}/x-pack/plugins/lists/README.md[lists] - -README.md for developers working on the backend lists on how to get started -using the CURL scripts in the scripts folder. - - -- {kib-repo}blob/{branch}/x-pack/plugins/logstash[logstash] - -WARNING: Missing README. - - -- {kib-repo}blob/{branch}/x-pack/plugins/maps/README.md[maps] - -Visualize geo data from Elasticsearch or 3rd party geo-services. - - -- {kib-repo}blob/{branch}/x-pack/plugins/maps_legacy_licensing/README.md[mapsLegacyLicensing] - -This plugin provides access to the detailed tile map services from Elastic. - - -- {kib-repo}blob/{branch}/x-pack/plugins/ml[ml] - -WARNING: Missing README. - - -- {kib-repo}blob/{branch}/x-pack/plugins/monitoring[monitoring] - -WARNING: Missing README. - - -- {kib-repo}blob/{branch}/x-pack/plugins/observability/README.md[observability] - -This plugin provides shared components and services for use across observability solutions, as well as the observability landing page UI. - - -- {kib-repo}blob/{branch}/x-pack/plugins/oss_telemetry[ossTelemetry] - -WARNING: Missing README. - - -- {kib-repo}blob/{branch}/x-pack/plugins/painless_lab[painlessLab] - -WARNING: Missing README. - - -- {kib-repo}blob/{branch}/x-pack/plugins/remote_clusters[remoteClusters] - -WARNING: Missing README. - - -- {kib-repo}blob/{branch}/x-pack/plugins/reporting/README.md[reporting] - -An awesome Kibana reporting plugin - - -- {kib-repo}blob/{branch}/x-pack/plugins/rollup/README.md[rollup] - -Welcome to the Kibana rollup plugin! This plugin provides Kibana support for Elasticsearch's rollup feature. Please refer to the Elasticsearch documentation to understand rollup indices and how to create rollup jobs. - - -- {kib-repo}blob/{branch}/x-pack/plugins/searchprofiler[searchprofiler] - -WARNING: Missing README. - - -- {kib-repo}blob/{branch}/x-pack/plugins/security/README.md[security] - -See Configuring security in Kibana. - - -- {kib-repo}blob/{branch}/x-pack/plugins/security_solution/README.md[securitySolution] - -Welcome to the Kibana Security Solution plugin! This README will go over getting started with development and testing. - - -- {kib-repo}blob/{branch}/x-pack/plugins/snapshot_restore/README.md[snapshotRestore] - -or - - -- {kib-repo}blob/{branch}/x-pack/plugins/spaces[spaces] - -WARNING: Missing README. - - -- {kib-repo}blob/{branch}/x-pack/plugins/task_manager[taskManager] - -WARNING: Missing README. - - -- {kib-repo}blob/{branch}/x-pack/plugins/telemetry_collection_xpack/README.md[telemetryCollectionXpack] - -Gathers all usage collection, retrieving them from both: OSS and X-Pack plugins. - - -- {kib-repo}blob/{branch}/x-pack/plugins/transform[transform] - -WARNING: Missing README. - - -- {kib-repo}blob/{branch}/x-pack/plugins/translations[translations] - -WARNING: Missing README. - - -- {kib-repo}blob/{branch}/x-pack/plugins/triggers_actions_ui/README.md[triggers_actions_ui] - -The Kibana alerts and actions UI plugin provides a user interface for managing alerts and actions. -As a developer you can reuse and extend built-in alerts and actions UI functionality: - - -- {kib-repo}blob/{branch}/x-pack/plugins/ui_actions_enhanced/README.md[uiActionsEnhanced] - -- {kib-repo}blob/{branch}/x-pack/plugins/upgrade_assistant[upgradeAssistant] - -WARNING: Missing README. - - -- {kib-repo}blob/{branch}/x-pack/plugins/uptime/README.md[uptime] - -The purpose of this plugin is to provide users of Heartbeat more visibility of what's happening -in their infrastructure. - - -- {kib-repo}blob/{branch}/x-pack/plugins/watcher/README.md[watcher] - -This plugins adopts some conventions in addition to or in place of conventions in Kibana (at the time of the plugin's creation): - diff --git a/docs/developer/architecture/development-plugin-saved-objects.asciidoc b/docs/developer/architecture/development-plugin-saved-objects.asciidoc new file mode 100644 index 0000000000000..0d31f5d90f668 --- /dev/null +++ b/docs/developer/architecture/development-plugin-saved-objects.asciidoc @@ -0,0 +1,311 @@ +[[development-plugin-saved-objects]] +== Using Saved Objects + +Saved Objects allow {kib} plugins to use {es} like a primary +database. Think of it as an Object Document Mapper for {es}. Once a +plugin has registered one or more Saved Object types, the Saved Objects client +can be used to query or perform create, read, update and delete operations on +each type. + +By using Saved Objects your plugin can take advantage of the following +features: + +* Migrations can evolve your document's schema by transforming documents and +ensuring that the field mappings on the index are always up to date. +* a <> is automatically exposed for each type (unless +`hidden=true` is specified). +* a Saved Objects client that can be used from both the server and the browser. +* Users can import or export Saved Objects using the Saved Objects management +UI or the Saved Objects import/export API. +* By declaring `references`, an object's entire reference graph will be +exported. This makes it easy for users to export e.g. a `dashboard` object and +have all the `visualization` objects required to display the dashboard +included in the export. +* When the X-Pack security and spaces plugins are enabled these transparently +provide RBAC access control and the ability to organize Saved Objects into +spaces. + +This document contains developer guidelines and best-practices for plugins +wanting to use Saved Objects. + +=== Registering a Saved Object type +Saved object type definitions should be defined in their own `my_plugin/server/saved_objects` directory. + +The folder should contain a file per type, named after the snake_case name of the type, and an `index.ts` file exporting all the types. + +.src/plugins/my_plugin/server/saved_objects/dashboard_visualization.ts +[source,typescript] +---- +import { SavedObjectsType } from 'src/core/server'; + +export const dashboardVisualization: SavedObjectsType = { + name: 'dashboard_visualization', // <1> + hidden: false, + namespaceType: 'single', + mappings: { + dynamic: false, + properties: { + description: { + type: 'text', + }, + hits: { + type: 'integer', + }, + }, + }, + migrations: { + '1.0.0': migratedashboardVisualizationToV1, + '2.0.0': migratedashboardVisualizationToV2, + }, +}; +---- +<1> Since the name of a Saved Object type forms part of the url path for the +public Saved Objects HTTP API, these should follow our API URL path convention +and always be written as snake case. + +.src/plugins/my_plugin/server/saved_objects/index.ts +[source,typescript] +---- +export { dashboardVisualization } from './dashboard_visualization'; +export { dashboard } from './dashboard'; +---- + +.src/plugins/my_plugin/server/plugin.ts +[source,typescript] +---- +import { dashboard, dashboardVisualization } from './saved_objects'; + +export class MyPlugin implements Plugin { + setup({ savedObjects }) { + savedObjects.registerType(dashboard); + savedObjects.registerType(dashboardVisualization); + } +} +---- + +=== Mappings +Each Saved Object type can define it's own {es} field mappings. +Because multiple Saved Object types can share the same index, mappings defined +by a type will be nested under a top-level field that matches the type name. + +For example, the mappings defined by the `dashboard_visualization` Saved +Object type: + +.src/plugins/my_plugin/server/saved_objects/dashboard_visualization.ts +[source,typescript] +---- +import { SavedObjectsType } from 'src/core/server'; + +export const dashboardVisualization: SavedObjectsType = { + name: 'dashboard_visualization', + ... + mappings: { + properties: { + dynamic: false, + description: { + type: 'text', + }, + hits: { + type: 'integer', + }, + }, + }, + migrations: { ... }, +}; +---- + +Will result in the following mappings being applied to the `.kibana` index: +[source,json] +---- +{ + "mappings": { + "dynamic": "strict", + "properties": { + ... + "dashboard_vizualization": { + "dynamic": false, + "properties": { + "description": { + "type": "text", + }, + "hits": { + "type": "integer", + }, + }, + } + } + } +} +---- + +Do not use field mappings like you would use data types for the columns of a +SQL database. Instead, field mappings are analogous to a SQL index. Only +specify field mappings for the fields you wish to search on or query. By +specifying `dynamic: false` in any level of your mappings, {es} will +accept and store any other fields even if they are not specified in your mappings. + +Since {es} has a default limit of 1000 fields per index, plugins +should carefully consider the fields they add to the mappings. Similarly, +Saved Object types should never use `dynamic: true` as this can cause an +arbitrary amount of fields to be added to the `.kibana` index. + +=== References +When a Saved Object declares `references` to other Saved Objects, the +Saved Objects Export API will automatically export the target object with all +of it's references. This makes it easy for users to export the entire +reference graph of an object. + +If a Saved Object can't be used on it's own, that is, it needs other objects +to exist for a feature to function correctly, that Saved Object should declare +references to all the objects it requires. For example, a `dashboard` +object might have panels for several `visualization` objects. When these +`visualization` objects don't exist, the dashboard cannot be rendered +correctly. The `dashboard` object should declare references to all it's +visualizations. + +However, `visualization` objects can continue to be rendered or embedded into +other dashboards even if the `dashboard` it was originally embedded into +doesn't exist. As a result, `visualization` objects should not declare +references to `dashboard` objects. + +For each referenced object, an `id`, `type` and `name` are added to the +`references` array: + +[source, typescript] +---- +router.get( + { path: '/some-path', validate: false }, + async (context, req, res) => { + const object = await context.core.savedObjects.client.create( + 'dashboard', + { + title: 'my dashboard', + panels: [ + { visualization: 'vis1' }, // <1> + ], + indexPattern: 'indexPattern1' + }, + { references: [ + { id: '...', type: 'visualization', name: 'vis1' }, + { id: '...', type: 'index_pattern', name: 'indexPattern1' }, + ] + } + ) + ... + } +); +---- +<1> Note how `dashboard.panels[0].visualization` stores the `name` property of +the reference (not the `id` directly) to be able to uniquely identify this +reference. This guarantees that the id the reference points to always remains +up to date. If a visualization `id` was directly stored in +`dashboard.panels[0].visualization` there is a risk that this `id` gets +updated without updating the reference in the references array. + +==== Writing Migrations + +Saved Objects support schema changes between Kibana versions, which we call +migrations. Migrations are applied when a Kibana installation is upgraded from +one version to the next, when exports are imported via the Saved Objects +Management UI, or when a new object is created via the HTTP API. + +Each Saved Object type may define migrations for its schema. Migrations are +specified by the Kibana version number, receive an input document, and must +return the fully migrated document to be persisted to Elasticsearch. + +Let's say we want to define two migrations: +- In version 1.1.0, we want to drop the `subtitle` field and append it to the + title +- In version 1.4.0, we want to add a new `id` field to every panel with a newly + generated UUID. + +First, the current `mappings` should always reflect the latest or "target" +schema. Next, we should define a migration function for each step in the schema +evolution: + +src/plugins/my_plugin/server/saved_objects/dashboard_visualization.ts +[source,typescript] +---- +import { SavedObjectsType, SavedObjectMigrationFn } from 'src/core/server'; +import uuid from 'uuid'; + +interface DashboardVisualizationPre110 { + title: string; + subtitle: string; + panels: Array<{}>; +} +interface DashboardVisualization110 { + title: string; + panels: Array<{}>; +} + +interface DashboardVisualization140 { + title: string; + panels: Array<{ id: string }>; +} + +const migrateDashboardVisualization110: SavedObjectMigrationFn< + DashboardVisualizationPre110, // <1> + DashboardVisualization110 +> = (doc) => { + const { subtitle, ...attributesWithoutSubtitle } = doc.attributes; + return { + ...doc, // <2> + attributes: { + ...attributesWithoutSubtitle, + title: `${doc.attributes.title} - ${doc.attributes.subtitle}`, + }, + }; +}; + +const migrateDashboardVisualization140: SavedObjectMigrationFn< + DashboardVisualization110, + DashboardVisualization140 +> = (doc) => { + const outPanels = doc.attributes.panels?.map((panel) => { + return { ...panel, id: uuid.v4() }; + }); + return { + ...doc, + attributes: { + ...doc.attributes, + panels: outPanels, + }, + }; +}; + +export const dashboardVisualization: SavedObjectsType = { + name: 'dashboard_visualization', // <1> + /** ... */ + migrations: { + // Takes a pre 1.1.0 doc, and converts it to 1.1.0 + '1.1.0': migrateDashboardVisualization110, + + // Takes a 1.1.0 doc, and converts it to 1.4.0 + '1.4.0': migrateDashboardVisualization140, // <3> + }, +}; +---- +<1> It is useful to define an interface for each version of the schema. This +allows TypeScript to ensure that you are properly handling the input and output +types correctly as the schema evolves. +<2> Returning a shallow copy is necessary to avoid type errors when using +different types for the input and output shape. +<3> Migrations do not have to be defined for every version. The version number +of a migration must always be the earliest Kibana version in which this +migration was released. So if you are creating a migration which will be +part of the v7.10.0 release, but will also be backported and released as +v7.9.3, the migration version should be: 7.9.3. + +Migrations should be written defensively, an exception in a migration function +will prevent a Kibana upgrade from succeeding and will cause downtime for our +users. Having said that, if a document is encountered that is not in the +expected shape, migrations are encouraged to throw an exception to abort the +upgrade. In most scenarios, it is better to fail an upgrade than to silently +ignore a corrupt document which can cause unexpected behaviour at some future +point in time. + +It is critical that you have extensive tests to ensure that migrations behave +as expected with all possible input documents. Given how simple it is to test +all the branch conditions in a migration function and the high impact of a bug +in this code, there's really no reason not to aim for 100% test code coverage. \ No newline at end of file diff --git a/docs/developer/architecture/index.asciidoc b/docs/developer/architecture/index.asciidoc index ac25fe003df08..dc15b90b69d1a 100644 --- a/docs/developer/architecture/index.asciidoc +++ b/docs/developer/architecture/index.asciidoc @@ -15,12 +15,16 @@ A few services also automatically generate api documentation which can be browse A few notable services are called out below. * <> +* <> * <> * <> +include::security/index.asciidoc[leveloffset=+1] + +include::development-plugin-saved-objects.asciidoc[leveloffset=+1] + include::add-data-tutorials.asciidoc[leveloffset=+1] include::development-visualize-index.asciidoc[leveloffset=+1] -include::security/index.asciidoc[leveloffset=+1] diff --git a/docs/developer/best-practices/index.asciidoc b/docs/developer/best-practices/index.asciidoc index 13ea010d0aa96..42b379e606898 100644 --- a/docs/developer/best-practices/index.asciidoc +++ b/docs/developer/best-practices/index.asciidoc @@ -138,9 +138,12 @@ Review: * <> * <> * <> +* <> include::navigation.asciidoc[leveloffset=+1] include::stability.asciidoc[leveloffset=+1] include::security.asciidoc[leveloffset=+1] + +include::typescript.asciidoc[leveloffset=+1] diff --git a/docs/developer/best-practices/typescript.asciidoc b/docs/developer/best-practices/typescript.asciidoc new file mode 100644 index 0000000000000..3321aae3c0994 --- /dev/null +++ b/docs/developer/best-practices/typescript.asciidoc @@ -0,0 +1,64 @@ +[[typescript]] +== Typescript + +Although this is not a requirement, we encourage if all new code is developed in https://www.typescriptlang.org/[Typescript]. + +[discrete] +=== Project references +Kibana has crossed the 2m LoC mark. The current situation creates some scaling problems when the default out-of-the-box setup stops working. As a result, developers suffer from slow project compilation and IDE unresponsiveness. As a part of https://github.com/elastic/kibana/projects/63[Developer Experience project], we are migrating our tooling to use built-in TypeScript features addressing the scaling problems - https://www.typescriptlang.org/docs/handbook/project-references.html[project references] & https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-4.html#faster-subsequent-builds-with-the---incremental-flag[incremental builds] + +In a nutshell - instead of compiling the whole Kibana codebase at once, this setup enforces splitting the code base into independent projects that form a directed acyclic graph (DAG). This allows the TypeScript compiler (`tsc`) to apply several advanced optimizations: + +- Every project emits `public` interfaces in the form of `d.ts` type declarations generated by the TypeScript compiler +- These generated `d.ts` type declarations are used whenever a referenced project is imported in a depending project +- This makes it possible to determine which project needs rebuilding when the source code has changed to use a more aggressive caching strategy. + +More details are available in the https://www.typescriptlang.org/docs/handbook/project-references.html[official docs] + +[discrete] +==== Caveats +This architecture imposes several limitations to which we must comply: + +- Projects cannot have circular dependencies. Even though the Kibana platform doesn't support circular dependencies between Kibana plugins, TypeScript (and ES6 modules) does allow circular imports between files. So in theory, you may face a problem when migrating to the TS project references and you will have to resolve this circular dependency. +- A project must emit its type declaration. It's not always possible to generate a type declaration if the compiler cannot infer a type. There are two basic cases: + +1. Your plugin exports a type inferring an internal type declared in Kibana codebase. In this case, you'll have to either export an internal type or to declare an exported type explicitly. +2. Your plugin exports something inferring a type from a 3rd party library that doesn't export this type. To fix the problem, you have to declare the exported type manually. + +[discrete] +==== Prerequisites +Since `tsc` doesn't support circular project references, the migration order does matter. You can migrate your plugin only when all the plugin dependencies already have migrated. It creates a situation where commonly used plugins (such as `data` or `kibana_react`) have to migrate first. + +[discrete] +==== Implementation +- Make sure all the plugins listed as dependencies in `kibana.json` file have migrated to TS project references. +- Add `tsconfig.json` in the root folder of your plugin. +[source,json] +---- +{ + "extends": "../../../tsconfig.base.json", + "compilerOptions": { + "composite": true, + "outDir": "./target/types", + "emitDeclarationOnly": true, + "declaration": true, + "declarationMap": true + }, + "include": [ + // add all the folders containg files to be compiled + ], + "references": [ + { "path": "../../core/tsconfig.json" }, + // add references to other TypeScript projects your plugin dependes on + ] +} +---- +If your plugin imports a file not listed in `include`, the build will fail with the next message `File ‘…’ is not listed within the file list of project …’. Projects must list all files or use an 'include' pattern.` + +- Build you plugin `./node_modules/.bin/tsc -b src/plugins/my_plugin`. Fix errors if `tsc` cannot generate type declarations for your project. +- Add your project reference to `references` property of `tsconfig.refs.json` +- Add your plugin to `references` property and plugin folder to `exclude` property of the `tsconfig.json` it used to belong to (for example, for `src/plugins/**` it's `tsconfig.json`; for `x-pack/plugins/**` it’s `x-pack/tsconfig.json`). +- List the reference to your newly created project in all the Kibana `tsconfig.json` files that could import your project: `tsconfig.json`, `test/tsconfig.json`, `x-pack/tsconfig.json`, `x-pack/test/tsconfig.json`. And in all the plugin-specific `tsconfig.refs.json` for dependent plugins. +- You can measure how your changes affect `tsc` compiler performance with `node --max-old-space-size=4096 ./node_modules/.bin/tsc -p tsconfig.json --extendedDiagnostics --noEmit`. Compare with `master` branch. + +You can use https://github.com/elastic/kibana/pull/79446 as an example. diff --git a/docs/developer/contributing/development-ci-metrics.asciidoc b/docs/developer/contributing/development-ci-metrics.asciidoc new file mode 100644 index 0000000000000..d4d54f1da7b8b --- /dev/null +++ b/docs/developer/contributing/development-ci-metrics.asciidoc @@ -0,0 +1,65 @@ +[[ci-metrics]] +== CI Metrics + +In addition to running our tests, CI collects metrics about the Kibana build. These metrics are sent to an external service to track changes over time, and to provide PR authors insights into the impact of their changes. + + +[[ci-metric-types]] +=== Metric types + + +[[ci-metric-types-bundle-size-metrics]] +==== Bundle size + +These metrics help contributors know how they are impacting the size of the bundles Kibana creates, and help make sure that Kibana loads as fast as possible. + +[[ci-metric-page-load-bundle-size]] `page load bundle size` :: +The size of the entry file produced for each bundle/plugin. This file is always loaded on every page load, so it should be as small as possible. To reduce this metric you can put any code that isn't necessary on every page load behind an https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import#Dynamic_Imports[`async import()`]. ++ +Code that is shared statically with other plugins will contribute to the `page load bundle size` of that plugin. This includes exports from the `public/index.ts` file and any file referenced by the `extraPublicDirs` manifest property. + +[[ci-metric-async-chunks-size]] `async chunks size` :: +An "async chunk" is created for the files imported by each https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import#Dynamic_Imports[`async import()`] statement. This metric tracks the sum size of these chunks, in bytes, broken down by plugin/bundle id. You can think of this as the amount of code users will have to download if they access all the components/applications within a bundle. + +[[ci-metric-misc-asset-size]] `miscellaneous assets size` :: +A "miscellaneous asset" is anything that isn't an async chunk or entry chunk, often images. This metric tracks the sum size of these assets, in bytes, broken down by plugin/bundle id. + +[[ci-metric-bundle-module-count]] `@kbn/optimizer bundle module count` :: +The number of separate modules included in each bundle/plugin. This is the best indicator we have for how long a specific bundle will take to be built by the `@kbn/optimizer`, so we report it to help people know when they've imported a module which might include a surprising number of sub-modules. + + +[[ci-metric-types-distributable-size]] +==== Distributable size + +The size of the Kibana distributable is an essential metric as it not only contributes to the time it takes to download, but it also impacts time it takes to extract the archive once downloaded. + +There are several metrics that we don't report on PRs because gzip-compression produces different file sizes even when provided the same input, so this metric would regularly show changes even though PR authors hadn't made any relevant changes. + +All metrics are collected from the `tar.gz` archive produced for the linux platform. + +[[ci-metric-distributable-file-count]] `distributable file count` :: +The number of files included in the default distributable. + +[[ci-metric-oss-distributable-file-count]] `oss distributable file count` :: +The number of files included in the OSS distributable. + +[[ci-metric-distributable-size]] `distributable size` :: +The size, in bytes, of the default distributable. _(not reported on PRs)_ + +[[ci-metric-oss-distributable-size]] `oss distributable size` :: +The size, in bytes, of the OSS distributable. _(not reported on PRs)_ + + +[[ci-metric-types-saved-object-field-counts]] +==== Saved Object field counts + +Elasticsearch limits the number of fields in an index to 1000 by default, and we want to avoid raising that limit. + +[[ci-metric-saved-object-field-count]] `Saved Objects .kibana field count` :: +The number of saved object fields broken down by saved object type. + + +[[ci-metric-adding-new-metrics]] +=== Adding new metrics + +You can report new metrics by using the `CiStatsReporter` class provided by the `@kbn/dev-utils` package. This class is automatically configured on CI and its methods noop when running outside of CI. For more details checkout the {kib-repo}blob/{branch}/packages/kbn-dev-utils/src/ci_stats_reporter[`CiStatsReporter` readme]. \ No newline at end of file diff --git a/docs/developer/contributing/development-documentation.asciidoc b/docs/developer/contributing/development-documentation.asciidoc index 99e55963f57af..70dd756ca808e 100644 --- a/docs/developer/contributing/development-documentation.asciidoc +++ b/docs/developer/contributing/development-documentation.asciidoc @@ -26,6 +26,13 @@ README for getting the docs tooling set up. ```bash node scripts/docs.js --open ``` +[discrete] +==== REST APIs + +REST APIs should be documented using the following recommended formats: + +* https://raw.githubusercontent.com/elastic/docs/master/shared/api-ref-ex.asciidoc[API doc templaate] +* https://raw.githubusercontent.com/elastic/docs/master/shared/api-definitions-ex.asciidoc[API object definition template] [discrete] === General developer documentation and guidelines diff --git a/docs/developer/contributing/development-github.asciidoc b/docs/developer/contributing/development-github.asciidoc index 84f51843098a7..c5a3d942f2af3 100644 --- a/docs/developer/contributing/development-github.asciidoc +++ b/docs/developer/contributing/development-github.asciidoc @@ -25,7 +25,7 @@ Pull requests are made into the `master` branch and then backported when it is s * Breaking changes do not get backported and only go into `master`. * All non-breaking changes can be backported to the `.x` branch. * Features should not be backported to a `.` branch. -* Bugs can be backported to a `.` branch if the changes are safe and appropriate. Safety is a judgment call you make based on factors like the bug's severity, test coverage, confidence in the changes, etc. Your reasoning should be included in the pull request description. +* Bug fixes can be backported to a `.` branch if the changes are safe and appropriate. Safety is a judgment call you make based on factors like the bug's severity, test coverage, confidence in the changes, etc. Your reasoning should be included in the pull request description. * Documentation changes can be backported to any branch at any time. [discrete] diff --git a/docs/developer/contributing/index.asciidoc b/docs/developer/contributing/index.asciidoc index 99ab83bc2f073..ba4ab89d17c27 100644 --- a/docs/developer/contributing/index.asciidoc +++ b/docs/developer/contributing/index.asciidoc @@ -9,6 +9,7 @@ Read <> to get your environment up and running, the * <> * <> * <> +* <> * <> * <> * <> @@ -48,7 +49,7 @@ The Release Notes summarize what the PRs accomplish in language that is meaningf The text that appears in the Release Notes is pulled directly from your PR title, or a single paragraph of text that you specify in the PR description. -To use a single paragraph of text, enter `Release note:` or a `## Release note` header in the PR description, followed by your text. For example, refer to this https://github.com/elastic/kibana/pull/65796[PR] that uses the `## Release note` header. +To use a single paragraph of text, enter a `Release note:` or `## Release note` header in the PR description ("dev docs" works too), followed by your text. For example, refer to this https://github.com/elastic/kibana/pull/65796[PR] that uses the `## Release note` header. When you create the Release Notes text, use the following best practices: @@ -78,6 +79,8 @@ include::development-tests.asciidoc[leveloffset=+1] include::interpreting-ci-failures.asciidoc[leveloffset=+1] +include::development-ci-metrics.asciidoc[leveloffset=+1] + include::development-documentation.asciidoc[leveloffset=+1] include::development-pull-request.asciidoc[leveloffset=+1] diff --git a/docs/developer/getting-started/development-plugin-resources.asciidoc b/docs/developer/getting-started/development-plugin-resources.asciidoc index 8f81138b81ed7..1fe211c87c660 100644 --- a/docs/developer/getting-started/development-plugin-resources.asciidoc +++ b/docs/developer/getting-started/development-plugin-resources.asciidoc @@ -33,7 +33,7 @@ To enable TypeScript support, create a `tsconfig.json` file at the root of your ["source","js"] ----------- { - // extend {kib}'s tsconfig, or use your own settings + // extend Kibana's tsconfig, or use your own settings "extends": "../../kibana/tsconfig.json", // tell the TypeScript compiler where to find your source files diff --git a/docs/developer/index.asciidoc b/docs/developer/index.asciidoc index 5f032a3952173..9e349a38557f2 100644 --- a/docs/developer/index.asciidoc +++ b/docs/developer/index.asciidoc @@ -1,7 +1,6 @@ [[development]] = Developer guide -[partintro] -- Contributing to {kib} can be daunting at first, but it doesn't have to be. The following sections should get you up and running in no time. If you have any problems, file an issue in the https://github.com/elastic/kibana/issues[Kibana repo]. diff --git a/docs/developer/plugin-list.asciidoc b/docs/developer/plugin-list.asciidoc index 501a3698d07d9..21c51f8cabd32 100644 --- a/docs/developer/plugin-list.asciidoc +++ b/docs/developer/plugin-list.asciidoc @@ -16,7 +16,7 @@ NOTE: [discrete] === src/plugins -[%header,cols=2*] +[%header,cols=2*] |=== |Name |Description @@ -48,7 +48,7 @@ NOTE: |{kib-repo}blob/{branch}/src/plugins/data/README.md[data] -|data plugin provides common data access services. +|The data plugin provides common data access services, such as search and query, for solutions and application developers. |{kib-repo}blob/{branch}/src/plugins/dev_tools/README.md[devTools] @@ -62,16 +62,28 @@ This API doesn't support angular, for registering angular dev tools, bootstrap a |Contains the Discover application and the saved search embeddable. -|{kib-repo}blob/{branch}/src/plugins/embeddable/README.md[embeddable] -|Embeddables are re-usable widgets that can be rendered in any environment or plugin. Developers can embed them directly in their plugin. End users can dynamically add them to any embeddable containers. +|<> +|Embeddables are re-usable widgets that can be rendered in any environment or plugin. Developers can embed them directly in their plugin. End users can dynamically add them to any embeddable _containers_. |{kib-repo}blob/{branch}/src/plugins/es_ui_shared/README.md[esUiShared] |This plugin contains reusable code in the form of self-contained modules (or libraries). Each of these modules exports a set of functionality relevant to the domain of the module. -|{kib-repo}blob/{branch}/src/plugins/expressions/README.md[expressions] -|This plugin provides methods which will parse & execute an expression pipeline +|<> +|Expression pipeline is a chain of functions that *pipe* its output to the +input of the next function. Functions can be configured using arguments provided +by the user. The final output of the expression pipeline can be rendered using +one of the *renderers* registered in `expressions` plugin. + +All the arguments to expression functions need to be serializable, as well as input and output. +Expression functions should try to stay 'pure'. This makes functions easy to reuse and also +make it possible to serialize the whole chain as well as output at every step of execution. + +Expressions power visualizations in Dashboard and Lens, as well as, every +*element* in Canvas is backed by an expression. + +This plugin provides methods which will parse & execute an *expression pipeline* string for you, as well as a series of registries for advanced users who might want to incorporate their own functions, types, and renderers into the service for use in their own application. @@ -98,6 +110,10 @@ in Kibana, e.g. visualizations. It has the form of a flyout panel. |This plugin contains several helpers and services to integrate pieces of the legacy Kibana app with the new Kibana platform. +|{kib-repo}blob/{branch}/src/plugins/kibana_overview/README.md[kibanaOverview] +|An overview page highlighting Kibana apps + + |{kib-repo}blob/{branch}/src/plugins/kibana_react/README.md[kibanaReact] |Tools for building React applications in Kibana. @@ -143,6 +159,11 @@ It also provides a stateful version of it on the start contract. |WARNING: Missing README. +|{kib-repo}blob/{branch}/src/plugins/security_oss/README.md[securityOss] +|securityOss is responsible for educating users about Elastic's free security features, +so they can properly protect the data within their clusters. + + |{kib-repo}blob/{branch}/src/plugins/share/README.md[share] |Replaces the legacy ui/share module for registering share context menus. @@ -156,7 +177,7 @@ It also provides a stateful version of it on the start contract. |{kib-repo}blob/{branch}/src/plugins/telemetry_management_section/README.md[telemetryManagementSection] -|This plugin adds the Advanced Settings section for the Usage Data collection (aka Telemetry). +|This plugin adds the Advanced Settings section for the Usage and Security Data collection (aka Telemetry). |{kib-repo}blob/{branch}/src/plugins/tile_map[tileMap] @@ -168,9 +189,16 @@ It also provides a stateful version of it on the start contract. which also contains the timelion APIs and backend, look at the vis_type_timelion plugin. -|{kib-repo}blob/{branch}/src/plugins/ui_actions/README.md[uiActions] +|<> |An API for: +- creating custom functionality (`actions`) +- creating custom user interaction events (`triggers`) +- attaching and detaching `actions` to `triggers`. +- emitting `trigger` events +- executing `actions` attached to a given `trigger`. +- exposing a context menu for the user to choose the appropriate action when there are multiple actions attached to a single trigger. + |{kib-repo}blob/{branch}/src/plugins/url_forwarding/README.md[urlForwarding] |This plugins contains helpers to redirect legacy URLs. It can be used to forward old URLs to their new counterparts. @@ -181,6 +209,12 @@ which also contains the timelion APIs and backend, look at the vis_type_timelion To integrate with the telemetry services for usage collection of your feature, there are 2 steps: +|{kib-repo}blob/{branch}/src/plugins/vis_default_editor/README.md[visDefaultEditor] +|The default editor is used in most primary visualizations, e.x. Area, Data table, Pie, etc. +It acts as a container for a particular visualization and options tabs. Contains the default "Data" tab in public/components/sidebar/data_tab.tsx. +The plugin exposes the static DefaultEditorController class to consume. + + |{kib-repo}blob/{branch}/src/plugins/vis_type_markdown/README.md[visTypeMarkdown] |The markdown visualization that can be used to place text panels on dashboards. @@ -234,7 +268,7 @@ which will load the visualization's editor. [discrete] === x-pack/plugins -[%header,cols=2*] +[%header,cols=2*] |=== |Name |Description @@ -244,13 +278,6 @@ which will load the visualization's editor. |The Kibana actions plugin provides a framework to create executable actions. You can: -|{kib-repo}blob/{branch}/x-pack/plugins/alerting_builtins/README.md[alertingBuiltins] -|This plugin provides alertTypes shipped with Kibana for use with the -the alerts plugin. When enabled, it will register -the built-in alertTypes with the alerting plugin, register associated HTTP -routes, etc. - - |{kib-repo}blob/{branch}/x-pack/plugins/alerts/README.md[alerts] |The Kibana alerting plugin provides a common place to set up alerts. You can: @@ -372,7 +399,7 @@ the infrastructure monitoring use-case within Kibana. |{kib-repo}blob/{branch}/x-pack/plugins/ingest_manager/README.md[ingestManager] -|Fleet needs to have Elasticsearch API keys enabled, and also to have TLS enabled on kibana, (if you want to run Kibana without TLS you can provide the following config flag --xpack.ingestManager.fleet.tlsCheckDisabled=false) +|Fleet needs to have Elasticsearch API keys enabled, and also to have TLS enabled on kibana, (if you want to run Kibana without TLS you can provide the following config flag --xpack.fleet.agents.tlsCheckDisabled=false) |{kib-repo}blob/{branch}/x-pack/plugins/ingest_pipelines/README.md[ingestPipelines] @@ -456,6 +483,13 @@ using the CURL scripts in the scripts folder. |WARNING: Missing README. +|{kib-repo}blob/{branch}/x-pack/plugins/stack_alerts/README.md[stackAlerts] +|This plugin provides alertTypes shipped with Kibana for use with the +the alerts plugin. When enabled, it will register +the alertTypes by the Stack in the alerting plugin, register associated HTTP +routes, etc. + + |{kib-repo}blob/{branch}/x-pack/plugins/task_manager[taskManager] |WARNING: Missing README. @@ -472,7 +506,7 @@ using the CURL scripts in the scripts folder. |WARNING: Missing README. -|{kib-repo}blob/{branch}/x-pack/plugins/triggers_actions_ui/README.md[triggers_actions_ui] +|{kib-repo}blob/{branch}/x-pack/plugins/triggers_actions_ui/README.md[triggersActionsUi] |The Kibana alerts and actions UI plugin provides a user interface for managing alerts and actions. As a developer you can reuse and extend built-in alerts and actions UI functionality: @@ -490,6 +524,10 @@ As a developer you can reuse and extend built-in alerts and actions UI functiona in their infrastructure. +|{kib-repo}blob/{branch}/x-pack/plugins/drilldowns/url_drilldown/README.md[urlDrilldown] +|NOTE: This plugin contains implementation of URL drilldown. For drilldowns infrastructure code refer to ui_actions_enhanced plugin. + + |{kib-repo}blob/{branch}/x-pack/plugins/watcher/README.md[watcher] |This plugins adopts some conventions in addition to or in place of conventions in Kibana (at the time of the plugin's creation): @@ -501,5 +539,8 @@ in their infrastructure. |=== include::{kibana-root}/src/plugins/dashboard/README.asciidoc[leveloffset=+1] +include::{kibana-root}/src/plugins/embeddable/README.asciidoc[leveloffset=+1] +include::{kibana-root}/src/plugins/expressions/README.asciidoc[leveloffset=+1] +include::{kibana-root}/src/plugins/ui_actions/README.asciidoc[leveloffset=+1] include::{kibana-root}/x-pack/plugins/dashboard_enhanced/README.asciidoc[leveloffset=+1] include::{kibana-root}/x-pack/plugins/embeddable_enhanced/README.asciidoc[leveloffset=+1] diff --git a/docs/development/core/public/kibana-plugin-core-public.applicationstart.geturlforapp.md b/docs/development/core/public/kibana-plugin-core-public.applicationstart.geturlforapp.md index 055ad9f37e654..1eaf00c7a678d 100644 --- a/docs/development/core/public/kibana-plugin-core-public.applicationstart.geturlforapp.md +++ b/docs/development/core/public/kibana-plugin-core-public.applicationstart.geturlforapp.md @@ -4,9 +4,11 @@ ## ApplicationStart.getUrlForApp() method -Returns an URL to a given app, including the global base path. By default, the URL is relative (/basePath/app/my-app). Use the `absolute` option to generate an absolute url (http://host:port/basePath/app/my-app) +Returns the absolute path (or URL) to a given app, including the global base path. -Note that when generating absolute urls, the origin (protocol, host and port) are determined from the browser's location. +By default, it returns the absolute path of the application (e.g `/basePath/app/my-app`). Use the `absolute` option to generate an absolute url instead (e.g `http://host:port/basePath/app/my-app`) + +Note that when generating absolute urls, the origin (protocol, host and port) are determined from the browser's current location. Signature: diff --git a/docs/development/core/public/kibana-plugin-core-public.applicationstart.md b/docs/development/core/public/kibana-plugin-core-public.applicationstart.md index 00318f32984e9..ae62a7767a0e9 100644 --- a/docs/development/core/public/kibana-plugin-core-public.applicationstart.md +++ b/docs/development/core/public/kibana-plugin-core-public.applicationstart.md @@ -23,8 +23,8 @@ export interface ApplicationStart | Method | Description | | --- | --- | -| [getUrlForApp(appId, options)](./kibana-plugin-core-public.applicationstart.geturlforapp.md) | Returns an URL to a given app, including the global base path. By default, the URL is relative (/basePath/app/my-app). Use the absolute option to generate an absolute url (http://host:port/basePath/app/my-app)Note that when generating absolute urls, the origin (protocol, host and port) are determined from the browser's location. | +| [getUrlForApp(appId, options)](./kibana-plugin-core-public.applicationstart.geturlforapp.md) | Returns the absolute path (or URL) to a given app, including the global base path.By default, it returns the absolute path of the application (e.g /basePath/app/my-app). Use the absolute option to generate an absolute url instead (e.g http://host:port/basePath/app/my-app)Note that when generating absolute urls, the origin (protocol, host and port) are determined from the browser's current location. | | [navigateToApp(appId, options)](./kibana-plugin-core-public.applicationstart.navigatetoapp.md) | Navigate to a given app | -| [navigateToUrl(url)](./kibana-plugin-core-public.applicationstart.navigatetourl.md) | Navigate to given url, which can either be an absolute url or a relative path, in a SPA friendly way when possible.If all these criteria are true for the given url: - (only for absolute URLs) The origin of the URL matches the origin of the browser's current location - The pathname of the URL starts with the current basePath (eg. /mybasepath/s/my-space) - The pathname segment after the basePath matches any known application route (eg. /app// or any application's appRoute configuration)Then a SPA navigation will be performed using navigateToApp using the corresponding application and path. Otherwise, fallback to a full page reload to navigate to the url using window.location.assign | +| [navigateToUrl(url)](./kibana-plugin-core-public.applicationstart.navigatetourl.md) | Navigate to given URL in a SPA friendly way when possible (when the URL will redirect to a valid application within the current basePath).The method resolves pathnames the same way browsers do when resolving a <a href> value. The provided url can be: - an absolute URL - an absolute path - a path relative to the current URL (window.location.href)If all these criteria are true for the given URL: - (only for absolute URLs) The origin of the URL matches the origin of the browser's current location - The resolved pathname of the provided URL/path starts with the current basePath (eg. /mybasepath/s/my-space) - The pathname segment after the basePath matches any known application route (eg. /app// or any application's appRoute configuration)Then a SPA navigation will be performed using navigateToApp using the corresponding application and path. Otherwise, fallback to a full page reload to navigate to the url using window.location.assign | | [registerMountContext(contextName, provider)](./kibana-plugin-core-public.applicationstart.registermountcontext.md) | Register a context provider for application mounting. Will only be available to applications that depend on the plugin that registered this context. Deprecated, use [CoreSetup.getStartServices](./kibana-plugin-core-public.coresetup.getstartservices.md). | diff --git a/docs/development/core/public/kibana-plugin-core-public.applicationstart.navigatetourl.md b/docs/development/core/public/kibana-plugin-core-public.applicationstart.navigatetourl.md index 86b86776b0b12..8639394cbc421 100644 --- a/docs/development/core/public/kibana-plugin-core-public.applicationstart.navigatetourl.md +++ b/docs/development/core/public/kibana-plugin-core-public.applicationstart.navigatetourl.md @@ -4,9 +4,11 @@ ## ApplicationStart.navigateToUrl() method -Navigate to given url, which can either be an absolute url or a relative path, in a SPA friendly way when possible. +Navigate to given URL in a SPA friendly way when possible (when the URL will redirect to a valid application within the current basePath). -If all these criteria are true for the given url: - (only for absolute URLs) The origin of the URL matches the origin of the browser's current location - The pathname of the URL starts with the current basePath (eg. /mybasepath/s/my-space) - The pathname segment after the basePath matches any known application route (eg. /app// or any application's `appRoute` configuration) +The method resolves pathnames the same way browsers do when resolving a `` value. The provided `url` can be: - an absolute URL - an absolute path - a path relative to the current URL (window.location.href) + +If all these criteria are true for the given URL: - (only for absolute URLs) The origin of the URL matches the origin of the browser's current location - The resolved pathname of the provided URL/path starts with the current basePath (eg. /mybasepath/s/my-space) - The pathname segment after the basePath matches any known application route (eg. /app// or any application's `appRoute` configuration) Then a SPA navigation will be performed using `navigateToApp` using the corresponding application and path. Otherwise, fallback to a full page reload to navigate to the url using `window.location.assign` @@ -20,7 +22,7 @@ navigateToUrl(url: string): Promise; | Parameter | Type | Description | | --- | --- | --- | -| url | string | an absolute url, or a relative path, to navigate to. | +| url | string | an absolute URL, an absolute path or a relative path, to navigate to. | Returns: @@ -35,11 +37,14 @@ navigateToUrl(url: string): Promise; // will call `application.navigateToApp('discover', { path: '/some-path?foo=bar'})` application.navigateToUrl('https://kibana:8080/base-path/s/my-space/app/discover/some-path?foo=bar') application.navigateToUrl('/base-path/s/my-space/app/discover/some-path?foo=bar') +application.navigateToUrl('./discover/some-path?foo=bar') // will perform a full page reload using `window.location.assign` application.navigateToUrl('https://elsewhere:8080/base-path/s/my-space/app/discover/some-path') // origin does not match application.navigateToUrl('/app/discover/some-path') // does not include the current basePath application.navigateToUrl('/base-path/s/my-space/app/unknown-app/some-path') // unknown application +application.navigateToUrl('../discover') // resolve to `/base-path/s/my-space/discover` which is not a path of a known app. +application.navigateToUrl('../../other-space/discover') // resolve to `/base-path/s/other-space/discover` which is not within the current basePath. ``` 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 f7b55b0650d8b..3afd5eaa6f1f7 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 @@ -91,6 +91,7 @@ readonly links: { readonly gettingStarted: string; }; readonly query: { + readonly eql: string; readonly luceneQuerySyntax: string; readonly queryDsl: string; readonly kueryQuerySyntax: 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 3f58cf08ee6b6..5249381969b98 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 dashboard: {
readonly drilldowns: string;
readonly drilldownsTriggerPicker: string;
readonly urlDrilldownTemplateSyntax: string;
readonly urlDrilldownVariables: string;
};
readonly filebeat: {
readonly base: string;
readonly installation: string;
readonly configuration: string;
readonly elasticsearchOutput: string;
readonly startup: string;
readonly exportedFields: string;
};
readonly auditbeat: {
readonly base: string;
};
readonly metricbeat: {
readonly base: string;
};
readonly heartbeat: {
readonly base: string;
};
readonly logstash: {
readonly base: string;
};
readonly functionbeat: {
readonly base: string;
};
readonly winlogbeat: {
readonly base: string;
};
readonly aggs: {
readonly date_histogram: string;
readonly date_range: string;
readonly filter: string;
readonly filters: string;
readonly geohash_grid: string;
readonly histogram: string;
readonly ip_range: string;
readonly range: string;
readonly significant_terms: string;
readonly terms: string;
readonly avg: string;
readonly avg_bucket: string;
readonly max_bucket: string;
readonly min_bucket: string;
readonly sum_bucket: string;
readonly cardinality: string;
readonly count: string;
readonly cumulative_sum: string;
readonly derivative: string;
readonly geo_bounds: string;
readonly geo_centroid: string;
readonly max: string;
readonly median: string;
readonly min: string;
readonly moving_avg: string;
readonly percentile_ranks: string;
readonly serial_diff: string;
readonly std_dev: string;
readonly sum: string;
readonly top_hits: string;
};
readonly scriptedFields: {
readonly scriptFields: string;
readonly scriptAggs: string;
readonly painless: string;
readonly painlessApi: string;
readonly painlessSyntax: string;
readonly luceneExpressions: string;
};
readonly indexPatterns: {
readonly loadingData: string;
readonly introduction: string;
};
readonly addData: string;
readonly kibana: string;
readonly siem: {
readonly guide: string;
readonly gettingStarted: string;
};
readonly query: {
readonly luceneQuerySyntax: string;
readonly queryDsl: string;
readonly kueryQuerySyntax: string;
};
readonly date: {
readonly dateMath: string;
};
readonly management: Record<string, string>;
readonly visualize: Record<string, string>;
} | | +| [links](./kibana-plugin-core-public.doclinksstart.links.md) | {
readonly dashboard: {
readonly drilldowns: string;
readonly drilldownsTriggerPicker: string;
readonly urlDrilldownTemplateSyntax: string;
readonly urlDrilldownVariables: string;
};
readonly filebeat: {
readonly base: string;
readonly installation: string;
readonly configuration: string;
readonly elasticsearchOutput: string;
readonly startup: string;
readonly exportedFields: string;
};
readonly auditbeat: {
readonly base: string;
};
readonly metricbeat: {
readonly base: string;
};
readonly heartbeat: {
readonly base: string;
};
readonly logstash: {
readonly base: string;
};
readonly functionbeat: {
readonly base: string;
};
readonly winlogbeat: {
readonly base: string;
};
readonly aggs: {
readonly date_histogram: string;
readonly date_range: string;
readonly filter: string;
readonly filters: string;
readonly geohash_grid: string;
readonly histogram: string;
readonly ip_range: string;
readonly range: string;
readonly significant_terms: string;
readonly terms: string;
readonly avg: string;
readonly avg_bucket: string;
readonly max_bucket: string;
readonly min_bucket: string;
readonly sum_bucket: string;
readonly cardinality: string;
readonly count: string;
readonly cumulative_sum: string;
readonly derivative: string;
readonly geo_bounds: string;
readonly geo_centroid: string;
readonly max: string;
readonly median: string;
readonly min: string;
readonly moving_avg: string;
readonly percentile_ranks: string;
readonly serial_diff: string;
readonly std_dev: string;
readonly sum: string;
readonly top_hits: string;
};
readonly scriptedFields: {
readonly scriptFields: string;
readonly scriptAggs: string;
readonly painless: string;
readonly painlessApi: string;
readonly painlessSyntax: string;
readonly luceneExpressions: string;
};
readonly indexPatterns: {
readonly loadingData: string;
readonly introduction: string;
};
readonly addData: string;
readonly kibana: string;
readonly siem: {
readonly guide: string;
readonly gettingStarted: string;
};
readonly query: {
readonly eql: string;
readonly luceneQuerySyntax: string;
readonly queryDsl: string;
readonly kueryQuerySyntax: string;
};
readonly date: {
readonly dateMath: string;
};
readonly management: Record<string, string>;
readonly visualize: Record<string, string>;
} | | diff --git a/docs/development/core/public/kibana-plugin-core-public.savedobjectsclient.delete.md b/docs/development/core/public/kibana-plugin-core-public.savedobjectsclient.delete.md index 3b5f5630e8060..3a5dcb51e2c42 100644 --- a/docs/development/core/public/kibana-plugin-core-public.savedobjectsclient.delete.md +++ b/docs/development/core/public/kibana-plugin-core-public.savedobjectsclient.delete.md @@ -9,5 +9,5 @@ Deletes an object Signature: ```typescript -delete: (type: string, id: string) => ReturnType; +delete: (type: string, id: string, options?: SavedObjectsDeleteOptions | undefined) => ReturnType; ``` diff --git a/docs/development/core/public/kibana-plugin-core-public.savedobjectsclient.md b/docs/development/core/public/kibana-plugin-core-public.savedobjectsclient.md index 904b9cce09d4e..6e53b169b8bed 100644 --- a/docs/development/core/public/kibana-plugin-core-public.savedobjectsclient.md +++ b/docs/development/core/public/kibana-plugin-core-public.savedobjectsclient.md @@ -23,7 +23,7 @@ The constructor for this class is marked as internal. Third-party code should no | [bulkCreate](./kibana-plugin-core-public.savedobjectsclient.bulkcreate.md) | | (objects?: SavedObjectsBulkCreateObject[], options?: SavedObjectsBulkCreateOptions) => Promise<SavedObjectsBatchResponse<unknown>> | Creates multiple documents at once | | [bulkGet](./kibana-plugin-core-public.savedobjectsclient.bulkget.md) | | (objects?: Array<{
id: string;
type: string;
}>) => Promise<SavedObjectsBatchResponse<unknown>> | Returns an array of objects by id | | [create](./kibana-plugin-core-public.savedobjectsclient.create.md) | | <T = unknown>(type: string, attributes: T, options?: SavedObjectsCreateOptions) => Promise<SimpleSavedObject<T>> | Persists an object | -| [delete](./kibana-plugin-core-public.savedobjectsclient.delete.md) | | (type: string, id: string) => ReturnType<SavedObjectsApi['delete']> | Deletes an object | +| [delete](./kibana-plugin-core-public.savedobjectsclient.delete.md) | | (type: string, id: string, options?: SavedObjectsDeleteOptions | undefined) => ReturnType<SavedObjectsApi['delete']> | Deletes an object | | [find](./kibana-plugin-core-public.savedobjectsclient.find.md) | | <T = unknown>(options: SavedObjectsFindOptions) => Promise<SavedObjectsFindResponsePublic<T>> | Search for objects | | [get](./kibana-plugin-core-public.savedobjectsclient.get.md) | | <T = unknown>(type: string, id: string) => Promise<SimpleSavedObject<T>> | Fetches a single object | diff --git a/docs/development/core/public/kibana-plugin-core-public.savedobjectsfindoptions.md b/docs/development/core/public/kibana-plugin-core-public.savedobjectsfindoptions.md index 903462ac3039d..470a41f30afbf 100644 --- a/docs/development/core/public/kibana-plugin-core-public.savedobjectsfindoptions.md +++ b/docs/development/core/public/kibana-plugin-core-public.savedobjectsfindoptions.md @@ -29,4 +29,5 @@ export interface SavedObjectsFindOptions | [sortField](./kibana-plugin-core-public.savedobjectsfindoptions.sortfield.md) | string | | | [sortOrder](./kibana-plugin-core-public.savedobjectsfindoptions.sortorder.md) | string | | | [type](./kibana-plugin-core-public.savedobjectsfindoptions.type.md) | string | string[] | | +| [typeToNamespacesMap](./kibana-plugin-core-public.savedobjectsfindoptions.typetonamespacesmap.md) | Map<string, string[] | undefined> | This map defines each type to search for, and the namespace(s) to search for the type in; this is only intended to be used by a saved object client wrapper. If this is defined, it supersedes the type and namespaces fields when building the Elasticsearch query. Any types that are not included in this map will be excluded entirely. If a type is included but its value is undefined, the operation will search for that type in the Default namespace. | diff --git a/docs/development/core/public/kibana-plugin-core-public.savedobjectsfindoptions.typetonamespacesmap.md b/docs/development/core/public/kibana-plugin-core-public.savedobjectsfindoptions.typetonamespacesmap.md new file mode 100644 index 0000000000000..4af8c9ddeaff4 --- /dev/null +++ b/docs/development/core/public/kibana-plugin-core-public.savedobjectsfindoptions.typetonamespacesmap.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [SavedObjectsFindOptions](./kibana-plugin-core-public.savedobjectsfindoptions.md) > [typeToNamespacesMap](./kibana-plugin-core-public.savedobjectsfindoptions.typetonamespacesmap.md) + +## SavedObjectsFindOptions.typeToNamespacesMap property + +This map defines each type to search for, and the namespace(s) to search for the type in; this is only intended to be used by a saved object client wrapper. If this is defined, it supersedes the `type` and `namespaces` fields when building the Elasticsearch query. Any types that are not included in this map will be excluded entirely. If a type is included but its value is undefined, the operation will search for that type in the Default namespace. + +Signature: + +```typescript +typeToNamespacesMap?: Map; +``` diff --git a/docs/development/core/server/kibana-plugin-core-server.kibanarequest.md b/docs/development/core/server/kibana-plugin-core-server.kibanarequest.md index 05e408ab49995..0a49ee6e63d6c 100644 --- a/docs/development/core/server/kibana-plugin-core-server.kibanarequest.md +++ b/docs/development/core/server/kibana-plugin-core-server.kibanarequest.md @@ -33,4 +33,5 @@ export declare class KibanaRequestRecursiveReadonly<KibanaRequestRoute<Method>> | matched route details | | [socket](./kibana-plugin-core-server.kibanarequest.socket.md) | | IKibanaSocket | [IKibanaSocket](./kibana-plugin-core-server.ikibanasocket.md) | | [url](./kibana-plugin-core-server.kibanarequest.url.md) | | Url | a WHATWG URL standard object. | +| [uuid](./kibana-plugin-core-server.kibanarequest.uuid.md) | | string | A UUID to identify this request. | diff --git a/docs/development/core/server/kibana-plugin-core-server.kibanarequest.uuid.md b/docs/development/core/server/kibana-plugin-core-server.kibanarequest.uuid.md new file mode 100644 index 0000000000000..8b980b82d0adb --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.kibanarequest.uuid.md @@ -0,0 +1,18 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [KibanaRequest](./kibana-plugin-core-server.kibanarequest.md) > [uuid](./kibana-plugin-core-server.kibanarequest.uuid.md) + +## KibanaRequest.uuid property + +A UUID to identify this request. + +Signature: + +```typescript +readonly uuid: string; +``` + +## Remarks + +This value is NOT sourced from the incoming request's `X-Opaque-Id` header. it is always a UUID uniquely identifying the request. + diff --git a/docs/development/core/server/kibana-plugin-core-server.md b/docs/development/core/server/kibana-plugin-core-server.md index be8b7c27495ad..a484c856ec015 100644 --- a/docs/development/core/server/kibana-plugin-core-server.md +++ b/docs/development/core/server/kibana-plugin-core-server.md @@ -121,6 +121,7 @@ The plugin integrates with the core system via lifecycle events: `setup` | [OnPreAuthToolkit](./kibana-plugin-core-server.onpreauthtoolkit.md) | A tool set defining an outcome of OnPreAuth interceptor for incoming request. | | [OnPreResponseExtensions](./kibana-plugin-core-server.onpreresponseextensions.md) | Additional data to extend a response. | | [OnPreResponseInfo](./kibana-plugin-core-server.onpreresponseinfo.md) | Response status code. | +| [OnPreResponseRender](./kibana-plugin-core-server.onpreresponserender.md) | Additional data to extend a response when rendering a new body | | [OnPreResponseToolkit](./kibana-plugin-core-server.onpreresponsetoolkit.md) | A tool set defining an outcome of OnPreResponse interceptor for incoming request. | | [OnPreRoutingToolkit](./kibana-plugin-core-server.onpreroutingtoolkit.md) | A tool set defining an outcome of OnPreRouting interceptor for incoming request. | | [OpsMetrics](./kibana-plugin-core-server.opsmetrics.md) | Regroups metrics gathered by all the collectors. This contains metrics about the os/runtime, the kibana process and the http server. | diff --git a/docs/development/core/server/kibana-plugin-core-server.onpreresponserender.body.md b/docs/development/core/server/kibana-plugin-core-server.onpreresponserender.body.md new file mode 100644 index 0000000000000..ab5b5e7a4f272 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.onpreresponserender.body.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [OnPreResponseRender](./kibana-plugin-core-server.onpreresponserender.md) > [body](./kibana-plugin-core-server.onpreresponserender.body.md) + +## OnPreResponseRender.body property + +the body to use in the response + +Signature: + +```typescript +body: string; +``` diff --git a/docs/development/core/server/kibana-plugin-core-server.onpreresponserender.headers.md b/docs/development/core/server/kibana-plugin-core-server.onpreresponserender.headers.md new file mode 100644 index 0000000000000..100d12f63d165 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.onpreresponserender.headers.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [OnPreResponseRender](./kibana-plugin-core-server.onpreresponserender.md) > [headers](./kibana-plugin-core-server.onpreresponserender.headers.md) + +## OnPreResponseRender.headers property + +additional headers to attach to the response + +Signature: + +```typescript +headers?: ResponseHeaders; +``` diff --git a/docs/development/core/server/kibana-plugin-core-server.onpreresponserender.md b/docs/development/core/server/kibana-plugin-core-server.onpreresponserender.md new file mode 100644 index 0000000000000..0a7ce2d546701 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.onpreresponserender.md @@ -0,0 +1,21 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [OnPreResponseRender](./kibana-plugin-core-server.onpreresponserender.md) + +## OnPreResponseRender interface + +Additional data to extend a response when rendering a new body + +Signature: + +```typescript +export interface OnPreResponseRender +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [body](./kibana-plugin-core-server.onpreresponserender.body.md) | string | the body to use in the response | +| [headers](./kibana-plugin-core-server.onpreresponserender.headers.md) | ResponseHeaders | additional headers to attach to the response | + diff --git a/docs/development/core/server/kibana-plugin-core-server.onpreresponsetoolkit.md b/docs/development/core/server/kibana-plugin-core-server.onpreresponsetoolkit.md index 44da09d0cc68e..14070038132da 100644 --- a/docs/development/core/server/kibana-plugin-core-server.onpreresponsetoolkit.md +++ b/docs/development/core/server/kibana-plugin-core-server.onpreresponsetoolkit.md @@ -17,4 +17,5 @@ export interface OnPreResponseToolkit | Property | Type | Description | | --- | --- | --- | | [next](./kibana-plugin-core-server.onpreresponsetoolkit.next.md) | (responseExtensions?: OnPreResponseExtensions) => OnPreResponseResult | To pass request to the next handler | +| [render](./kibana-plugin-core-server.onpreresponsetoolkit.render.md) | (responseRender: OnPreResponseRender) => OnPreResponseResult | To override the response with a different body | diff --git a/docs/development/core/server/kibana-plugin-core-server.onpreresponsetoolkit.render.md b/docs/development/core/server/kibana-plugin-core-server.onpreresponsetoolkit.render.md new file mode 100644 index 0000000000000..7dced7fe8deee --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.onpreresponsetoolkit.render.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [OnPreResponseToolkit](./kibana-plugin-core-server.onpreresponsetoolkit.md) > [render](./kibana-plugin-core-server.onpreresponsetoolkit.render.md) + +## OnPreResponseToolkit.render property + +To override the response with a different body + +Signature: + +```typescript +render: (responseRender: OnPreResponseRender) => OnPreResponseResult; +``` diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsbulkcreateobject.initialnamespaces.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsbulkcreateobject.initialnamespaces.md new file mode 100644 index 0000000000000..3db8bbadfbd6b --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectsbulkcreateobject.initialnamespaces.md @@ -0,0 +1,15 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [SavedObjectsBulkCreateObject](./kibana-plugin-core-server.savedobjectsbulkcreateobject.md) > [initialNamespaces](./kibana-plugin-core-server.savedobjectsbulkcreateobject.initialnamespaces.md) + +## SavedObjectsBulkCreateObject.initialNamespaces property + +Optional initial namespaces for the object to be created in. If this is defined, it will supersede the namespace ID that is in [SavedObjectsCreateOptions](./kibana-plugin-core-server.savedobjectscreateoptions.md). + +Note: this can only be used for multi-namespace object types. + +Signature: + +```typescript +initialNamespaces?: string[]; +``` diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsbulkcreateobject.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsbulkcreateobject.md index 019d30570ab36..5ac5f6d9807bd 100644 --- a/docs/development/core/server/kibana-plugin-core-server.savedobjectsbulkcreateobject.md +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectsbulkcreateobject.md @@ -17,6 +17,7 @@ export interface SavedObjectsBulkCreateObject | --- | --- | --- | | [attributes](./kibana-plugin-core-server.savedobjectsbulkcreateobject.attributes.md) | T | | | [id](./kibana-plugin-core-server.savedobjectsbulkcreateobject.id.md) | string | | +| [initialNamespaces](./kibana-plugin-core-server.savedobjectsbulkcreateobject.initialnamespaces.md) | string[] | Optional initial namespaces for the object to be created in. If this is defined, it will supersede the namespace ID that is in [SavedObjectsCreateOptions](./kibana-plugin-core-server.savedobjectscreateoptions.md).Note: this can only be used for multi-namespace object types. | | [migrationVersion](./kibana-plugin-core-server.savedobjectsbulkcreateobject.migrationversion.md) | SavedObjectsMigrationVersion | Information about the migrations that have been applied to this SavedObject. When Kibana starts up, KibanaMigrator detects outdated documents and migrates them based on this value. For each migration that has been applied, the plugin's name is used as a key and the latest migration version as the value. | | [originId](./kibana-plugin-core-server.savedobjectsbulkcreateobject.originid.md) | string | Optional ID of the original saved object, if this object's id was regenerated | | [references](./kibana-plugin-core-server.savedobjectsbulkcreateobject.references.md) | SavedObjectReference[] | | diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectscreateoptions.initialnamespaces.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectscreateoptions.initialnamespaces.md new file mode 100644 index 0000000000000..262b0997cb905 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectscreateoptions.initialnamespaces.md @@ -0,0 +1,15 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [SavedObjectsCreateOptions](./kibana-plugin-core-server.savedobjectscreateoptions.md) > [initialNamespaces](./kibana-plugin-core-server.savedobjectscreateoptions.initialnamespaces.md) + +## SavedObjectsCreateOptions.initialNamespaces property + +Optional initial namespaces for the object to be created in. If this is defined, it will supersede the namespace ID that is in [SavedObjectsCreateOptions](./kibana-plugin-core-server.savedobjectscreateoptions.md). + +Note: this can only be used for multi-namespace object types. + +Signature: + +```typescript +initialNamespaces?: string[]; +``` diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectscreateoptions.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectscreateoptions.md index d936829443753..e6d306784f8ae 100644 --- a/docs/development/core/server/kibana-plugin-core-server.savedobjectscreateoptions.md +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectscreateoptions.md @@ -16,6 +16,7 @@ export interface SavedObjectsCreateOptions extends SavedObjectsBaseOptions | Property | Type | Description | | --- | --- | --- | | [id](./kibana-plugin-core-server.savedobjectscreateoptions.id.md) | string | (not recommended) Specify an id for the document | +| [initialNamespaces](./kibana-plugin-core-server.savedobjectscreateoptions.initialnamespaces.md) | string[] | Optional initial namespaces for the object to be created in. If this is defined, it will supersede the namespace ID that is in [SavedObjectsCreateOptions](./kibana-plugin-core-server.savedobjectscreateoptions.md).Note: this can only be used for multi-namespace object types. | | [migrationVersion](./kibana-plugin-core-server.savedobjectscreateoptions.migrationversion.md) | SavedObjectsMigrationVersion | Information about the migrations that have been applied to this SavedObject. When Kibana starts up, KibanaMigrator detects outdated documents and migrates them based on this value. For each migration that has been applied, the plugin's name is used as a key and the latest migration version as the value. | | [originId](./kibana-plugin-core-server.savedobjectscreateoptions.originid.md) | string | Optional ID of the original saved object, if this object's id was regenerated | | [overwrite](./kibana-plugin-core-server.savedobjectscreateoptions.overwrite.md) | boolean | Overwrite existing documents (defaults to false) | diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsdeleteoptions.force.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsdeleteoptions.force.md new file mode 100644 index 0000000000000..f869d1f863a9f --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectsdeleteoptions.force.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [SavedObjectsDeleteOptions](./kibana-plugin-core-server.savedobjectsdeleteoptions.md) > [force](./kibana-plugin-core-server.savedobjectsdeleteoptions.force.md) + +## SavedObjectsDeleteOptions.force property + +Force deletion of an object that exists in multiple namespaces + +Signature: + +```typescript +force?: boolean; +``` diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsdeleteoptions.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsdeleteoptions.md index 760c30edcdfb5..245819e44d37d 100644 --- a/docs/development/core/server/kibana-plugin-core-server.savedobjectsdeleteoptions.md +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectsdeleteoptions.md @@ -15,5 +15,6 @@ export interface SavedObjectsDeleteOptions extends SavedObjectsBaseOptions | Property | Type | Description | | --- | --- | --- | +| [force](./kibana-plugin-core-server.savedobjectsdeleteoptions.force.md) | boolean | Force deletion of an object that exists in multiple namespaces | | [refresh](./kibana-plugin-core-server.savedobjectsdeleteoptions.refresh.md) | MutatingOperationRefreshSetting | The Elasticsearch Refresh setting for this operation | diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsfindoptions.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsfindoptions.md index 804c83f7c1b48..ce5c20e60ca11 100644 --- a/docs/development/core/server/kibana-plugin-core-server.savedobjectsfindoptions.md +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectsfindoptions.md @@ -29,4 +29,5 @@ export interface SavedObjectsFindOptions | [sortField](./kibana-plugin-core-server.savedobjectsfindoptions.sortfield.md) | string | | | [sortOrder](./kibana-plugin-core-server.savedobjectsfindoptions.sortorder.md) | string | | | [type](./kibana-plugin-core-server.savedobjectsfindoptions.type.md) | string | string[] | | +| [typeToNamespacesMap](./kibana-plugin-core-server.savedobjectsfindoptions.typetonamespacesmap.md) | Map<string, string[] | undefined> | This map defines each type to search for, and the namespace(s) to search for the type in; this is only intended to be used by a saved object client wrapper. If this is defined, it supersedes the type and namespaces fields when building the Elasticsearch query. Any types that are not included in this map will be excluded entirely. If a type is included but its value is undefined, the operation will search for that type in the Default namespace. | diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsfindoptions.typetonamespacesmap.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsfindoptions.typetonamespacesmap.md new file mode 100644 index 0000000000000..8bec759f05580 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectsfindoptions.typetonamespacesmap.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [SavedObjectsFindOptions](./kibana-plugin-core-server.savedobjectsfindoptions.md) > [typeToNamespacesMap](./kibana-plugin-core-server.savedobjectsfindoptions.typetonamespacesmap.md) + +## SavedObjectsFindOptions.typeToNamespacesMap property + +This map defines each type to search for, and the namespace(s) to search for the type in; this is only intended to be used by a saved object client wrapper. If this is defined, it supersedes the `type` and `namespaces` fields when building the Elasticsearch query. Any types that are not included in this map will be excluded entirely. If a type is included but its value is undefined, the operation will search for that type in the Default namespace. + +Signature: + +```typescript +typeToNamespacesMap?: Map; +``` diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsrepository.find.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsrepository.find.md index 1b562263145da..d3e93e7af2aa0 100644 --- a/docs/development/core/server/kibana-plugin-core-server.savedobjectsrepository.find.md +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectsrepository.find.md @@ -7,14 +7,14 @@ Signature: ```typescript -find({ search, defaultSearchOperator, searchFields, rootSearchFields, hasReference, page, perPage, sortField, sortOrder, fields, namespaces, type, filter, preference, }: SavedObjectsFindOptions): Promise>; +find(options: SavedObjectsFindOptions): Promise>; ``` ## Parameters | Parameter | Type | Description | | --- | --- | --- | -| { search, defaultSearchOperator, searchFields, rootSearchFields, hasReference, page, perPage, sortField, sortOrder, fields, namespaces, type, filter, preference, } | SavedObjectsFindOptions | | +| options | SavedObjectsFindOptions | | Returns: diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsrepository.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsrepository.md index 14d3741425987..1d11d5262a9c4 100644 --- a/docs/development/core/server/kibana-plugin-core-server.savedobjectsrepository.md +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectsrepository.md @@ -24,7 +24,7 @@ export declare class SavedObjectsRepository | [delete(type, id, options)](./kibana-plugin-core-server.savedobjectsrepository.delete.md) | | Deletes an object | | [deleteByNamespace(namespace, options)](./kibana-plugin-core-server.savedobjectsrepository.deletebynamespace.md) | | Deletes all objects from the provided namespace. | | [deleteFromNamespaces(type, id, namespaces, options)](./kibana-plugin-core-server.savedobjectsrepository.deletefromnamespaces.md) | | Removes one or more namespaces from a given multi-namespace saved object. If no namespaces remain, the saved object is deleted entirely. This method and \[addToNamespaces\][SavedObjectsRepository.addToNamespaces()](./kibana-plugin-core-server.savedobjectsrepository.addtonamespaces.md) are the only ways to change which Spaces a multi-namespace saved object is shared to. | -| [find({ search, defaultSearchOperator, searchFields, rootSearchFields, hasReference, page, perPage, sortField, sortOrder, fields, namespaces, type, filter, preference, })](./kibana-plugin-core-server.savedobjectsrepository.find.md) | | | +| [find(options)](./kibana-plugin-core-server.savedobjectsrepository.find.md) | | | | [get(type, id, options)](./kibana-plugin-core-server.savedobjectsrepository.get.md) | | Gets a single object | | [incrementCounter(type, id, counterFieldName, options)](./kibana-plugin-core-server.savedobjectsrepository.incrementcounter.md) | | Increases a counter field by one. Creates the document if one doesn't exist for the given id. | | [update(type, id, attributes, options)](./kibana-plugin-core-server.savedobjectsrepository.update.md) | | Updates an object | diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsutils.createemptyfindresponse.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsutils.createemptyfindresponse.md new file mode 100644 index 0000000000000..40e865cb02ce8 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectsutils.createemptyfindresponse.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [SavedObjectsUtils](./kibana-plugin-core-server.savedobjectsutils.md) > [createEmptyFindResponse](./kibana-plugin-core-server.savedobjectsutils.createemptyfindresponse.md) + +## SavedObjectsUtils.createEmptyFindResponse property + +Creates an empty response for a find operation. This is only intended to be used by saved objects client wrappers. + +Signature: + +```typescript +static createEmptyFindResponse: ({ page, perPage, }: SavedObjectsFindOptions) => SavedObjectsFindResponse; +``` diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsutils.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsutils.md index e365dfbcb5142..83831f65bd41a 100644 --- a/docs/development/core/server/kibana-plugin-core-server.savedobjectsutils.md +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectsutils.md @@ -15,6 +15,7 @@ export declare class SavedObjectsUtils | Property | Modifiers | Type | Description | | --- | --- | --- | --- | +| [createEmptyFindResponse](./kibana-plugin-core-server.savedobjectsutils.createemptyfindresponse.md) | static | <T>({ page, perPage, }: SavedObjectsFindOptions) => SavedObjectsFindResponse<T> | Creates an empty response for a find operation. This is only intended to be used by saved objects client wrappers. | | [namespaceIdToString](./kibana-plugin-core-server.savedobjectsutils.namespaceidtostring.md) | static | (namespace?: string | undefined) => string | Converts a given saved object namespace ID to its string representation. All namespace IDs have an identical string representation, with the exception of the undefined namespace ID (which has a namespace string of 'default'). | | [namespaceStringToId](./kibana-plugin-core-server.savedobjectsutils.namespacestringtoid.md) | static | (namespace: string) => string | undefined | Converts a given saved object namespace string to its ID representation. All namespace strings have an identical ID representation, with the exception of the 'default' namespace string (which has a namespace ID of undefined). | diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.duplicateindexpatternerror._constructor_.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.duplicateindexpatternerror._constructor_.md new file mode 100644 index 0000000000000..676f1a2c785f8 --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.duplicateindexpatternerror._constructor_.md @@ -0,0 +1,20 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [DuplicateIndexPatternError](./kibana-plugin-plugins-data-public.duplicateindexpatternerror.md) > [(constructor)](./kibana-plugin-plugins-data-public.duplicateindexpatternerror._constructor_.md) + +## DuplicateIndexPatternError.(constructor) + +Constructs a new instance of the `DuplicateIndexPatternError` class + +Signature: + +```typescript +constructor(message: string); +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| message | string | | + diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.duplicateindexpatternerror.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.duplicateindexpatternerror.md new file mode 100644 index 0000000000000..7ed8f97976464 --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.duplicateindexpatternerror.md @@ -0,0 +1,18 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [DuplicateIndexPatternError](./kibana-plugin-plugins-data-public.duplicateindexpatternerror.md) + +## DuplicateIndexPatternError class + +Signature: + +```typescript +export declare class DuplicateIndexPatternError extends Error +``` + +## Constructors + +| Constructor | Modifiers | Description | +| --- | --- | --- | +| [(constructor)(message)](./kibana-plugin-plugins-data-public.duplicateindexpatternerror._constructor_.md) | | Constructs a new instance of the DuplicateIndexPatternError class | + diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.esfilters.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.esfilters.md index 4422b755faa77..0f362f302104b 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.esfilters.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.esfilters.md @@ -8,7 +8,7 @@ ```typescript esFilters: { - FilterLabel: typeof FilterLabel; + FilterLabel: (props: import("./ui/filter_bar/filter_editor/lib/filter_label").FilterLabelProps) => JSX.Element; FILTERS: typeof FILTERS; FilterStateStore: typeof FilterStateStore; buildEmptyFilter: (isPinned: boolean, index?: string | undefined) => import("../common").Filter; diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.filterbar.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.filterbar.md deleted file mode 100644 index 6d8862323792a..0000000000000 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.filterbar.md +++ /dev/null @@ -1,13 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [FilterBar](./kibana-plugin-plugins-data-public.filterbar.md) - -## FilterBar variable - -Signature: - -```typescript -FilterBar: React.ComponentClass, any> & { - WrappedComponent: React.ComponentType; -} -``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.iessearchrequest.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.iessearchrequest.md index fee34378339af..45cd088ee1203 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.iessearchrequest.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.iessearchrequest.md @@ -7,7 +7,7 @@ Signature: ```typescript -export interface IEsSearchRequest extends IKibanaSearchRequest +export interface IEsSearchRequest extends IKibanaSearchRequest ``` ## Properties @@ -15,5 +15,4 @@ export interface IEsSearchRequest extends IKibanaSearchRequest | Property | Type | Description | | --- | --- | --- | | [indexType](./kibana-plugin-plugins-data-public.iessearchrequest.indextype.md) | string | | -| [params](./kibana-plugin-plugins-data-public.iessearchrequest.params.md) | ISearchRequestParams | | diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.iessearchrequest.params.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.iessearchrequest.params.md deleted file mode 100644 index 24107faa28e8c..0000000000000 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.iessearchrequest.params.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [IEsSearchRequest](./kibana-plugin-plugins-data-public.iessearchrequest.md) > [params](./kibana-plugin-plugins-data-public.iessearchrequest.params.md) - -## IEsSearchRequest.params property - -Signature: - -```typescript -params?: ISearchRequestParams; -``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.iessearchresponse.ispartial.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.iessearchresponse.ispartial.md deleted file mode 100644 index 00a56c6fe9c31..0000000000000 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.iessearchresponse.ispartial.md +++ /dev/null @@ -1,13 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [IEsSearchResponse](./kibana-plugin-plugins-data-public.iessearchresponse.md) > [isPartial](./kibana-plugin-plugins-data-public.iessearchresponse.ispartial.md) - -## IEsSearchResponse.isPartial property - -Indicates whether the results returned are complete or partial - -Signature: - -```typescript -isPartial?: boolean; -``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.iessearchresponse.isrunning.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.iessearchresponse.isrunning.md deleted file mode 100644 index 56fb1a7519811..0000000000000 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.iessearchresponse.isrunning.md +++ /dev/null @@ -1,13 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [IEsSearchResponse](./kibana-plugin-plugins-data-public.iessearchresponse.md) > [isRunning](./kibana-plugin-plugins-data-public.iessearchresponse.isrunning.md) - -## IEsSearchResponse.isRunning property - -Indicates whether async search is still in flight - -Signature: - -```typescript -isRunning?: boolean; -``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.iessearchresponse.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.iessearchresponse.md index 7c9a6aa702463..c8a372edbdb85 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.iessearchresponse.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.iessearchresponse.md @@ -2,19 +2,10 @@ [Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [IEsSearchResponse](./kibana-plugin-plugins-data-public.iessearchresponse.md) -## IEsSearchResponse interface +## IEsSearchResponse type Signature: ```typescript -export interface IEsSearchResponse extends IKibanaSearchResponse +export declare type IEsSearchResponse = IKibanaSearchResponse>; ``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [isPartial](./kibana-plugin-plugins-data-public.iessearchresponse.ispartial.md) | boolean | Indicates whether the results returned are complete or partial | -| [isRunning](./kibana-plugin-plugins-data-public.iessearchresponse.isrunning.md) | boolean | Indicates whether async search is still in flight | -| [rawResponse](./kibana-plugin-plugins-data-public.iessearchresponse.rawresponse.md) | SearchResponse<Source> | | - diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.iessearchresponse.rawresponse.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.iessearchresponse.rawresponse.md deleted file mode 100644 index f4648143ebc2e..0000000000000 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.iessearchresponse.rawresponse.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [IEsSearchResponse](./kibana-plugin-plugins-data-public.iessearchresponse.md) > [rawResponse](./kibana-plugin-plugins-data-public.iessearchresponse.rawresponse.md) - -## IEsSearchResponse.rawResponse property - -Signature: - -```typescript -rawResponse: SearchResponse; -``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.iindexpattern.fieldformatmap.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.iindexpattern.fieldformatmap.md index 2c131c6da9937..60ac95bc21af2 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.iindexpattern.fieldformatmap.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.iindexpattern.fieldformatmap.md @@ -7,8 +7,5 @@ Signature: ```typescript -fieldFormatMap?: Record; +fieldFormatMap?: Record | undefined>; ``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.iindexpattern.getformatterforfield.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.iindexpattern.getformatterforfield.md new file mode 100644 index 0000000000000..7466e4b9cf658 --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.iindexpattern.getformatterforfield.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [IIndexPattern](./kibana-plugin-plugins-data-public.iindexpattern.md) > [getFormatterForField](./kibana-plugin-plugins-data-public.iindexpattern.getformatterforfield.md) + +## IIndexPattern.getFormatterForField property + +Signature: + +```typescript +getFormatterForField?: (field: IndexPatternField | IndexPatternField['spec'] | IFieldType) => FieldFormat; +``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.iindexpattern.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.iindexpattern.md index 1cb89822eb605..ba77e659f0834 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.iindexpattern.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.iindexpattern.md @@ -14,8 +14,9 @@ export interface IIndexPattern | Property | Type | Description | | --- | --- | --- | -| [fieldFormatMap](./kibana-plugin-plugins-data-public.iindexpattern.fieldformatmap.md) | Record<string, {
id: string;
params: unknown;
}> | | +| [fieldFormatMap](./kibana-plugin-plugins-data-public.iindexpattern.fieldformatmap.md) | Record<string, SerializedFieldFormat<unknown> | undefined> | | | [fields](./kibana-plugin-plugins-data-public.iindexpattern.fields.md) | IFieldType[] | | +| [getFormatterForField](./kibana-plugin-plugins-data-public.iindexpattern.getformatterforfield.md) | (field: IndexPatternField | IndexPatternField['spec'] | IFieldType) => FieldFormat | | | [id](./kibana-plugin-plugins-data-public.iindexpattern.id.md) | string | | | [timeFieldName](./kibana-plugin-plugins-data-public.iindexpattern.timefieldname.md) | string | | | [title](./kibana-plugin-plugins-data-public.iindexpattern.title.md) | string | | diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.iindexpatternfieldlist.tospec.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.iindexpatternfieldlist.tospec.md index fd20f2944c5be..0fe62f575a927 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.iindexpatternfieldlist.tospec.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.iindexpatternfieldlist.tospec.md @@ -9,7 +9,7 @@ ```typescript toSpec(options?: { getFormatterForField?: IndexPattern['getFormatterForField']; - }): FieldSpec[]; + }): IndexPatternFieldMap; ``` ## Parameters @@ -20,5 +20,5 @@ toSpec(options?: { Returns: -`FieldSpec[]` +`IndexPatternFieldMap` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.ikibanasearchrequest.debug.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.ikibanasearchrequest.debug.md deleted file mode 100644 index cfb21a78557fd..0000000000000 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.ikibanasearchrequest.debug.md +++ /dev/null @@ -1,13 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [IKibanaSearchRequest](./kibana-plugin-plugins-data-public.ikibanasearchrequest.md) > [debug](./kibana-plugin-plugins-data-public.ikibanasearchrequest.debug.md) - -## IKibanaSearchRequest.debug property - -Optionally tell search strategies to output debug information. - -Signature: - -```typescript -debug?: boolean; -``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.ikibanasearchrequest.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.ikibanasearchrequest.md index 57e0fbe2c19a9..bba051037e29b 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.ikibanasearchrequest.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.ikibanasearchrequest.md @@ -7,13 +7,13 @@ Signature: ```typescript -export interface IKibanaSearchRequest +export interface IKibanaSearchRequest ``` ## Properties | Property | Type | Description | | --- | --- | --- | -| [debug](./kibana-plugin-plugins-data-public.ikibanasearchrequest.debug.md) | boolean | Optionally tell search strategies to output debug information. | | [id](./kibana-plugin-plugins-data-public.ikibanasearchrequest.id.md) | string | An id can be used to uniquely identify this request. | +| [params](./kibana-plugin-plugins-data-public.ikibanasearchrequest.params.md) | Params | | diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.ikibanasearchrequest.params.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.ikibanasearchrequest.params.md new file mode 100644 index 0000000000000..b7e2006a66c14 --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.ikibanasearchrequest.params.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [IKibanaSearchRequest](./kibana-plugin-plugins-data-public.ikibanasearchrequest.md) > [params](./kibana-plugin-plugins-data-public.ikibanasearchrequest.params.md) + +## IKibanaSearchRequest.params property + +Signature: + +```typescript +params?: Params; +``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.ikibanasearchresponse.ispartial.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.ikibanasearchresponse.ispartial.md new file mode 100644 index 0000000000000..702c774eb8818 --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.ikibanasearchresponse.ispartial.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [IKibanaSearchResponse](./kibana-plugin-plugins-data-public.ikibanasearchresponse.md) > [isPartial](./kibana-plugin-plugins-data-public.ikibanasearchresponse.ispartial.md) + +## IKibanaSearchResponse.isPartial property + +Indicates whether the results returned are complete or partial + +Signature: + +```typescript +isPartial?: boolean; +``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.ikibanasearchresponse.isrunning.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.ikibanasearchresponse.isrunning.md new file mode 100644 index 0000000000000..1e625ccff26f9 --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.ikibanasearchresponse.isrunning.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [IKibanaSearchResponse](./kibana-plugin-plugins-data-public.ikibanasearchresponse.md) > [isRunning](./kibana-plugin-plugins-data-public.ikibanasearchresponse.isrunning.md) + +## IKibanaSearchResponse.isRunning property + +Indicates whether search is still in flight + +Signature: + +```typescript +isRunning?: boolean; +``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.ikibanasearchresponse.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.ikibanasearchresponse.md index f7dfd1ddd2f49..159dc8f4ada18 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.ikibanasearchresponse.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.ikibanasearchresponse.md @@ -7,7 +7,7 @@ Signature: ```typescript -export interface IKibanaSearchResponse +export interface IKibanaSearchResponse ``` ## Properties @@ -15,6 +15,9 @@ export interface IKibanaSearchResponse | Property | Type | Description | | --- | --- | --- | | [id](./kibana-plugin-plugins-data-public.ikibanasearchresponse.id.md) | string | Some responses may contain a unique id to identify the request this response came from. | +| [isPartial](./kibana-plugin-plugins-data-public.ikibanasearchresponse.ispartial.md) | boolean | Indicates whether the results returned are complete or partial | +| [isRunning](./kibana-plugin-plugins-data-public.ikibanasearchresponse.isrunning.md) | boolean | Indicates whether search is still in flight | | [loaded](./kibana-plugin-plugins-data-public.ikibanasearchresponse.loaded.md) | number | If relevant to the search strategy, return a loaded number that represents how progress is indicated. | +| [rawResponse](./kibana-plugin-plugins-data-public.ikibanasearchresponse.rawresponse.md) | RawResponse | | | [total](./kibana-plugin-plugins-data-public.ikibanasearchresponse.total.md) | number | If relevant to the search strategy, return a total number that represents how progress is indicated. | diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.ikibanasearchresponse.rawresponse.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.ikibanasearchresponse.rawresponse.md new file mode 100644 index 0000000000000..865c7d795801b --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.ikibanasearchresponse.rawresponse.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [IKibanaSearchResponse](./kibana-plugin-plugins-data-public.ikibanasearchresponse.md) > [rawResponse](./kibana-plugin-plugins-data-public.ikibanasearchresponse.rawresponse.md) + +## IKibanaSearchResponse.rawResponse property + +Signature: + +```typescript +rawResponse: RawResponse; +``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern._constructor_.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern._constructor_.md index a5bb15c963978..f81d03a28ec12 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern._constructor_.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern._constructor_.md @@ -9,13 +9,12 @@ Constructs a new instance of the `IndexPattern` class Signature: ```typescript -constructor(id: string | undefined, { savedObjectsClient, apiClient, patternCache, fieldFormats, indexPatternsService, onNotification, onError, shortDotsEnable, metaFields, }: IndexPatternDeps); +constructor({ spec, fieldFormats, shortDotsEnable, metaFields, }: IndexPatternDeps); ``` ## Parameters | Parameter | Type | Description | | --- | --- | --- | -| id | string | undefined | | -| { savedObjectsClient, apiClient, patternCache, fieldFormats, indexPatternsService, onNotification, onError, shortDotsEnable, metaFields, } | IndexPatternDeps | | +| { spec, fieldFormats, shortDotsEnable, metaFields, } | IndexPatternDeps | | diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern._fetchfields.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern._fetchfields.md deleted file mode 100644 index 8fff8baa71139..0000000000000 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern._fetchfields.md +++ /dev/null @@ -1,15 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [IndexPattern](./kibana-plugin-plugins-data-public.indexpattern.md) > [\_fetchFields](./kibana-plugin-plugins-data-public.indexpattern._fetchfields.md) - -## IndexPattern.\_fetchFields() method - -Signature: - -```typescript -_fetchFields(): Promise; -``` -Returns: - -`Promise` - diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.addscriptedfield.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.addscriptedfield.md index 4bbbd83c65e10..99d2fc00a6b7b 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.addscriptedfield.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.addscriptedfield.md @@ -4,10 +4,12 @@ ## IndexPattern.addScriptedField() method +Add scripted field to field list + Signature: ```typescript -addScriptedField(name: string, script: string, fieldType: string | undefined, lang: string): Promise; +addScriptedField(name: string, script: string, fieldType?: string): Promise; ``` ## Parameters @@ -16,8 +18,7 @@ addScriptedField(name: string, script: string, fieldType: string | undefined, la | --- | --- | --- | | name | string | | | script | string | | -| fieldType | string | undefined | | -| lang | string | | +| fieldType | string | | Returns: diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.create.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.create.md deleted file mode 100644 index 5c122b835f59d..0000000000000 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.create.md +++ /dev/null @@ -1,22 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [IndexPattern](./kibana-plugin-plugins-data-public.indexpattern.md) > [create](./kibana-plugin-plugins-data-public.indexpattern.create.md) - -## IndexPattern.create() method - -Signature: - -```typescript -create(allowOverride?: boolean): Promise; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| allowOverride | boolean | | - -Returns: - -`Promise` - diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.fieldformatmap.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.fieldformatmap.md index b89b244d9826c..904d52fcd5751 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.fieldformatmap.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.fieldformatmap.md @@ -7,5 +7,5 @@ Signature: ```typescript -fieldFormatMap: any; +fieldFormatMap: Record; ``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.fields.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.fields.md index d4dca48c7cd7b..76bc41238526e 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.fields.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.fields.md @@ -8,6 +8,6 @@ ```typescript fields: IIndexPatternFieldList & { - toSpec: () => FieldSpec[]; + toSpec: () => IndexPatternFieldMap; }; ``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.fieldsfetcher.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.fieldsfetcher.md deleted file mode 100644 index 4d44b386a1db1..0000000000000 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.fieldsfetcher.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [IndexPattern](./kibana-plugin-plugins-data-public.indexpattern.md) > [fieldsFetcher](./kibana-plugin-plugins-data-public.indexpattern.fieldsfetcher.md) - -## IndexPattern.fieldsFetcher property - -Signature: - -```typescript -fieldsFetcher: any; -``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.flattenhit.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.flattenhit.md index db28d95197bb3..049c3e5e990f7 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.flattenhit.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.flattenhit.md @@ -7,5 +7,5 @@ Signature: ```typescript -flattenHit: any; +flattenHit: (hit: Record, deep?: boolean) => Record; ``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.formatfield.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.formatfield.md index 5a475d6161ac3..aadaddca6cc85 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.formatfield.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.formatfield.md @@ -7,5 +7,5 @@ Signature: ```typescript -formatField: any; +formatField: FormatFieldFn; ``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.formathit.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.formathit.md index ac515d374a93f..2be76bf1c1e05 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.formathit.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.formathit.md @@ -7,5 +7,8 @@ Signature: ```typescript -formatHit: any; +formatHit: { + (hit: Record, type?: string): any; + formatField: FormatFieldFn; + }; ``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.getassavedobjectbody.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.getassavedobjectbody.md new file mode 100644 index 0000000000000..2c5f30e4889ea --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.getassavedobjectbody.md @@ -0,0 +1,35 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [IndexPattern](./kibana-plugin-plugins-data-public.indexpattern.md) > [getAsSavedObjectBody](./kibana-plugin-plugins-data-public.indexpattern.getassavedobjectbody.md) + +## IndexPattern.getAsSavedObjectBody() method + +Returns index pattern as saved object body for saving + +Signature: + +```typescript +getAsSavedObjectBody(): { + title: string; + timeFieldName: string | undefined; + intervalName: string | undefined; + sourceFilters: string | undefined; + fields: string | undefined; + fieldFormatMap: string | undefined; + type: string | undefined; + typeMeta: string | undefined; + }; +``` +Returns: + +`{ + title: string; + timeFieldName: string | undefined; + intervalName: string | undefined; + sourceFilters: string | undefined; + fields: string | undefined; + fieldFormatMap: string | undefined; + type: string | undefined; + typeMeta: string | undefined; + }` + diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.getformatterforfield.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.getformatterforfield.md index 7984f7aff1d2d..ba31d60b56892 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.getformatterforfield.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.getformatterforfield.md @@ -4,17 +4,19 @@ ## IndexPattern.getFormatterForField() method +Provide a field, get its formatter + Signature: ```typescript -getFormatterForField(field: IndexPatternField | IndexPatternField['spec']): FieldFormat; +getFormatterForField(field: IndexPatternField | IndexPatternField['spec'] | IFieldType): FieldFormat; ``` ## Parameters | Parameter | Type | Description | | --- | --- | --- | -| field | IndexPatternField | IndexPatternField['spec'] | | +| field | IndexPatternField | IndexPatternField['spec'] | IFieldType | | Returns: diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.getoriginalsavedobjectbody.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.getoriginalsavedobjectbody.md new file mode 100644 index 0000000000000..349da63c13ca7 --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.getoriginalsavedobjectbody.md @@ -0,0 +1,22 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [IndexPattern](./kibana-plugin-plugins-data-public.indexpattern.md) > [getOriginalSavedObjectBody](./kibana-plugin-plugins-data-public.indexpattern.getoriginalsavedobjectbody.md) + +## IndexPattern.getOriginalSavedObjectBody property + +Get last saved saved object fields + +Signature: + +```typescript +getOriginalSavedObjectBody: () => { + title?: string | undefined; + timeFieldName?: string | undefined; + intervalName?: string | undefined; + fields?: string | undefined; + sourceFilters?: string | undefined; + fieldFormatMap?: string | undefined; + typeMeta?: string | undefined; + type?: string | undefined; + }; +``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.getsourcefiltering.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.getsourcefiltering.md index 121d32c7c40c8..4ce0144b73882 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.getsourcefiltering.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.getsourcefiltering.md @@ -4,6 +4,8 @@ ## IndexPattern.getSourceFiltering() method +Get the source filtering configuration for that index. + Signature: ```typescript diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.init.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.init.md deleted file mode 100644 index 595992dc82b74..0000000000000 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.init.md +++ /dev/null @@ -1,15 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [IndexPattern](./kibana-plugin-plugins-data-public.indexpattern.md) > [init](./kibana-plugin-plugins-data-public.indexpattern.init.md) - -## IndexPattern.init() method - -Signature: - -```typescript -init(): Promise; -``` -Returns: - -`Promise` - diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.initfromspec.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.initfromspec.md deleted file mode 100644 index 764dd11638221..0000000000000 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.initfromspec.md +++ /dev/null @@ -1,22 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [IndexPattern](./kibana-plugin-plugins-data-public.indexpattern.md) > [initFromSpec](./kibana-plugin-plugins-data-public.indexpattern.initfromspec.md) - -## IndexPattern.initFromSpec() method - -Signature: - -```typescript -initFromSpec(spec: IndexPatternSpec): this; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| spec | IndexPatternSpec | | - -Returns: - -`this` - diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.istimebasedwildcard.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.istimebasedwildcard.md deleted file mode 100644 index 27f99f418a078..0000000000000 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.istimebasedwildcard.md +++ /dev/null @@ -1,15 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [IndexPattern](./kibana-plugin-plugins-data-public.indexpattern.md) > [isTimeBasedWildcard](./kibana-plugin-plugins-data-public.indexpattern.istimebasedwildcard.md) - -## IndexPattern.isTimeBasedWildcard() method - -Signature: - -```typescript -isTimeBasedWildcard(): boolean; -``` -Returns: - -`boolean` - diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.iswildcard.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.iswildcard.md deleted file mode 100644 index e5ea55ef1dd48..0000000000000 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.iswildcard.md +++ /dev/null @@ -1,15 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [IndexPattern](./kibana-plugin-plugins-data-public.indexpattern.md) > [isWildcard](./kibana-plugin-plugins-data-public.indexpattern.iswildcard.md) - -## IndexPattern.isWildcard() method - -Signature: - -```typescript -isWildcard(): boolean; -``` -Returns: - -`boolean` - diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.md index 87ce1e258712a..c07041470d102 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.md @@ -14,22 +14,22 @@ export declare class IndexPattern implements IIndexPattern | Constructor | Modifiers | Description | | --- | --- | --- | -| [(constructor)(id, { savedObjectsClient, apiClient, patternCache, fieldFormats, indexPatternsService, onNotification, onError, shortDotsEnable, metaFields, })](./kibana-plugin-plugins-data-public.indexpattern._constructor_.md) | | Constructs a new instance of the IndexPattern class | +| [(constructor)({ spec, fieldFormats, shortDotsEnable, metaFields, })](./kibana-plugin-plugins-data-public.indexpattern._constructor_.md) | | Constructs a new instance of the IndexPattern class | ## Properties | Property | Modifiers | Type | Description | | --- | --- | --- | --- | -| [fieldFormatMap](./kibana-plugin-plugins-data-public.indexpattern.fieldformatmap.md) | | any | | -| [fields](./kibana-plugin-plugins-data-public.indexpattern.fields.md) | | IIndexPatternFieldList & {
toSpec: () => FieldSpec[];
} | | -| [fieldsFetcher](./kibana-plugin-plugins-data-public.indexpattern.fieldsfetcher.md) | | any | | -| [flattenHit](./kibana-plugin-plugins-data-public.indexpattern.flattenhit.md) | | any | | -| [formatField](./kibana-plugin-plugins-data-public.indexpattern.formatfield.md) | | any | | -| [formatHit](./kibana-plugin-plugins-data-public.indexpattern.formathit.md) | | any | | +| [fieldFormatMap](./kibana-plugin-plugins-data-public.indexpattern.fieldformatmap.md) | | Record<string, any> | | +| [fields](./kibana-plugin-plugins-data-public.indexpattern.fields.md) | | IIndexPatternFieldList & {
toSpec: () => IndexPatternFieldMap;
} | | +| [flattenHit](./kibana-plugin-plugins-data-public.indexpattern.flattenhit.md) | | (hit: Record<string, any>, deep?: boolean) => Record<string, any> | | +| [formatField](./kibana-plugin-plugins-data-public.indexpattern.formatfield.md) | | FormatFieldFn | | +| [formatHit](./kibana-plugin-plugins-data-public.indexpattern.formathit.md) | | {
(hit: Record<string, any>, type?: string): any;
formatField: FormatFieldFn;
} | | +| [getOriginalSavedObjectBody](./kibana-plugin-plugins-data-public.indexpattern.getoriginalsavedobjectbody.md) | | () => {
title?: string | undefined;
timeFieldName?: string | undefined;
intervalName?: string | undefined;
fields?: string | undefined;
sourceFilters?: string | undefined;
fieldFormatMap?: string | undefined;
typeMeta?: string | undefined;
type?: string | undefined;
} | Get last saved saved object fields | | [id](./kibana-plugin-plugins-data-public.indexpattern.id.md) | | string | | | [intervalName](./kibana-plugin-plugins-data-public.indexpattern.intervalname.md) | | string | undefined | | | [metaFields](./kibana-plugin-plugins-data-public.indexpattern.metafields.md) | | string[] | | -| [originalBody](./kibana-plugin-plugins-data-public.indexpattern.originalbody.md) | | {
[key: string]: any;
} | | +| [resetOriginalSavedObjectBody](./kibana-plugin-plugins-data-public.indexpattern.resetoriginalsavedobjectbody.md) | | () => void | Reset last saved saved object fields. used after saving | | [sourceFilters](./kibana-plugin-plugins-data-public.indexpattern.sourcefilters.md) | | SourceFilter[] | | | [timeFieldName](./kibana-plugin-plugins-data-public.indexpattern.timefieldname.md) | | string | undefined | | | [title](./kibana-plugin-plugins-data-public.indexpattern.title.md) | | string | | @@ -41,26 +41,18 @@ export declare class IndexPattern implements IIndexPattern | Method | Modifiers | Description | | --- | --- | --- | -| [\_fetchFields()](./kibana-plugin-plugins-data-public.indexpattern._fetchfields.md) | | | -| [addScriptedField(name, script, fieldType, lang)](./kibana-plugin-plugins-data-public.indexpattern.addscriptedfield.md) | | | -| [create(allowOverride)](./kibana-plugin-plugins-data-public.indexpattern.create.md) | | | +| [addScriptedField(name, script, fieldType)](./kibana-plugin-plugins-data-public.indexpattern.addscriptedfield.md) | | Add scripted field to field list | | [getAggregationRestrictions()](./kibana-plugin-plugins-data-public.indexpattern.getaggregationrestrictions.md) | | | +| [getAsSavedObjectBody()](./kibana-plugin-plugins-data-public.indexpattern.getassavedobjectbody.md) | | Returns index pattern as saved object body for saving | | [getComputedFields()](./kibana-plugin-plugins-data-public.indexpattern.getcomputedfields.md) | | | | [getFieldByName(name)](./kibana-plugin-plugins-data-public.indexpattern.getfieldbyname.md) | | | -| [getFormatterForField(field)](./kibana-plugin-plugins-data-public.indexpattern.getformatterforfield.md) | | | +| [getFormatterForField(field)](./kibana-plugin-plugins-data-public.indexpattern.getformatterforfield.md) | | Provide a field, get its formatter | | [getNonScriptedFields()](./kibana-plugin-plugins-data-public.indexpattern.getnonscriptedfields.md) | | | | [getScriptedFields()](./kibana-plugin-plugins-data-public.indexpattern.getscriptedfields.md) | | | -| [getSourceFiltering()](./kibana-plugin-plugins-data-public.indexpattern.getsourcefiltering.md) | | | +| [getSourceFiltering()](./kibana-plugin-plugins-data-public.indexpattern.getsourcefiltering.md) | | Get the source filtering configuration for that index. | | [getTimeField()](./kibana-plugin-plugins-data-public.indexpattern.gettimefield.md) | | | -| [init()](./kibana-plugin-plugins-data-public.indexpattern.init.md) | | | -| [initFromSpec(spec)](./kibana-plugin-plugins-data-public.indexpattern.initfromspec.md) | | | | [isTimeBased()](./kibana-plugin-plugins-data-public.indexpattern.istimebased.md) | | | -| [isTimeBasedWildcard()](./kibana-plugin-plugins-data-public.indexpattern.istimebasedwildcard.md) | | | | [isTimeNanosBased()](./kibana-plugin-plugins-data-public.indexpattern.istimenanosbased.md) | | | -| [isWildcard()](./kibana-plugin-plugins-data-public.indexpattern.iswildcard.md) | | | -| [popularizeField(fieldName, unit)](./kibana-plugin-plugins-data-public.indexpattern.popularizefield.md) | | | -| [prepBody()](./kibana-plugin-plugins-data-public.indexpattern.prepbody.md) | | | -| [refreshFields()](./kibana-plugin-plugins-data-public.indexpattern.refreshfields.md) | | | -| [removeScriptedField(fieldName)](./kibana-plugin-plugins-data-public.indexpattern.removescriptedfield.md) | | | +| [removeScriptedField(fieldName)](./kibana-plugin-plugins-data-public.indexpattern.removescriptedfield.md) | | Remove scripted field from field list | | [toSpec()](./kibana-plugin-plugins-data-public.indexpattern.tospec.md) | | | diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.originalbody.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.originalbody.md deleted file mode 100644 index 4bc3c76afbae9..0000000000000 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.originalbody.md +++ /dev/null @@ -1,13 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [IndexPattern](./kibana-plugin-plugins-data-public.indexpattern.md) > [originalBody](./kibana-plugin-plugins-data-public.indexpattern.originalbody.md) - -## IndexPattern.originalBody property - -Signature: - -```typescript -originalBody: { - [key: string]: any; - }; -``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.popularizefield.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.popularizefield.md deleted file mode 100644 index eba5382158520..0000000000000 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.popularizefield.md +++ /dev/null @@ -1,23 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [IndexPattern](./kibana-plugin-plugins-data-public.indexpattern.md) > [popularizeField](./kibana-plugin-plugins-data-public.indexpattern.popularizefield.md) - -## IndexPattern.popularizeField() method - -Signature: - -```typescript -popularizeField(fieldName: string, unit?: number): Promise; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| fieldName | string | | -| unit | number | | - -Returns: - -`Promise` - diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.prepbody.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.prepbody.md deleted file mode 100644 index 1d77b2a55860e..0000000000000 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.prepbody.md +++ /dev/null @@ -1,33 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [IndexPattern](./kibana-plugin-plugins-data-public.indexpattern.md) > [prepBody](./kibana-plugin-plugins-data-public.indexpattern.prepbody.md) - -## IndexPattern.prepBody() method - -Signature: - -```typescript -prepBody(): { - title: string; - timeFieldName: string | undefined; - intervalName: string | undefined; - sourceFilters: string | undefined; - fields: string | undefined; - fieldFormatMap: string | undefined; - type: string | undefined; - typeMeta: string | undefined; - }; -``` -Returns: - -`{ - title: string; - timeFieldName: string | undefined; - intervalName: string | undefined; - sourceFilters: string | undefined; - fields: string | undefined; - fieldFormatMap: string | undefined; - type: string | undefined; - typeMeta: string | undefined; - }` - diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.refreshfields.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.refreshfields.md deleted file mode 100644 index 271d0c45a4244..0000000000000 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.refreshfields.md +++ /dev/null @@ -1,15 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [IndexPattern](./kibana-plugin-plugins-data-public.indexpattern.md) > [refreshFields](./kibana-plugin-plugins-data-public.indexpattern.refreshfields.md) - -## IndexPattern.refreshFields() method - -Signature: - -```typescript -refreshFields(): Promise; -``` -Returns: - -`Promise` - diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.removescriptedfield.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.removescriptedfield.md index e902d9c42b082..aaaebdaccca5d 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.removescriptedfield.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.removescriptedfield.md @@ -4,6 +4,8 @@ ## IndexPattern.removeScriptedField() method +Remove scripted field from field list + Signature: ```typescript diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.resetoriginalsavedobjectbody.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.resetoriginalsavedobjectbody.md new file mode 100644 index 0000000000000..6bbc13d8fd410 --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.resetoriginalsavedobjectbody.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [IndexPattern](./kibana-plugin-plugins-data-public.indexpattern.md) > [resetOriginalSavedObjectBody](./kibana-plugin-plugins-data-public.indexpattern.resetoriginalsavedobjectbody.md) + +## IndexPattern.resetOriginalSavedObjectBody property + +Reset last saved saved object fields. used after saving + +Signature: + +```typescript +resetOriginalSavedObjectBody: () => void; +``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternattributes.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternattributes.md index eff2349f053ff..77a8ebb0b2d3f 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternattributes.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternattributes.md @@ -4,12 +4,6 @@ ## IndexPatternAttributes interface -> Warning: This API is now obsolete. -> -> - -Use data plugin interface instead - Signature: ```typescript diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfield.conflictdescriptions.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfield.conflictdescriptions.md index 6d62053726197..9b226266f0b5a 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfield.conflictdescriptions.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfield.conflictdescriptions.md @@ -4,6 +4,8 @@ ## IndexPatternField.conflictDescriptions property +Description of field type conflicts across different indices in the same index pattern + Signature: ```typescript diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfield.count.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfield.count.md index 84c0a75fd206d..1b8e13a38c6d9 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfield.count.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfield.count.md @@ -4,6 +4,8 @@ ## IndexPatternField.count property +Count is used for field popularity + Signature: ```typescript diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfield.lang.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfield.lang.md index 0a8446d40e5ec..b81218eb08886 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfield.lang.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfield.lang.md @@ -4,6 +4,8 @@ ## IndexPatternField.lang property +Script field language + Signature: ```typescript diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfield.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfield.md index 215188ffa2607..4f49a9a8fc3ab 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfield.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfield.md @@ -21,15 +21,15 @@ export declare class IndexPatternField implements IFieldType | Property | Modifiers | Type | Description | | --- | --- | --- | --- | | [aggregatable](./kibana-plugin-plugins-data-public.indexpatternfield.aggregatable.md) | | boolean | | -| [conflictDescriptions](./kibana-plugin-plugins-data-public.indexpatternfield.conflictdescriptions.md) | | Record<string, string[]> | undefined | | -| [count](./kibana-plugin-plugins-data-public.indexpatternfield.count.md) | | number | | +| [conflictDescriptions](./kibana-plugin-plugins-data-public.indexpatternfield.conflictdescriptions.md) | | Record<string, string[]> | undefined | Description of field type conflicts across different indices in the same index pattern | +| [count](./kibana-plugin-plugins-data-public.indexpatternfield.count.md) | | number | Count is used for field popularity | | [displayName](./kibana-plugin-plugins-data-public.indexpatternfield.displayname.md) | | string | | | [esTypes](./kibana-plugin-plugins-data-public.indexpatternfield.estypes.md) | | string[] | undefined | | | [filterable](./kibana-plugin-plugins-data-public.indexpatternfield.filterable.md) | | boolean | | -| [lang](./kibana-plugin-plugins-data-public.indexpatternfield.lang.md) | | string | undefined | | +| [lang](./kibana-plugin-plugins-data-public.indexpatternfield.lang.md) | | string | undefined | Script field language | | [name](./kibana-plugin-plugins-data-public.indexpatternfield.name.md) | | string | | | [readFromDocValues](./kibana-plugin-plugins-data-public.indexpatternfield.readfromdocvalues.md) | | boolean | | -| [script](./kibana-plugin-plugins-data-public.indexpatternfield.script.md) | | string | undefined | | +| [script](./kibana-plugin-plugins-data-public.indexpatternfield.script.md) | | string | undefined | Script field code | | [scripted](./kibana-plugin-plugins-data-public.indexpatternfield.scripted.md) | | boolean | | | [searchable](./kibana-plugin-plugins-data-public.indexpatternfield.searchable.md) | | boolean | | | [sortable](./kibana-plugin-plugins-data-public.indexpatternfield.sortable.md) | | boolean | | diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfield.script.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfield.script.md index 27f9c797c92f2..7501e191d9363 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfield.script.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfield.script.md @@ -4,6 +4,8 @@ ## IndexPatternField.script property +Script field code + Signature: ```typescript diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfield.tospec.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfield.tospec.md index 1d80c90991f55..711d6ad660450 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfield.tospec.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfield.tospec.md @@ -9,24 +9,7 @@ ```typescript toSpec({ getFormatterForField, }?: { getFormatterForField?: IndexPattern['getFormatterForField']; - }): { - count: number; - script: string | undefined; - lang: string | undefined; - conflictDescriptions: Record | undefined; - name: string; - type: string; - esTypes: string[] | undefined; - scripted: boolean; - searchable: boolean; - aggregatable: boolean; - readFromDocValues: boolean; - subType: import("../types").IFieldSubType | undefined; - format: { - id: any; - params: any; - } | undefined; - }; + }): FieldSpec; ``` ## Parameters @@ -37,22 +20,5 @@ toSpec({ getFormatterForField, }?: { Returns: -`{ - count: number; - script: string | undefined; - lang: string | undefined; - conflictDescriptions: Record | undefined; - name: string; - type: string; - esTypes: string[] | undefined; - scripted: boolean; - searchable: boolean; - aggregatable: boolean; - readFromDocValues: boolean; - subType: import("../types").IFieldSubType | undefined; - format: { - id: any; - params: any; - } | undefined; - }` +`FieldSpec` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternselect._constructor_.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternselect._constructor_.md deleted file mode 100644 index 4c08e8c862613..0000000000000 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternselect._constructor_.md +++ /dev/null @@ -1,20 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [IndexPatternSelect](./kibana-plugin-plugins-data-public.indexpatternselect.md) > [(constructor)](./kibana-plugin-plugins-data-public.indexpatternselect._constructor_.md) - -## IndexPatternSelect.(constructor) - -Constructs a new instance of the `IndexPatternSelect` class - -Signature: - -```typescript -constructor(props: IndexPatternSelectProps); -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| props | IndexPatternSelectProps | | - diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternselect.componentdidmount.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternselect.componentdidmount.md deleted file mode 100644 index cf70c2add8742..0000000000000 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternselect.componentdidmount.md +++ /dev/null @@ -1,15 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [IndexPatternSelect](./kibana-plugin-plugins-data-public.indexpatternselect.md) > [componentDidMount](./kibana-plugin-plugins-data-public.indexpatternselect.componentdidmount.md) - -## IndexPatternSelect.componentDidMount() method - -Signature: - -```typescript -componentDidMount(): void; -``` -Returns: - -`void` - diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternselect.componentwillunmount.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternselect.componentwillunmount.md deleted file mode 100644 index 5f11208ecc317..0000000000000 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternselect.componentwillunmount.md +++ /dev/null @@ -1,15 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [IndexPatternSelect](./kibana-plugin-plugins-data-public.indexpatternselect.md) > [componentWillUnmount](./kibana-plugin-plugins-data-public.indexpatternselect.componentwillunmount.md) - -## IndexPatternSelect.componentWillUnmount() method - -Signature: - -```typescript -componentWillUnmount(): void; -``` -Returns: - -`void` - diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternselect.debouncedfetch.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternselect.debouncedfetch.md deleted file mode 100644 index 5238e2f1913e4..0000000000000 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternselect.debouncedfetch.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [IndexPatternSelect](./kibana-plugin-plugins-data-public.indexpatternselect.md) > [debouncedFetch](./kibana-plugin-plugins-data-public.indexpatternselect.debouncedfetch.md) - -## IndexPatternSelect.debouncedFetch property - -Signature: - -```typescript -debouncedFetch: ((searchValue: string) => Promise) & _.Cancelable; -``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternselect.fetchoptions.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternselect.fetchoptions.md deleted file mode 100644 index f5e388a86f4ae..0000000000000 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternselect.fetchoptions.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [IndexPatternSelect](./kibana-plugin-plugins-data-public.indexpatternselect.md) > [fetchOptions](./kibana-plugin-plugins-data-public.indexpatternselect.fetchoptions.md) - -## IndexPatternSelect.fetchOptions property - -Signature: - -```typescript -fetchOptions: (searchValue?: string) => void; -``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternselect.fetchselectedindexpattern.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternselect.fetchselectedindexpattern.md deleted file mode 100644 index d5981c19b99af..0000000000000 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternselect.fetchselectedindexpattern.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [IndexPatternSelect](./kibana-plugin-plugins-data-public.indexpatternselect.md) > [fetchSelectedIndexPattern](./kibana-plugin-plugins-data-public.indexpatternselect.fetchselectedindexpattern.md) - -## IndexPatternSelect.fetchSelectedIndexPattern property - -Signature: - -```typescript -fetchSelectedIndexPattern: (indexPatternId: string) => Promise; -``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternselect.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternselect.md deleted file mode 100644 index 4f4feeb4caa8d..0000000000000 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternselect.md +++ /dev/null @@ -1,37 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [IndexPatternSelect](./kibana-plugin-plugins-data-public.indexpatternselect.md) - -## IndexPatternSelect class - -Signature: - -```typescript -export declare class IndexPatternSelect extends Component -``` - -## Constructors - -| Constructor | Modifiers | Description | -| --- | --- | --- | -| [(constructor)(props)](./kibana-plugin-plugins-data-public.indexpatternselect._constructor_.md) | | Constructs a new instance of the IndexPatternSelect class | - -## Properties - -| Property | Modifiers | Type | Description | -| --- | --- | --- | --- | -| [debouncedFetch](./kibana-plugin-plugins-data-public.indexpatternselect.debouncedfetch.md) | | ((searchValue: string) => Promise<void>) & _.Cancelable | | -| [fetchOptions](./kibana-plugin-plugins-data-public.indexpatternselect.fetchoptions.md) | | (searchValue?: string) => void | | -| [fetchSelectedIndexPattern](./kibana-plugin-plugins-data-public.indexpatternselect.fetchselectedindexpattern.md) | | (indexPatternId: string) => Promise<void> | | -| [onChange](./kibana-plugin-plugins-data-public.indexpatternselect.onchange.md) | | (selectedOptions: any) => void | | -| [state](./kibana-plugin-plugins-data-public.indexpatternselect.state.md) | | IndexPatternSelectState | | - -## Methods - -| Method | Modifiers | Description | -| --- | --- | --- | -| [componentDidMount()](./kibana-plugin-plugins-data-public.indexpatternselect.componentdidmount.md) | | | -| [componentWillUnmount()](./kibana-plugin-plugins-data-public.indexpatternselect.componentwillunmount.md) | | | -| [render()](./kibana-plugin-plugins-data-public.indexpatternselect.render.md) | | | -| [UNSAFE\_componentWillReceiveProps(nextProps)](./kibana-plugin-plugins-data-public.indexpatternselect.unsafe_componentwillreceiveprops.md) | | | - diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternselect.onchange.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternselect.onchange.md deleted file mode 100644 index c0c2a2e6802e9..0000000000000 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternselect.onchange.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [IndexPatternSelect](./kibana-plugin-plugins-data-public.indexpatternselect.md) > [onChange](./kibana-plugin-plugins-data-public.indexpatternselect.onchange.md) - -## IndexPatternSelect.onChange property - -Signature: - -```typescript -onChange: (selectedOptions: any) => void; -``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternselect.render.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternselect.render.md deleted file mode 100644 index 1cb495e7f8795..0000000000000 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternselect.render.md +++ /dev/null @@ -1,15 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [IndexPatternSelect](./kibana-plugin-plugins-data-public.indexpatternselect.md) > [render](./kibana-plugin-plugins-data-public.indexpatternselect.render.md) - -## IndexPatternSelect.render() method - -Signature: - -```typescript -render(): JSX.Element; -``` -Returns: - -`JSX.Element` - diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternselect.state.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternselect.state.md deleted file mode 100644 index 58fbcfe090235..0000000000000 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternselect.state.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [IndexPatternSelect](./kibana-plugin-plugins-data-public.indexpatternselect.md) > [state](./kibana-plugin-plugins-data-public.indexpatternselect.state.md) - -## IndexPatternSelect.state property - -Signature: - -```typescript -state: IndexPatternSelectState; -``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternselect.unsafe_componentwillreceiveprops.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternselect.unsafe_componentwillreceiveprops.md deleted file mode 100644 index de9d6a69e216e..0000000000000 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternselect.unsafe_componentwillreceiveprops.md +++ /dev/null @@ -1,22 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [IndexPatternSelect](./kibana-plugin-plugins-data-public.indexpatternselect.md) > [UNSAFE\_componentWillReceiveProps](./kibana-plugin-plugins-data-public.indexpatternselect.unsafe_componentwillreceiveprops.md) - -## IndexPatternSelect.UNSAFE\_componentWillReceiveProps() method - -Signature: - -```typescript -UNSAFE_componentWillReceiveProps(nextProps: IndexPatternSelectProps): void; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| nextProps | IndexPatternSelectProps | | - -Returns: - -`void` - diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternselectprops.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternselectprops.md new file mode 100644 index 0000000000000..5cfd5e1bc9929 --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternselectprops.md @@ -0,0 +1,16 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [IndexPatternSelectProps](./kibana-plugin-plugins-data-public.indexpatternselectprops.md) + +## IndexPatternSelectProps type + +Signature: + +```typescript +export declare type IndexPatternSelectProps = Required, 'isLoading' | 'onSearchChange' | 'options' | 'selectedOptions' | 'onChange'>, 'placeholder'> & { + onChange: (indexPatternId?: string) => void; + indexPatternId: string; + fieldTypes?: string[]; + onNoIndexPatterns?: () => void; +}; +``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternspec.fields.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternspec.fields.md new file mode 100644 index 0000000000000..386e080dbe6c2 --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternspec.fields.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [IndexPatternSpec](./kibana-plugin-plugins-data-public.indexpatternspec.md) > [fields](./kibana-plugin-plugins-data-public.indexpatternspec.fields.md) + +## IndexPatternSpec.fields property + +Signature: + +```typescript +fields?: IndexPatternFieldMap; +``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternspec.id.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternspec.id.md new file mode 100644 index 0000000000000..55eadbf36c660 --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternspec.id.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [IndexPatternSpec](./kibana-plugin-plugins-data-public.indexpatternspec.md) > [id](./kibana-plugin-plugins-data-public.indexpatternspec.id.md) + +## IndexPatternSpec.id property + +Signature: + +```typescript +id?: string; +``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternspec.intervalname.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternspec.intervalname.md new file mode 100644 index 0000000000000..98748661256da --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternspec.intervalname.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [IndexPatternSpec](./kibana-plugin-plugins-data-public.indexpatternspec.md) > [intervalName](./kibana-plugin-plugins-data-public.indexpatternspec.intervalname.md) + +## IndexPatternSpec.intervalName property + +Signature: + +```typescript +intervalName?: string; +``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternspec.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternspec.md new file mode 100644 index 0000000000000..74c4df126e1bf --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternspec.md @@ -0,0 +1,26 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [IndexPatternSpec](./kibana-plugin-plugins-data-public.indexpatternspec.md) + +## IndexPatternSpec interface + +Signature: + +```typescript +export interface IndexPatternSpec +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [fields](./kibana-plugin-plugins-data-public.indexpatternspec.fields.md) | IndexPatternFieldMap | | +| [id](./kibana-plugin-plugins-data-public.indexpatternspec.id.md) | string | | +| [intervalName](./kibana-plugin-plugins-data-public.indexpatternspec.intervalname.md) | string | | +| [sourceFilters](./kibana-plugin-plugins-data-public.indexpatternspec.sourcefilters.md) | SourceFilter[] | | +| [timeFieldName](./kibana-plugin-plugins-data-public.indexpatternspec.timefieldname.md) | string | | +| [title](./kibana-plugin-plugins-data-public.indexpatternspec.title.md) | string | | +| [type](./kibana-plugin-plugins-data-public.indexpatternspec.type.md) | string | | +| [typeMeta](./kibana-plugin-plugins-data-public.indexpatternspec.typemeta.md) | TypeMeta | | +| [version](./kibana-plugin-plugins-data-public.indexpatternspec.version.md) | string | | + diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternspec.sourcefilters.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternspec.sourcefilters.md new file mode 100644 index 0000000000000..cda5285730135 --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternspec.sourcefilters.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [IndexPatternSpec](./kibana-plugin-plugins-data-public.indexpatternspec.md) > [sourceFilters](./kibana-plugin-plugins-data-public.indexpatternspec.sourcefilters.md) + +## IndexPatternSpec.sourceFilters property + +Signature: + +```typescript +sourceFilters?: SourceFilter[]; +``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternspec.timefieldname.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternspec.timefieldname.md new file mode 100644 index 0000000000000..a527e3ac0658b --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternspec.timefieldname.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [IndexPatternSpec](./kibana-plugin-plugins-data-public.indexpatternspec.md) > [timeFieldName](./kibana-plugin-plugins-data-public.indexpatternspec.timefieldname.md) + +## IndexPatternSpec.timeFieldName property + +Signature: + +```typescript +timeFieldName?: string; +``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternspec.title.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternspec.title.md new file mode 100644 index 0000000000000..4cc6d3c2524a7 --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternspec.title.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [IndexPatternSpec](./kibana-plugin-plugins-data-public.indexpatternspec.md) > [title](./kibana-plugin-plugins-data-public.indexpatternspec.title.md) + +## IndexPatternSpec.title property + +Signature: + +```typescript +title?: string; +``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternspec.type.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternspec.type.md new file mode 100644 index 0000000000000..d1c49be1b706f --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternspec.type.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [IndexPatternSpec](./kibana-plugin-plugins-data-public.indexpatternspec.md) > [type](./kibana-plugin-plugins-data-public.indexpatternspec.type.md) + +## IndexPatternSpec.type property + +Signature: + +```typescript +type?: string; +``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternspec.typemeta.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternspec.typemeta.md new file mode 100644 index 0000000000000..9303047e905d3 --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternspec.typemeta.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [IndexPatternSpec](./kibana-plugin-plugins-data-public.indexpatternspec.md) > [typeMeta](./kibana-plugin-plugins-data-public.indexpatternspec.typemeta.md) + +## IndexPatternSpec.typeMeta property + +Signature: + +```typescript +typeMeta?: TypeMeta; +``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternspec.version.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternspec.version.md new file mode 100644 index 0000000000000..43f7cf0226fb0 --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternspec.version.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [IndexPatternSpec](./kibana-plugin-plugins-data-public.indexpatternspec.md) > [version](./kibana-plugin-plugins-data-public.indexpatternspec.version.md) + +## IndexPatternSpec.version property + +Signature: + +```typescript +version?: string; +``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternsservice._constructor_.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternsservice._constructor_.md new file mode 100644 index 0000000000000..ab397efb1fe0e --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternsservice._constructor_.md @@ -0,0 +1,20 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [IndexPatternsService](./kibana-plugin-plugins-data-public.indexpatternsservice.md) > [(constructor)](./kibana-plugin-plugins-data-public.indexpatternsservice._constructor_.md) + +## IndexPatternsService.(constructor) + +Constructs a new instance of the `IndexPatternsService` class + +Signature: + +```typescript +constructor({ uiSettings, savedObjectsClient, apiClient, fieldFormats, onNotification, onError, onRedirectNoIndexPattern, }: IndexPatternsServiceDeps); +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| { uiSettings, savedObjectsClient, apiClient, fieldFormats, onNotification, onError, onRedirectNoIndexPattern, } | IndexPatternsServiceDeps | | + diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternsservice.clearcache.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternsservice.clearcache.md new file mode 100644 index 0000000000000..b371218325086 --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternsservice.clearcache.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [IndexPatternsService](./kibana-plugin-plugins-data-public.indexpatternsservice.md) > [clearCache](./kibana-plugin-plugins-data-public.indexpatternsservice.clearcache.md) + +## IndexPatternsService.clearCache property + +Clear index pattern list cache + +Signature: + +```typescript +clearCache: (id?: string | undefined) => void; +``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternsservice.create.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternsservice.create.md new file mode 100644 index 0000000000000..d7152ba617cc6 --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternsservice.create.md @@ -0,0 +1,25 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [IndexPatternsService](./kibana-plugin-plugins-data-public.indexpatternsservice.md) > [create](./kibana-plugin-plugins-data-public.indexpatternsservice.create.md) + +## IndexPatternsService.create() method + +Create a new index pattern instance + +Signature: + +```typescript +create(spec: IndexPatternSpec, skipFetchFields?: boolean): Promise; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| spec | IndexPatternSpec | | +| skipFetchFields | boolean | | + +Returns: + +`Promise` + diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternsservice.createandsave.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternsservice.createandsave.md new file mode 100644 index 0000000000000..eebfbb506fb77 --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternsservice.createandsave.md @@ -0,0 +1,26 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [IndexPatternsService](./kibana-plugin-plugins-data-public.indexpatternsservice.md) > [createAndSave](./kibana-plugin-plugins-data-public.indexpatternsservice.createandsave.md) + +## IndexPatternsService.createAndSave() method + +Create a new index pattern and save it right away + +Signature: + +```typescript +createAndSave(spec: IndexPatternSpec, override?: boolean, skipFetchFields?: boolean): Promise; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| spec | IndexPatternSpec | | +| override | boolean | | +| skipFetchFields | boolean | | + +Returns: + +`Promise` + diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternsservice.createsavedobject.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternsservice.createsavedobject.md new file mode 100644 index 0000000000000..8efb33c423b01 --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternsservice.createsavedobject.md @@ -0,0 +1,25 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [IndexPatternsService](./kibana-plugin-plugins-data-public.indexpatternsservice.md) > [createSavedObject](./kibana-plugin-plugins-data-public.indexpatternsservice.createsavedobject.md) + +## IndexPatternsService.createSavedObject() method + +Save a new index pattern + +Signature: + +```typescript +createSavedObject(indexPattern: IndexPattern, override?: boolean): Promise; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| indexPattern | IndexPattern | | +| override | boolean | | + +Returns: + +`Promise` + diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternsservice.delete.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternsservice.delete.md new file mode 100644 index 0000000000000..aba31ab2c0d29 --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternsservice.delete.md @@ -0,0 +1,24 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [IndexPatternsService](./kibana-plugin-plugins-data-public.indexpatternsservice.md) > [delete](./kibana-plugin-plugins-data-public.indexpatternsservice.delete.md) + +## IndexPatternsService.delete() method + +Deletes an index pattern from .kibana index + +Signature: + +```typescript +delete(indexPatternId: string): Promise<{}>; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| indexPatternId | string | | + +Returns: + +`Promise<{}>` + diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternsservice.ensuredefaultindexpattern.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternsservice.ensuredefaultindexpattern.md new file mode 100644 index 0000000000000..3b6a8c7e4a04f --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternsservice.ensuredefaultindexpattern.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [IndexPatternsService](./kibana-plugin-plugins-data-public.indexpatternsservice.md) > [ensureDefaultIndexPattern](./kibana-plugin-plugins-data-public.indexpatternsservice.ensuredefaultindexpattern.md) + +## IndexPatternsService.ensureDefaultIndexPattern property + +Signature: + +```typescript +ensureDefaultIndexPattern: EnsureDefaultIndexPattern; +``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternsservice.fieldarraytomap.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternsservice.fieldarraytomap.md new file mode 100644 index 0000000000000..ed365fe03f980 --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternsservice.fieldarraytomap.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [IndexPatternsService](./kibana-plugin-plugins-data-public.indexpatternsservice.md) > [fieldArrayToMap](./kibana-plugin-plugins-data-public.indexpatternsservice.fieldarraytomap.md) + +## IndexPatternsService.fieldArrayToMap property + +Converts field array to map + +Signature: + +```typescript +fieldArrayToMap: (fields: FieldSpec[]) => Record; +``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternsservice.get.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternsservice.get.md new file mode 100644 index 0000000000000..4aad6df6b413b --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternsservice.get.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [IndexPatternsService](./kibana-plugin-plugins-data-public.indexpatternsservice.md) > [get](./kibana-plugin-plugins-data-public.indexpatternsservice.get.md) + +## IndexPatternsService.get property + +Get an index pattern by id. Cache optimized + +Signature: + +```typescript +get: (id: string) => Promise; +``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternsservice.getcache.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternsservice.getcache.md new file mode 100644 index 0000000000000..ad2a167bd8c74 --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternsservice.getcache.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [IndexPatternsService](./kibana-plugin-plugins-data-public.indexpatternsservice.md) > [getCache](./kibana-plugin-plugins-data-public.indexpatternsservice.getcache.md) + +## IndexPatternsService.getCache property + +Signature: + +```typescript +getCache: () => Promise[] | null | undefined>; +``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternsservice.getdefault.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternsservice.getdefault.md new file mode 100644 index 0000000000000..01d4efeffe921 --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternsservice.getdefault.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [IndexPatternsService](./kibana-plugin-plugins-data-public.indexpatternsservice.md) > [getDefault](./kibana-plugin-plugins-data-public.indexpatternsservice.getdefault.md) + +## IndexPatternsService.getDefault property + +Get default index pattern + +Signature: + +```typescript +getDefault: () => Promise; +``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternsservice.getfieldsforindexpattern.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternsservice.getfieldsforindexpattern.md new file mode 100644 index 0000000000000..c06c3c6f68492 --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternsservice.getfieldsforindexpattern.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [IndexPatternsService](./kibana-plugin-plugins-data-public.indexpatternsservice.md) > [getFieldsForIndexPattern](./kibana-plugin-plugins-data-public.indexpatternsservice.getfieldsforindexpattern.md) + +## IndexPatternsService.getFieldsForIndexPattern property + +Get field list by providing an index patttern (or spec) + +Signature: + +```typescript +getFieldsForIndexPattern: (indexPattern: IndexPattern | IndexPatternSpec, options?: GetFieldsOptions) => Promise; +``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternsservice.getfieldsforwildcard.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternsservice.getfieldsforwildcard.md new file mode 100644 index 0000000000000..aec84866b9e58 --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternsservice.getfieldsforwildcard.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [IndexPatternsService](./kibana-plugin-plugins-data-public.indexpatternsservice.md) > [getFieldsForWildcard](./kibana-plugin-plugins-data-public.indexpatternsservice.getfieldsforwildcard.md) + +## IndexPatternsService.getFieldsForWildcard property + +Get field list by providing { pattern } + +Signature: + +```typescript +getFieldsForWildcard: (options?: GetFieldsOptions) => Promise; +``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternsservice.getids.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternsservice.getids.md new file mode 100644 index 0000000000000..a012e0dc9d9c5 --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternsservice.getids.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [IndexPatternsService](./kibana-plugin-plugins-data-public.indexpatternsservice.md) > [getIds](./kibana-plugin-plugins-data-public.indexpatternsservice.getids.md) + +## IndexPatternsService.getIds property + +Get list of index pattern ids + +Signature: + +```typescript +getIds: (refresh?: boolean) => Promise; +``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternsservice.getidswithtitle.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternsservice.getidswithtitle.md new file mode 100644 index 0000000000000..7d29ced66afa8 --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternsservice.getidswithtitle.md @@ -0,0 +1,16 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [IndexPatternsService](./kibana-plugin-plugins-data-public.indexpatternsservice.md) > [getIdsWithTitle](./kibana-plugin-plugins-data-public.indexpatternsservice.getidswithtitle.md) + +## IndexPatternsService.getIdsWithTitle property + +Get list of index pattern ids with titles + +Signature: + +```typescript +getIdsWithTitle: (refresh?: boolean) => Promise>; +``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternsservice.gettitles.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternsservice.gettitles.md new file mode 100644 index 0000000000000..04cc294a79dfc --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternsservice.gettitles.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [IndexPatternsService](./kibana-plugin-plugins-data-public.indexpatternsservice.md) > [getTitles](./kibana-plugin-plugins-data-public.indexpatternsservice.gettitles.md) + +## IndexPatternsService.getTitles property + +Get list of index pattern titles + +Signature: + +```typescript +getTitles: (refresh?: boolean) => Promise; +``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternsservice.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternsservice.md new file mode 100644 index 0000000000000..34df8656e9175 --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternsservice.md @@ -0,0 +1,47 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [IndexPatternsService](./kibana-plugin-plugins-data-public.indexpatternsservice.md) + +## IndexPatternsService class + +Signature: + +```typescript +export declare class IndexPatternsService +``` + +## Constructors + +| Constructor | Modifiers | Description | +| --- | --- | --- | +| [(constructor)({ uiSettings, savedObjectsClient, apiClient, fieldFormats, onNotification, onError, onRedirectNoIndexPattern, })](./kibana-plugin-plugins-data-public.indexpatternsservice._constructor_.md) | | Constructs a new instance of the IndexPatternsService class | + +## Properties + +| Property | Modifiers | Type | Description | +| --- | --- | --- | --- | +| [clearCache](./kibana-plugin-plugins-data-public.indexpatternsservice.clearcache.md) | | (id?: string | undefined) => void | Clear index pattern list cache | +| [ensureDefaultIndexPattern](./kibana-plugin-plugins-data-public.indexpatternsservice.ensuredefaultindexpattern.md) | | EnsureDefaultIndexPattern | | +| [fieldArrayToMap](./kibana-plugin-plugins-data-public.indexpatternsservice.fieldarraytomap.md) | | (fields: FieldSpec[]) => Record<string, FieldSpec> | Converts field array to map | +| [get](./kibana-plugin-plugins-data-public.indexpatternsservice.get.md) | | (id: string) => Promise<IndexPattern> | Get an index pattern by id. Cache optimized | +| [getCache](./kibana-plugin-plugins-data-public.indexpatternsservice.getcache.md) | | () => Promise<SavedObject<IndexPatternSavedObjectAttrs>[] | null | undefined> | | +| [getDefault](./kibana-plugin-plugins-data-public.indexpatternsservice.getdefault.md) | | () => Promise<IndexPattern | null> | Get default index pattern | +| [getFieldsForIndexPattern](./kibana-plugin-plugins-data-public.indexpatternsservice.getfieldsforindexpattern.md) | | (indexPattern: IndexPattern | IndexPatternSpec, options?: GetFieldsOptions) => Promise<any> | Get field list by providing an index patttern (or spec) | +| [getFieldsForWildcard](./kibana-plugin-plugins-data-public.indexpatternsservice.getfieldsforwildcard.md) | | (options?: GetFieldsOptions) => Promise<any> | Get field list by providing { pattern } | +| [getIds](./kibana-plugin-plugins-data-public.indexpatternsservice.getids.md) | | (refresh?: boolean) => Promise<string[]> | Get list of index pattern ids | +| [getIdsWithTitle](./kibana-plugin-plugins-data-public.indexpatternsservice.getidswithtitle.md) | | (refresh?: boolean) => Promise<Array<{
id: string;
title: string;
}>> | Get list of index pattern ids with titles | +| [getTitles](./kibana-plugin-plugins-data-public.indexpatternsservice.gettitles.md) | | (refresh?: boolean) => Promise<string[]> | Get list of index pattern titles | +| [refreshFields](./kibana-plugin-plugins-data-public.indexpatternsservice.refreshfields.md) | | (indexPattern: IndexPattern) => Promise<void> | Refresh field list for a given index pattern | +| [savedObjectToSpec](./kibana-plugin-plugins-data-public.indexpatternsservice.savedobjecttospec.md) | | (savedObject: SavedObject<IndexPatternAttributes>) => IndexPatternSpec | Converts index pattern saved object to index pattern spec | +| [setDefault](./kibana-plugin-plugins-data-public.indexpatternsservice.setdefault.md) | | (id: string, force?: boolean) => Promise<void> | Optionally set default index pattern, unless force = true | + +## Methods + +| Method | Modifiers | Description | +| --- | --- | --- | +| [create(spec, skipFetchFields)](./kibana-plugin-plugins-data-public.indexpatternsservice.create.md) | | Create a new index pattern instance | +| [createAndSave(spec, override, skipFetchFields)](./kibana-plugin-plugins-data-public.indexpatternsservice.createandsave.md) | | Create a new index pattern and save it right away | +| [createSavedObject(indexPattern, override)](./kibana-plugin-plugins-data-public.indexpatternsservice.createsavedobject.md) | | Save a new index pattern | +| [delete(indexPatternId)](./kibana-plugin-plugins-data-public.indexpatternsservice.delete.md) | | Deletes an index pattern from .kibana index | +| [updateSavedObject(indexPattern, saveAttempts, ignoreErrors)](./kibana-plugin-plugins-data-public.indexpatternsservice.updatesavedobject.md) | | Save existing index pattern. Will attempt to merge differences if there are conflicts | + diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternsservice.refreshfields.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternsservice.refreshfields.md new file mode 100644 index 0000000000000..b7c47efbb445a --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternsservice.refreshfields.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [IndexPatternsService](./kibana-plugin-plugins-data-public.indexpatternsservice.md) > [refreshFields](./kibana-plugin-plugins-data-public.indexpatternsservice.refreshfields.md) + +## IndexPatternsService.refreshFields property + +Refresh field list for a given index pattern + +Signature: + +```typescript +refreshFields: (indexPattern: IndexPattern) => Promise; +``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternsservice.savedobjecttospec.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternsservice.savedobjecttospec.md new file mode 100644 index 0000000000000..7bd40c9cafd42 --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternsservice.savedobjecttospec.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [IndexPatternsService](./kibana-plugin-plugins-data-public.indexpatternsservice.md) > [savedObjectToSpec](./kibana-plugin-plugins-data-public.indexpatternsservice.savedobjecttospec.md) + +## IndexPatternsService.savedObjectToSpec property + +Converts index pattern saved object to index pattern spec + +Signature: + +```typescript +savedObjectToSpec: (savedObject: SavedObject) => IndexPatternSpec; +``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternsservice.setdefault.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternsservice.setdefault.md new file mode 100644 index 0000000000000..2bf8eaa03d1ae --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternsservice.setdefault.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [IndexPatternsService](./kibana-plugin-plugins-data-public.indexpatternsservice.md) > [setDefault](./kibana-plugin-plugins-data-public.indexpatternsservice.setdefault.md) + +## IndexPatternsService.setDefault property + +Optionally set default index pattern, unless force = true + +Signature: + +```typescript +setDefault: (id: string, force?: boolean) => Promise; +``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternsservice.updatesavedobject.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternsservice.updatesavedobject.md new file mode 100644 index 0000000000000..5fc16c70de7ed --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternsservice.updatesavedobject.md @@ -0,0 +1,26 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [IndexPatternsService](./kibana-plugin-plugins-data-public.indexpatternsservice.md) > [updateSavedObject](./kibana-plugin-plugins-data-public.indexpatternsservice.updatesavedobject.md) + +## IndexPatternsService.updateSavedObject() method + +Save existing index pattern. Will attempt to merge differences if there are conflicts + +Signature: + +```typescript +updateSavedObject(indexPattern: IndexPattern, saveAttempts?: number, ignoreErrors?: boolean): Promise; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| indexPattern | IndexPattern | | +| saveAttempts | number | | +| ignoreErrors | boolean | | + +Returns: + +`Promise` + diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.iscompleteresponse.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.iscompleteresponse.md new file mode 100644 index 0000000000000..e17e453ecb749 --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.iscompleteresponse.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [isCompleteResponse](./kibana-plugin-plugins-data-public.iscompleteresponse.md) + +## isCompleteResponse variable + +Signature: + +```typescript +isCompleteResponse: (response?: IKibanaSearchResponse | undefined) => boolean | undefined +``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.isearchgeneric.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.isearchgeneric.md index 861b59e73ef04..025ca6681d39b 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.isearchgeneric.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.isearchgeneric.md @@ -7,5 +7,5 @@ Signature: ```typescript -export declare type ISearchGeneric = (request: SearchStrategyRequest, options?: ISearchOptions) => Observable; +export declare type ISearchGeneric = (request: SearchStrategyRequest, options?: ISearchOptions) => Observable; ``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.isearchstart.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.isearchstart.md index cee213fc6e7e3..5defe4a647614 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.isearchstart.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.isearchstart.md @@ -19,4 +19,5 @@ export interface ISearchStart | [aggs](./kibana-plugin-plugins-data-public.isearchstart.aggs.md) | AggsStart | agg config sub service [AggsStart](./kibana-plugin-plugins-data-public.aggsstart.md) | | [search](./kibana-plugin-plugins-data-public.isearchstart.search.md) | ISearchGeneric | low level search [ISearchGeneric](./kibana-plugin-plugins-data-public.isearchgeneric.md) | | [searchSource](./kibana-plugin-plugins-data-public.isearchstart.searchsource.md) | ISearchStartSearchSource | high level search [ISearchStartSearchSource](./kibana-plugin-plugins-data-public.isearchstartsearchsource.md) | +| [showError](./kibana-plugin-plugins-data-public.isearchstart.showerror.md) | (e: Error) => void | | diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.isearchstart.showerror.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.isearchstart.showerror.md new file mode 100644 index 0000000000000..fb14057d83d5c --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.isearchstart.showerror.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [ISearchStart](./kibana-plugin-plugins-data-public.isearchstart.md) > [showError](./kibana-plugin-plugins-data-public.isearchstart.showerror.md) + +## ISearchStart.showError property + +Signature: + +```typescript +showError: (e: Error) => void; +``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.iserrorresponse.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.iserrorresponse.md new file mode 100644 index 0000000000000..e4ac35f19e959 --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.iserrorresponse.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [isErrorResponse](./kibana-plugin-plugins-data-public.iserrorresponse.md) + +## isErrorResponse variable + +Signature: + +```typescript +isErrorResponse: (response?: IKibanaSearchResponse | undefined) => boolean | undefined +``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.ispartialresponse.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.ispartialresponse.md new file mode 100644 index 0000000000000..4b707ceeacc89 --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.ispartialresponse.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [isPartialResponse](./kibana-plugin-plugins-data-public.ispartialresponse.md) + +## isPartialResponse variable + +Signature: + +```typescript +isPartialResponse: (response?: IKibanaSearchResponse | undefined) => boolean | undefined +``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.md index f51549c81fb62..f8897a059377d 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.md @@ -11,16 +11,18 @@ | [AggConfig](./kibana-plugin-plugins-data-public.aggconfig.md) | | | [AggConfigs](./kibana-plugin-plugins-data-public.aggconfigs.md) | | | [AggParamType](./kibana-plugin-plugins-data-public.aggparamtype.md) | | +| [DuplicateIndexPatternError](./kibana-plugin-plugins-data-public.duplicateindexpatternerror.md) | | | [FieldFormat](./kibana-plugin-plugins-data-public.fieldformat.md) | | | [FilterManager](./kibana-plugin-plugins-data-public.filtermanager.md) | | | [IndexPattern](./kibana-plugin-plugins-data-public.indexpattern.md) | | | [IndexPatternField](./kibana-plugin-plugins-data-public.indexpatternfield.md) | | -| [IndexPatternSelect](./kibana-plugin-plugins-data-public.indexpatternselect.md) | | +| [IndexPatternsService](./kibana-plugin-plugins-data-public.indexpatternsservice.md) | | | [OptionedParamType](./kibana-plugin-plugins-data-public.optionedparamtype.md) | | +| [PainlessError](./kibana-plugin-plugins-data-public.painlesserror.md) | | | [Plugin](./kibana-plugin-plugins-data-public.plugin.md) | | -| [RequestTimeoutError](./kibana-plugin-plugins-data-public.requesttimeouterror.md) | Class used to signify that a request timed out. Useful for applications to conditionally handle this type of error differently than other errors. | | [SearchInterceptor](./kibana-plugin-plugins-data-public.searchinterceptor.md) | | | [SearchSource](./kibana-plugin-plugins-data-public.searchsource.md) | \* | +| [SearchTimeoutError](./kibana-plugin-plugins-data-public.searchtimeouterror.md) | Request Failure - When an entire multi request fails | | [TimeHistory](./kibana-plugin-plugins-data-public.timehistory.md) | | ## Enumerations @@ -33,6 +35,7 @@ | [METRIC\_TYPES](./kibana-plugin-plugins-data-public.metric_types.md) | | | [QuerySuggestionTypes](./kibana-plugin-plugins-data-public.querysuggestiontypes.md) | | | [SortDirection](./kibana-plugin-plugins-data-public.sortdirection.md) | | +| [TimeoutErrorMode](./kibana-plugin-plugins-data-public.timeouterrormode.md) | | ## Functions @@ -57,17 +60,16 @@ | [EsQueryConfig](./kibana-plugin-plugins-data-public.esqueryconfig.md) | | | [FieldFormatConfig](./kibana-plugin-plugins-data-public.fieldformatconfig.md) | | | [FieldMappingSpec](./kibana-plugin-plugins-data-public.fieldmappingspec.md) | | -| [Filter](./kibana-plugin-plugins-data-public.filter.md) | | | [IDataPluginServices](./kibana-plugin-plugins-data-public.idatapluginservices.md) | | | [IEsSearchRequest](./kibana-plugin-plugins-data-public.iessearchrequest.md) | | -| [IEsSearchResponse](./kibana-plugin-plugins-data-public.iessearchresponse.md) | | | [IFieldSubType](./kibana-plugin-plugins-data-public.ifieldsubtype.md) | | | [IFieldType](./kibana-plugin-plugins-data-public.ifieldtype.md) | | | [IIndexPattern](./kibana-plugin-plugins-data-public.iindexpattern.md) | | | [IIndexPatternFieldList](./kibana-plugin-plugins-data-public.iindexpatternfieldlist.md) | | | [IKibanaSearchRequest](./kibana-plugin-plugins-data-public.ikibanasearchrequest.md) | | | [IKibanaSearchResponse](./kibana-plugin-plugins-data-public.ikibanasearchresponse.md) | | -| [IndexPatternAttributes](./kibana-plugin-plugins-data-public.indexpatternattributes.md) | Use data plugin interface instead | +| [IndexPatternAttributes](./kibana-plugin-plugins-data-public.indexpatternattributes.md) | | +| [IndexPatternSpec](./kibana-plugin-plugins-data-public.indexpatternspec.md) | | | [IndexPatternTypeMeta](./kibana-plugin-plugins-data-public.indexpatterntypemeta.md) | | | [ISearchOptions](./kibana-plugin-plugins-data-public.isearchoptions.md) | | | [ISearchSetup](./kibana-plugin-plugins-data-public.isearchsetup.md) | The setup contract exposed by the Search plugin exposes the search strategy extension point. | @@ -75,9 +77,9 @@ | [ISearchStartSearchSource](./kibana-plugin-plugins-data-public.isearchstartsearchsource.md) | high level search service | | [KueryNode](./kibana-plugin-plugins-data-public.kuerynode.md) | | | [OptionedValueProp](./kibana-plugin-plugins-data-public.optionedvalueprop.md) | | -| [Query](./kibana-plugin-plugins-data-public.query.md) | | | [QueryState](./kibana-plugin-plugins-data-public.querystate.md) | All query state service state | | [QueryStateChange](./kibana-plugin-plugins-data-public.querystatechange.md) | | +| [QueryStringInputProps](./kibana-plugin-plugins-data-public.querystringinputprops.md) | | | [QuerySuggestionBasic](./kibana-plugin-plugins-data-public.querysuggestionbasic.md) | \* | | [QuerySuggestionField](./kibana-plugin-plugins-data-public.querysuggestionfield.md) | \* | | [QuerySuggestionGetFnArgs](./kibana-plugin-plugins-data-public.querysuggestiongetfnargs.md) | \* | @@ -90,7 +92,6 @@ | [SearchSourceFields](./kibana-plugin-plugins-data-public.searchsourcefields.md) | search source fields | | [TabbedAggColumn](./kibana-plugin-plugins-data-public.tabbedaggcolumn.md) | \* | | [TabbedTable](./kibana-plugin-plugins-data-public.tabbedtable.md) | \* | -| [TimeRange](./kibana-plugin-plugins-data-public.timerange.md) | | ## Variables @@ -111,12 +112,14 @@ | [extractSearchSourceReferences](./kibana-plugin-plugins-data-public.extractsearchsourcereferences.md) | | | [fieldFormats](./kibana-plugin-plugins-data-public.fieldformats.md) | | | [fieldList](./kibana-plugin-plugins-data-public.fieldlist.md) | | -| [FilterBar](./kibana-plugin-plugins-data-public.filterbar.md) | | | [getKbnTypeNames](./kibana-plugin-plugins-data-public.getkbntypenames.md) | Get the esTypes known by all kbnFieldTypes {Array} | | [indexPatterns](./kibana-plugin-plugins-data-public.indexpatterns.md) | | | [injectSearchSourceReferences](./kibana-plugin-plugins-data-public.injectsearchsourcereferences.md) | | +| [isCompleteResponse](./kibana-plugin-plugins-data-public.iscompleteresponse.md) | | +| [isErrorResponse](./kibana-plugin-plugins-data-public.iserrorresponse.md) | | | [isFilter](./kibana-plugin-plugins-data-public.isfilter.md) | | | [isFilters](./kibana-plugin-plugins-data-public.isfilters.md) | | +| [isPartialResponse](./kibana-plugin-plugins-data-public.ispartialresponse.md) | | | [isQuery](./kibana-plugin-plugins-data-public.isquery.md) | | | [isTimeRange](./kibana-plugin-plugins-data-public.istimerange.md) | | | [parseSearchSourceJSON](./kibana-plugin-plugins-data-public.parsesearchsourcejson.md) | | @@ -145,14 +148,17 @@ | [FieldFormatsContentType](./kibana-plugin-plugins-data-public.fieldformatscontenttype.md) | \* | | [FieldFormatsGetConfigFn](./kibana-plugin-plugins-data-public.fieldformatsgetconfigfn.md) | | | [FieldFormatsStart](./kibana-plugin-plugins-data-public.fieldformatsstart.md) | | +| [Filter](./kibana-plugin-plugins-data-public.filter.md) | | | [IAggConfig](./kibana-plugin-plugins-data-public.iaggconfig.md) | AggConfig This class represents an aggregation, which is displayed in the left-hand nav of the Visualize app. | | [IAggType](./kibana-plugin-plugins-data-public.iaggtype.md) | | +| [IEsSearchResponse](./kibana-plugin-plugins-data-public.iessearchresponse.md) | | | [IFieldFormat](./kibana-plugin-plugins-data-public.ifieldformat.md) | | | [IFieldFormatsRegistry](./kibana-plugin-plugins-data-public.ifieldformatsregistry.md) | | | [IFieldParamType](./kibana-plugin-plugins-data-public.ifieldparamtype.md) | | | [IMetricAggType](./kibana-plugin-plugins-data-public.imetricaggtype.md) | | | [IndexPatternAggRestrictions](./kibana-plugin-plugins-data-public.indexpatternaggrestrictions.md) | | | [IndexPatternsContract](./kibana-plugin-plugins-data-public.indexpatternscontract.md) | | +| [IndexPatternSelectProps](./kibana-plugin-plugins-data-public.indexpatternselectprops.md) | | | [InputTimeRange](./kibana-plugin-plugins-data-public.inputtimerange.md) | | | [ISearch](./kibana-plugin-plugins-data-public.isearch.md) | | | [ISearchGeneric](./kibana-plugin-plugins-data-public.isearchgeneric.md) | | @@ -162,6 +168,7 @@ | [ParsedInterval](./kibana-plugin-plugins-data-public.parsedinterval.md) | | | [PhraseFilter](./kibana-plugin-plugins-data-public.phrasefilter.md) | | | [PhrasesFilter](./kibana-plugin-plugins-data-public.phrasesfilter.md) | | +| [Query](./kibana-plugin-plugins-data-public.query.md) | | | [QueryStart](./kibana-plugin-plugins-data-public.querystart.md) | | | [QuerySuggestion](./kibana-plugin-plugins-data-public.querysuggestion.md) | \* | | [QuerySuggestionGetFn](./kibana-plugin-plugins-data-public.querysuggestiongetfn.md) | | @@ -173,4 +180,5 @@ | [TabbedAggRow](./kibana-plugin-plugins-data-public.tabbedaggrow.md) | \* | | [TimefilterContract](./kibana-plugin-plugins-data-public.timefiltercontract.md) | | | [TimeHistoryContract](./kibana-plugin-plugins-data-public.timehistorycontract.md) | | +| [TimeRange](./kibana-plugin-plugins-data-public.timerange.md) | | diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.painlesserror._constructor_.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.painlesserror._constructor_.md new file mode 100644 index 0000000000000..f8966572afbb6 --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.painlesserror._constructor_.md @@ -0,0 +1,21 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [PainlessError](./kibana-plugin-plugins-data-public.painlesserror.md) > [(constructor)](./kibana-plugin-plugins-data-public.painlesserror._constructor_.md) + +## PainlessError.(constructor) + +Constructs a new instance of the `PainlessError` class + +Signature: + +```typescript +constructor(err: EsError, request: IKibanaSearchRequest); +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| err | EsError | | +| request | IKibanaSearchRequest | | + diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.painlesserror.geterrormessage.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.painlesserror.geterrormessage.md new file mode 100644 index 0000000000000..a3b4c51c6c331 --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.painlesserror.geterrormessage.md @@ -0,0 +1,22 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [PainlessError](./kibana-plugin-plugins-data-public.painlesserror.md) > [getErrorMessage](./kibana-plugin-plugins-data-public.painlesserror.geterrormessage.md) + +## PainlessError.getErrorMessage() method + +Signature: + +```typescript +getErrorMessage(application: ApplicationStart): JSX.Element; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| application | ApplicationStart | | + +Returns: + +`JSX.Element` + diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.painlesserror.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.painlesserror.md new file mode 100644 index 0000000000000..306211cd60259 --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.painlesserror.md @@ -0,0 +1,30 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [PainlessError](./kibana-plugin-plugins-data-public.painlesserror.md) + +## PainlessError class + +Signature: + +```typescript +export declare class PainlessError extends KbnError +``` + +## Constructors + +| Constructor | Modifiers | Description | +| --- | --- | --- | +| [(constructor)(err, request)](./kibana-plugin-plugins-data-public.painlesserror._constructor_.md) | | Constructs a new instance of the PainlessError class | + +## Properties + +| Property | Modifiers | Type | Description | +| --- | --- | --- | --- | +| [painlessStack](./kibana-plugin-plugins-data-public.painlesserror.painlessstack.md) | | string | | + +## Methods + +| Method | Modifiers | Description | +| --- | --- | --- | +| [getErrorMessage(application)](./kibana-plugin-plugins-data-public.painlesserror.geterrormessage.md) | | | + diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.painlesserror.painlessstack.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.painlesserror.painlessstack.md new file mode 100644 index 0000000000000..a7e6920b2ae21 --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.painlesserror.painlessstack.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [PainlessError](./kibana-plugin-plugins-data-public.painlesserror.md) > [painlessStack](./kibana-plugin-plugins-data-public.painlesserror.painlessstack.md) + +## PainlessError.painlessStack property + +Signature: + +```typescript +painlessStack?: string; +``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinput.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinput.md index e85747b8cc3d7..3a0786a110ab6 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinput.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinput.md @@ -7,5 +7,5 @@ Signature: ```typescript -QueryStringInput: React.FC> +QueryStringInput: (props: QueryStringInputProps) => JSX.Element ``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinputprops.bubblesubmitevent.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinputprops.bubblesubmitevent.md new file mode 100644 index 0000000000000..5a41852001ac0 --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinputprops.bubblesubmitevent.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [QueryStringInputProps](./kibana-plugin-plugins-data-public.querystringinputprops.md) > [bubbleSubmitEvent](./kibana-plugin-plugins-data-public.querystringinputprops.bubblesubmitevent.md) + +## QueryStringInputProps.bubbleSubmitEvent property + +Signature: + +```typescript +bubbleSubmitEvent?: boolean; +``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinputprops.classname.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinputprops.classname.md new file mode 100644 index 0000000000000..7fa3b76977183 --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinputprops.classname.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [QueryStringInputProps](./kibana-plugin-plugins-data-public.querystringinputprops.md) > [className](./kibana-plugin-plugins-data-public.querystringinputprops.classname.md) + +## QueryStringInputProps.className property + +Signature: + +```typescript +className?: string; +``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinputprops.datatestsubj.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinputprops.datatestsubj.md new file mode 100644 index 0000000000000..edaedf49f4b10 --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinputprops.datatestsubj.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [QueryStringInputProps](./kibana-plugin-plugins-data-public.querystringinputprops.md) > [dataTestSubj](./kibana-plugin-plugins-data-public.querystringinputprops.datatestsubj.md) + +## QueryStringInputProps.dataTestSubj property + +Signature: + +```typescript +dataTestSubj?: string; +``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinputprops.disableautofocus.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinputprops.disableautofocus.md new file mode 100644 index 0000000000000..cc4c6f606409e --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinputprops.disableautofocus.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [QueryStringInputProps](./kibana-plugin-plugins-data-public.querystringinputprops.md) > [disableAutoFocus](./kibana-plugin-plugins-data-public.querystringinputprops.disableautofocus.md) + +## QueryStringInputProps.disableAutoFocus property + +Signature: + +```typescript +disableAutoFocus?: boolean; +``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinputprops.indexpatterns.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinputprops.indexpatterns.md new file mode 100644 index 0000000000000..3783138696020 --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinputprops.indexpatterns.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [QueryStringInputProps](./kibana-plugin-plugins-data-public.querystringinputprops.md) > [indexPatterns](./kibana-plugin-plugins-data-public.querystringinputprops.indexpatterns.md) + +## QueryStringInputProps.indexPatterns property + +Signature: + +```typescript +indexPatterns: Array; +``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinputprops.isinvalid.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinputprops.isinvalid.md new file mode 100644 index 0000000000000..a282ac3bc5049 --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinputprops.isinvalid.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [QueryStringInputProps](./kibana-plugin-plugins-data-public.querystringinputprops.md) > [isInvalid](./kibana-plugin-plugins-data-public.querystringinputprops.isinvalid.md) + +## QueryStringInputProps.isInvalid property + +Signature: + +```typescript +isInvalid?: boolean; +``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinputprops.languageswitcherpopoveranchorposition.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinputprops.languageswitcherpopoveranchorposition.md new file mode 100644 index 0000000000000..d133a0930b53d --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinputprops.languageswitcherpopoveranchorposition.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [QueryStringInputProps](./kibana-plugin-plugins-data-public.querystringinputprops.md) > [languageSwitcherPopoverAnchorPosition](./kibana-plugin-plugins-data-public.querystringinputprops.languageswitcherpopoveranchorposition.md) + +## QueryStringInputProps.languageSwitcherPopoverAnchorPosition property + +Signature: + +```typescript +languageSwitcherPopoverAnchorPosition?: PopoverAnchorPosition; +``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinputprops.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinputprops.md new file mode 100644 index 0000000000000..d503980da7947 --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinputprops.md @@ -0,0 +1,34 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [QueryStringInputProps](./kibana-plugin-plugins-data-public.querystringinputprops.md) + +## QueryStringInputProps interface + +Signature: + +```typescript +export interface QueryStringInputProps +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [bubbleSubmitEvent](./kibana-plugin-plugins-data-public.querystringinputprops.bubblesubmitevent.md) | boolean | | +| [className](./kibana-plugin-plugins-data-public.querystringinputprops.classname.md) | string | | +| [dataTestSubj](./kibana-plugin-plugins-data-public.querystringinputprops.datatestsubj.md) | string | | +| [disableAutoFocus](./kibana-plugin-plugins-data-public.querystringinputprops.disableautofocus.md) | boolean | | +| [indexPatterns](./kibana-plugin-plugins-data-public.querystringinputprops.indexpatterns.md) | Array<IIndexPattern | string> | | +| [isInvalid](./kibana-plugin-plugins-data-public.querystringinputprops.isinvalid.md) | boolean | | +| [languageSwitcherPopoverAnchorPosition](./kibana-plugin-plugins-data-public.querystringinputprops.languageswitcherpopoveranchorposition.md) | PopoverAnchorPosition | | +| [onBlur](./kibana-plugin-plugins-data-public.querystringinputprops.onblur.md) | () => void | | +| [onChange](./kibana-plugin-plugins-data-public.querystringinputprops.onchange.md) | (query: Query) => void | | +| [onChangeQueryInputFocus](./kibana-plugin-plugins-data-public.querystringinputprops.onchangequeryinputfocus.md) | (isFocused: boolean) => void | | +| [onSubmit](./kibana-plugin-plugins-data-public.querystringinputprops.onsubmit.md) | (query: Query) => void | | +| [persistedLog](./kibana-plugin-plugins-data-public.querystringinputprops.persistedlog.md) | PersistedLog | | +| [placeholder](./kibana-plugin-plugins-data-public.querystringinputprops.placeholder.md) | string | | +| [prepend](./kibana-plugin-plugins-data-public.querystringinputprops.prepend.md) | any | | +| [query](./kibana-plugin-plugins-data-public.querystringinputprops.query.md) | Query | | +| [screenTitle](./kibana-plugin-plugins-data-public.querystringinputprops.screentitle.md) | string | | +| [size](./kibana-plugin-plugins-data-public.querystringinputprops.size.md) | SuggestionsListSize | | + diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinputprops.onblur.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinputprops.onblur.md new file mode 100644 index 0000000000000..10f2ae2ea4f14 --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinputprops.onblur.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [QueryStringInputProps](./kibana-plugin-plugins-data-public.querystringinputprops.md) > [onBlur](./kibana-plugin-plugins-data-public.querystringinputprops.onblur.md) + +## QueryStringInputProps.onBlur property + +Signature: + +```typescript +onBlur?: () => void; +``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinputprops.onchange.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinputprops.onchange.md new file mode 100644 index 0000000000000..fee44d7afd506 --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinputprops.onchange.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [QueryStringInputProps](./kibana-plugin-plugins-data-public.querystringinputprops.md) > [onChange](./kibana-plugin-plugins-data-public.querystringinputprops.onchange.md) + +## QueryStringInputProps.onChange property + +Signature: + +```typescript +onChange?: (query: Query) => void; +``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinputprops.onchangequeryinputfocus.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinputprops.onchangequeryinputfocus.md new file mode 100644 index 0000000000000..0421ae9c8bac5 --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinputprops.onchangequeryinputfocus.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [QueryStringInputProps](./kibana-plugin-plugins-data-public.querystringinputprops.md) > [onChangeQueryInputFocus](./kibana-plugin-plugins-data-public.querystringinputprops.onchangequeryinputfocus.md) + +## QueryStringInputProps.onChangeQueryInputFocus property + +Signature: + +```typescript +onChangeQueryInputFocus?: (isFocused: boolean) => void; +``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinputprops.onsubmit.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinputprops.onsubmit.md new file mode 100644 index 0000000000000..951ec7419485f --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinputprops.onsubmit.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [QueryStringInputProps](./kibana-plugin-plugins-data-public.querystringinputprops.md) > [onSubmit](./kibana-plugin-plugins-data-public.querystringinputprops.onsubmit.md) + +## QueryStringInputProps.onSubmit property + +Signature: + +```typescript +onSubmit?: (query: Query) => void; +``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinputprops.persistedlog.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinputprops.persistedlog.md new file mode 100644 index 0000000000000..d1a8efb364016 --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinputprops.persistedlog.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [QueryStringInputProps](./kibana-plugin-plugins-data-public.querystringinputprops.md) > [persistedLog](./kibana-plugin-plugins-data-public.querystringinputprops.persistedlog.md) + +## QueryStringInputProps.persistedLog property + +Signature: + +```typescript +persistedLog?: PersistedLog; +``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinputprops.placeholder.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinputprops.placeholder.md new file mode 100644 index 0000000000000..31e41f4d55205 --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinputprops.placeholder.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [QueryStringInputProps](./kibana-plugin-plugins-data-public.querystringinputprops.md) > [placeholder](./kibana-plugin-plugins-data-public.querystringinputprops.placeholder.md) + +## QueryStringInputProps.placeholder property + +Signature: + +```typescript +placeholder?: string; +``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinputprops.prepend.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinputprops.prepend.md new file mode 100644 index 0000000000000..7be882058d3fd --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinputprops.prepend.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [QueryStringInputProps](./kibana-plugin-plugins-data-public.querystringinputprops.md) > [prepend](./kibana-plugin-plugins-data-public.querystringinputprops.prepend.md) + +## QueryStringInputProps.prepend property + +Signature: + +```typescript +prepend?: any; +``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinputprops.query.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinputprops.query.md new file mode 100644 index 0000000000000..f15f6d082332b --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinputprops.query.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [QueryStringInputProps](./kibana-plugin-plugins-data-public.querystringinputprops.md) > [query](./kibana-plugin-plugins-data-public.querystringinputprops.query.md) + +## QueryStringInputProps.query property + +Signature: + +```typescript +query: Query; +``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinputprops.screentitle.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinputprops.screentitle.md new file mode 100644 index 0000000000000..0c80252d74571 --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinputprops.screentitle.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [QueryStringInputProps](./kibana-plugin-plugins-data-public.querystringinputprops.md) > [screenTitle](./kibana-plugin-plugins-data-public.querystringinputprops.screentitle.md) + +## QueryStringInputProps.screenTitle property + +Signature: + +```typescript +screenTitle?: string; +``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinputprops.size.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinputprops.size.md new file mode 100644 index 0000000000000..6b0e53a23e07b --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinputprops.size.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [QueryStringInputProps](./kibana-plugin-plugins-data-public.querystringinputprops.md) > [size](./kibana-plugin-plugins-data-public.querystringinputprops.size.md) + +## QueryStringInputProps.size property + +Signature: + +```typescript +size?: SuggestionsListSize; +``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.requesttimeouterror._constructor_.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.requesttimeouterror._constructor_.md deleted file mode 100644 index 25e472817b46d..0000000000000 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.requesttimeouterror._constructor_.md +++ /dev/null @@ -1,20 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [RequestTimeoutError](./kibana-plugin-plugins-data-public.requesttimeouterror.md) > [(constructor)](./kibana-plugin-plugins-data-public.requesttimeouterror._constructor_.md) - -## RequestTimeoutError.(constructor) - -Constructs a new instance of the `RequestTimeoutError` class - -Signature: - -```typescript -constructor(message?: string); -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| message | string | | - diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.requesttimeouterror.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.requesttimeouterror.md deleted file mode 100644 index 84b2fc3fe0b17..0000000000000 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.requesttimeouterror.md +++ /dev/null @@ -1,20 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [RequestTimeoutError](./kibana-plugin-plugins-data-public.requesttimeouterror.md) - -## RequestTimeoutError class - -Class used to signify that a request timed out. Useful for applications to conditionally handle this type of error differently than other errors. - -Signature: - -```typescript -export declare class RequestTimeoutError extends Error -``` - -## Constructors - -| Constructor | Modifiers | Description | -| --- | --- | --- | -| [(constructor)(message)](./kibana-plugin-plugins-data-public.requesttimeouterror._constructor_.md) | | Constructs a new instance of the RequestTimeoutError class | - diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.gettimeoutmode.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.gettimeoutmode.md new file mode 100644 index 0000000000000..8ecd8b8c5ac22 --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.gettimeoutmode.md @@ -0,0 +1,15 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [SearchInterceptor](./kibana-plugin-plugins-data-public.searchinterceptor.md) > [getTimeoutMode](./kibana-plugin-plugins-data-public.searchinterceptor.gettimeoutmode.md) + +## SearchInterceptor.getTimeoutMode() method + +Signature: + +```typescript +protected getTimeoutMode(): TimeoutErrorMode; +``` +Returns: + +`TimeoutErrorMode` + diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.handlesearcherror.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.handlesearcherror.md new file mode 100644 index 0000000000000..02db74b1a9e91 --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.handlesearcherror.md @@ -0,0 +1,25 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [SearchInterceptor](./kibana-plugin-plugins-data-public.searchinterceptor.md) > [handleSearchError](./kibana-plugin-plugins-data-public.searchinterceptor.handlesearcherror.md) + +## SearchInterceptor.handleSearchError() method + +Signature: + +```typescript +protected handleSearchError(e: any, request: IKibanaSearchRequest, timeoutSignal: AbortSignal, appAbortSignal?: AbortSignal): Error; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| e | any | | +| request | IKibanaSearchRequest | | +| timeoutSignal | AbortSignal | | +| appAbortSignal | AbortSignal | | + +Returns: + +`Error` + diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.md index 5cee345db6cd2..a02a6116d7ae0 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.md @@ -21,11 +21,13 @@ export declare class SearchInterceptor | Property | Modifiers | Type | Description | | --- | --- | --- | --- | | [deps](./kibana-plugin-plugins-data-public.searchinterceptor.deps.md) | | SearchInterceptorDeps | | -| [showTimeoutError](./kibana-plugin-plugins-data-public.searchinterceptor.showtimeouterror.md) | | ((e: Error) => void) & import("lodash").Cancelable | | ## Methods | Method | Modifiers | Description | | --- | --- | --- | +| [getTimeoutMode()](./kibana-plugin-plugins-data-public.searchinterceptor.gettimeoutmode.md) | | | +| [handleSearchError(e, request, timeoutSignal, appAbortSignal)](./kibana-plugin-plugins-data-public.searchinterceptor.handlesearcherror.md) | | | | [search(request, options)](./kibana-plugin-plugins-data-public.searchinterceptor.search.md) | | Searches using the given search method. Overrides the AbortSignal with one that will abort either when cancelPending is called, when the request times out, or when the original AbortSignal is aborted. Updates pendingCount$ when the request is started/finalized. | +| [showError(e)](./kibana-plugin-plugins-data-public.searchinterceptor.showerror.md) | | | diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.search.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.search.md index 1752d183a8737..672ff5065c456 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.search.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.search.md @@ -9,17 +9,19 @@ Searches using the given `search` method. Overrides the `AbortSignal` with one t Signature: ```typescript -search(request: IEsSearchRequest, options?: ISearchOptions): Observable; +search(request: IKibanaSearchRequest, options?: ISearchOptions): Observable; ``` ## Parameters | Parameter | Type | Description | | --- | --- | --- | -| request | IEsSearchRequest | | +| request | IKibanaSearchRequest | | | options | ISearchOptions | | Returns: -`Observable` +`Observable` + +`Observalbe` emitting the search response or an error. diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.showerror.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.showerror.md new file mode 100644 index 0000000000000..92e851c783dd0 --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.showerror.md @@ -0,0 +1,22 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [SearchInterceptor](./kibana-plugin-plugins-data-public.searchinterceptor.md) > [showError](./kibana-plugin-plugins-data-public.searchinterceptor.showerror.md) + +## SearchInterceptor.showError() method + +Signature: + +```typescript +showError(e: Error): void; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| e | Error | | + +Returns: + +`void` + diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.showtimeouterror.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.showtimeouterror.md deleted file mode 100644 index 91ecb2821acbf..0000000000000 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.showtimeouterror.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [SearchInterceptor](./kibana-plugin-plugins-data-public.searchinterceptor.md) > [showTimeoutError](./kibana-plugin-plugins-data-public.searchinterceptor.showtimeouterror.md) - -## SearchInterceptor.showTimeoutError property - -Signature: - -```typescript -protected showTimeoutError: ((e: Error) => void) & import("lodash").Cancelable; -``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchtimeouterror._constructor_.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchtimeouterror._constructor_.md new file mode 100644 index 0000000000000..1c6370c7d0356 --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchtimeouterror._constructor_.md @@ -0,0 +1,21 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [SearchTimeoutError](./kibana-plugin-plugins-data-public.searchtimeouterror.md) > [(constructor)](./kibana-plugin-plugins-data-public.searchtimeouterror._constructor_.md) + +## SearchTimeoutError.(constructor) + +Constructs a new instance of the `SearchTimeoutError` class + +Signature: + +```typescript +constructor(err: Error, mode: TimeoutErrorMode); +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| err | Error | | +| mode | TimeoutErrorMode | | + diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchtimeouterror.geterrormessage.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchtimeouterror.geterrormessage.md new file mode 100644 index 0000000000000..58ef953c9d7db --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchtimeouterror.geterrormessage.md @@ -0,0 +1,22 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [SearchTimeoutError](./kibana-plugin-plugins-data-public.searchtimeouterror.md) > [getErrorMessage](./kibana-plugin-plugins-data-public.searchtimeouterror.geterrormessage.md) + +## SearchTimeoutError.getErrorMessage() method + +Signature: + +```typescript +getErrorMessage(application: ApplicationStart): JSX.Element; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| application | ApplicationStart | | + +Returns: + +`JSX.Element` + diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchtimeouterror.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchtimeouterror.md new file mode 100644 index 0000000000000..5c0bec04dcfbc --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchtimeouterror.md @@ -0,0 +1,32 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [SearchTimeoutError](./kibana-plugin-plugins-data-public.searchtimeouterror.md) + +## SearchTimeoutError class + +Request Failure - When an entire multi request fails + +Signature: + +```typescript +export declare class SearchTimeoutError extends KbnError +``` + +## Constructors + +| Constructor | Modifiers | Description | +| --- | --- | --- | +| [(constructor)(err, mode)](./kibana-plugin-plugins-data-public.searchtimeouterror._constructor_.md) | | Constructs a new instance of the SearchTimeoutError class | + +## Properties + +| Property | Modifiers | Type | Description | +| --- | --- | --- | --- | +| [mode](./kibana-plugin-plugins-data-public.searchtimeouterror.mode.md) | | TimeoutErrorMode | | + +## Methods + +| Method | Modifiers | Description | +| --- | --- | --- | +| [getErrorMessage(application)](./kibana-plugin-plugins-data-public.searchtimeouterror.geterrormessage.md) | | | + diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchtimeouterror.mode.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchtimeouterror.mode.md new file mode 100644 index 0000000000000..d534a73eca2ec --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchtimeouterror.mode.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [SearchTimeoutError](./kibana-plugin-plugins-data-public.searchtimeouterror.md) > [mode](./kibana-plugin-plugins-data-public.searchtimeouterror.mode.md) + +## SearchTimeoutError.mode property + +Signature: + +```typescript +mode: TimeoutErrorMode; +``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.timeouterrormode.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.timeouterrormode.md new file mode 100644 index 0000000000000..8ad63e2c1e9b4 --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.timeouterrormode.md @@ -0,0 +1,20 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [TimeoutErrorMode](./kibana-plugin-plugins-data-public.timeouterrormode.md) + +## TimeoutErrorMode enum + +Signature: + +```typescript +export declare enum TimeoutErrorMode +``` + +## Enumeration Members + +| Member | Value | Description | +| --- | --- | --- | +| CHANGE | 2 | | +| CONTACT | 1 | | +| UPGRADE | 0 | | + diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.fielddescriptor.aggregatable.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.fielddescriptor.aggregatable.md new file mode 100644 index 0000000000000..2889ee34ad77b --- /dev/null +++ b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.fielddescriptor.aggregatable.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-server](./kibana-plugin-plugins-data-server.md) > [FieldDescriptor](./kibana-plugin-plugins-data-server.fielddescriptor.md) > [aggregatable](./kibana-plugin-plugins-data-server.fielddescriptor.aggregatable.md) + +## FieldDescriptor.aggregatable property + +Signature: + +```typescript +aggregatable: boolean; +``` diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.fielddescriptor.estypes.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.fielddescriptor.estypes.md new file mode 100644 index 0000000000000..9caa374d8da48 --- /dev/null +++ b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.fielddescriptor.estypes.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-server](./kibana-plugin-plugins-data-server.md) > [FieldDescriptor](./kibana-plugin-plugins-data-server.fielddescriptor.md) > [esTypes](./kibana-plugin-plugins-data-server.fielddescriptor.estypes.md) + +## FieldDescriptor.esTypes property + +Signature: + +```typescript +esTypes: string[]; +``` diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.fielddescriptor.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.fielddescriptor.md new file mode 100644 index 0000000000000..693de675da940 --- /dev/null +++ b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.fielddescriptor.md @@ -0,0 +1,24 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-server](./kibana-plugin-plugins-data-server.md) > [FieldDescriptor](./kibana-plugin-plugins-data-server.fielddescriptor.md) + +## FieldDescriptor interface + +Signature: + +```typescript +export interface FieldDescriptor +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [aggregatable](./kibana-plugin-plugins-data-server.fielddescriptor.aggregatable.md) | boolean | | +| [esTypes](./kibana-plugin-plugins-data-server.fielddescriptor.estypes.md) | string[] | | +| [name](./kibana-plugin-plugins-data-server.fielddescriptor.name.md) | string | | +| [readFromDocValues](./kibana-plugin-plugins-data-server.fielddescriptor.readfromdocvalues.md) | boolean | | +| [searchable](./kibana-plugin-plugins-data-server.fielddescriptor.searchable.md) | boolean | | +| [subType](./kibana-plugin-plugins-data-server.fielddescriptor.subtype.md) | FieldSubType | | +| [type](./kibana-plugin-plugins-data-server.fielddescriptor.type.md) | string | | + diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.fielddescriptor.name.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.fielddescriptor.name.md new file mode 100644 index 0000000000000..178880a34cd4d --- /dev/null +++ b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.fielddescriptor.name.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-server](./kibana-plugin-plugins-data-server.md) > [FieldDescriptor](./kibana-plugin-plugins-data-server.fielddescriptor.md) > [name](./kibana-plugin-plugins-data-server.fielddescriptor.name.md) + +## FieldDescriptor.name property + +Signature: + +```typescript +name: string; +``` diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.fielddescriptor.readfromdocvalues.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.fielddescriptor.readfromdocvalues.md new file mode 100644 index 0000000000000..b60dc5d0dfed0 --- /dev/null +++ b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.fielddescriptor.readfromdocvalues.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-server](./kibana-plugin-plugins-data-server.md) > [FieldDescriptor](./kibana-plugin-plugins-data-server.fielddescriptor.md) > [readFromDocValues](./kibana-plugin-plugins-data-server.fielddescriptor.readfromdocvalues.md) + +## FieldDescriptor.readFromDocValues property + +Signature: + +```typescript +readFromDocValues: boolean; +``` diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.fielddescriptor.searchable.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.fielddescriptor.searchable.md new file mode 100644 index 0000000000000..efc7b4219a355 --- /dev/null +++ b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.fielddescriptor.searchable.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-server](./kibana-plugin-plugins-data-server.md) > [FieldDescriptor](./kibana-plugin-plugins-data-server.fielddescriptor.md) > [searchable](./kibana-plugin-plugins-data-server.fielddescriptor.searchable.md) + +## FieldDescriptor.searchable property + +Signature: + +```typescript +searchable: boolean; +``` diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.fielddescriptor.subtype.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.fielddescriptor.subtype.md new file mode 100644 index 0000000000000..b08179f12f250 --- /dev/null +++ b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.fielddescriptor.subtype.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-server](./kibana-plugin-plugins-data-server.md) > [FieldDescriptor](./kibana-plugin-plugins-data-server.fielddescriptor.md) > [subType](./kibana-plugin-plugins-data-server.fielddescriptor.subtype.md) + +## FieldDescriptor.subType property + +Signature: + +```typescript +subType?: FieldSubType; +``` diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.fielddescriptor.type.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.fielddescriptor.type.md new file mode 100644 index 0000000000000..7b0513a60c90e --- /dev/null +++ b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.fielddescriptor.type.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-server](./kibana-plugin-plugins-data-server.md) > [FieldDescriptor](./kibana-plugin-plugins-data-server.fielddescriptor.md) > [type](./kibana-plugin-plugins-data-server.fielddescriptor.type.md) + +## FieldDescriptor.type property + +Signature: + +```typescript +type: string; +``` diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.iessearchrequest.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.iessearchrequest.md index 0dfa23eb64c1b..9141bcdd2e8d7 100644 --- a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.iessearchrequest.md +++ b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.iessearchrequest.md @@ -7,7 +7,7 @@ Signature: ```typescript -export interface IEsSearchRequest extends IKibanaSearchRequest +export interface IEsSearchRequest extends IKibanaSearchRequest ``` ## Properties @@ -15,5 +15,4 @@ export interface IEsSearchRequest extends IKibanaSearchRequest | Property | Type | Description | | --- | --- | --- | | [indexType](./kibana-plugin-plugins-data-server.iessearchrequest.indextype.md) | string | | -| [params](./kibana-plugin-plugins-data-server.iessearchrequest.params.md) | ISearchRequestParams | | diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.iessearchrequest.params.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.iessearchrequest.params.md deleted file mode 100644 index d65281973c951..0000000000000 --- a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.iessearchrequest.params.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-plugins-data-server](./kibana-plugin-plugins-data-server.md) > [IEsSearchRequest](./kibana-plugin-plugins-data-server.iessearchrequest.md) > [params](./kibana-plugin-plugins-data-server.iessearchrequest.params.md) - -## IEsSearchRequest.params property - -Signature: - -```typescript -params?: ISearchRequestParams; -``` diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.iessearchresponse.ispartial.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.iessearchresponse.ispartial.md deleted file mode 100644 index fbddfc1cd9fc4..0000000000000 --- a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.iessearchresponse.ispartial.md +++ /dev/null @@ -1,13 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-plugins-data-server](./kibana-plugin-plugins-data-server.md) > [IEsSearchResponse](./kibana-plugin-plugins-data-server.iessearchresponse.md) > [isPartial](./kibana-plugin-plugins-data-server.iessearchresponse.ispartial.md) - -## IEsSearchResponse.isPartial property - -Indicates whether the results returned are complete or partial - -Signature: - -```typescript -isPartial?: boolean; -``` diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.iessearchresponse.isrunning.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.iessearchresponse.isrunning.md deleted file mode 100644 index 01f3982957d5c..0000000000000 --- a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.iessearchresponse.isrunning.md +++ /dev/null @@ -1,13 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-plugins-data-server](./kibana-plugin-plugins-data-server.md) > [IEsSearchResponse](./kibana-plugin-plugins-data-server.iessearchresponse.md) > [isRunning](./kibana-plugin-plugins-data-server.iessearchresponse.isrunning.md) - -## IEsSearchResponse.isRunning property - -Indicates whether async search is still in flight - -Signature: - -```typescript -isRunning?: boolean; -``` diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.iessearchresponse.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.iessearchresponse.md index 55c0399e90e2f..d333af1b278c2 100644 --- a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.iessearchresponse.md +++ b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.iessearchresponse.md @@ -2,19 +2,10 @@ [Home](./index.md) > [kibana-plugin-plugins-data-server](./kibana-plugin-plugins-data-server.md) > [IEsSearchResponse](./kibana-plugin-plugins-data-server.iessearchresponse.md) -## IEsSearchResponse interface +## IEsSearchResponse type Signature: ```typescript -export interface IEsSearchResponse extends IKibanaSearchResponse +export declare type IEsSearchResponse = IKibanaSearchResponse>; ``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [isPartial](./kibana-plugin-plugins-data-server.iessearchresponse.ispartial.md) | boolean | Indicates whether the results returned are complete or partial | -| [isRunning](./kibana-plugin-plugins-data-server.iessearchresponse.isrunning.md) | boolean | Indicates whether async search is still in flight | -| [rawResponse](./kibana-plugin-plugins-data-server.iessearchresponse.rawresponse.md) | SearchResponse<Source> | | - diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.iessearchresponse.rawresponse.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.iessearchresponse.rawresponse.md deleted file mode 100644 index 9987debfa551c..0000000000000 --- a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.iessearchresponse.rawresponse.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-plugins-data-server](./kibana-plugin-plugins-data-server.md) > [IEsSearchResponse](./kibana-plugin-plugins-data-server.iessearchresponse.md) > [rawResponse](./kibana-plugin-plugins-data-server.iessearchresponse.rawresponse.md) - -## IEsSearchResponse.rawResponse property - -Signature: - -```typescript -rawResponse: SearchResponse; -``` diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.iindexpattern.fieldformatmap.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.iindexpattern.fieldformatmap.md deleted file mode 100644 index ab9e3171d7d7b..0000000000000 --- a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.iindexpattern.fieldformatmap.md +++ /dev/null @@ -1,14 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-plugins-data-server](./kibana-plugin-plugins-data-server.md) > [IIndexPattern](./kibana-plugin-plugins-data-server.iindexpattern.md) > [fieldFormatMap](./kibana-plugin-plugins-data-server.iindexpattern.fieldformatmap.md) - -## IIndexPattern.fieldFormatMap property - -Signature: - -```typescript -fieldFormatMap?: Record; -``` diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.iindexpattern.fields.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.iindexpattern.fields.md deleted file mode 100644 index fb6d046ff2174..0000000000000 --- a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.iindexpattern.fields.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-plugins-data-server](./kibana-plugin-plugins-data-server.md) > [IIndexPattern](./kibana-plugin-plugins-data-server.iindexpattern.md) > [fields](./kibana-plugin-plugins-data-server.iindexpattern.fields.md) - -## IIndexPattern.fields property - -Signature: - -```typescript -fields: IFieldType[]; -``` diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.iindexpattern.gettimefield.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.iindexpattern.gettimefield.md deleted file mode 100644 index a4d6abcf86a94..0000000000000 --- a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.iindexpattern.gettimefield.md +++ /dev/null @@ -1,15 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-plugins-data-server](./kibana-plugin-plugins-data-server.md) > [IIndexPattern](./kibana-plugin-plugins-data-server.iindexpattern.md) > [getTimeField](./kibana-plugin-plugins-data-server.iindexpattern.gettimefield.md) - -## IIndexPattern.getTimeField() method - -Signature: - -```typescript -getTimeField?(): IFieldType | undefined; -``` -Returns: - -`IFieldType | undefined` - diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.iindexpattern.id.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.iindexpattern.id.md deleted file mode 100644 index cac263df0f9aa..0000000000000 --- a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.iindexpattern.id.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-plugins-data-server](./kibana-plugin-plugins-data-server.md) > [IIndexPattern](./kibana-plugin-plugins-data-server.iindexpattern.md) > [id](./kibana-plugin-plugins-data-server.iindexpattern.id.md) - -## IIndexPattern.id property - -Signature: - -```typescript -id?: string; -``` diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.iindexpattern.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.iindexpattern.md deleted file mode 100644 index a79244a24acf5..0000000000000 --- a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.iindexpattern.md +++ /dev/null @@ -1,29 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-plugins-data-server](./kibana-plugin-plugins-data-server.md) > [IIndexPattern](./kibana-plugin-plugins-data-server.iindexpattern.md) - -## IIndexPattern interface - -Signature: - -```typescript -export interface IIndexPattern -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [fieldFormatMap](./kibana-plugin-plugins-data-server.iindexpattern.fieldformatmap.md) | Record<string, {
id: string;
params: unknown;
}> | | -| [fields](./kibana-plugin-plugins-data-server.iindexpattern.fields.md) | IFieldType[] | | -| [id](./kibana-plugin-plugins-data-server.iindexpattern.id.md) | string | | -| [timeFieldName](./kibana-plugin-plugins-data-server.iindexpattern.timefieldname.md) | string | | -| [title](./kibana-plugin-plugins-data-server.iindexpattern.title.md) | string | | -| [type](./kibana-plugin-plugins-data-server.iindexpattern.type.md) | string | | - -## Methods - -| Method | Description | -| --- | --- | -| [getTimeField()](./kibana-plugin-plugins-data-server.iindexpattern.gettimefield.md) | | - diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.iindexpattern.timefieldname.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.iindexpattern.timefieldname.md deleted file mode 100644 index 14cf514477da4..0000000000000 --- a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.iindexpattern.timefieldname.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-plugins-data-server](./kibana-plugin-plugins-data-server.md) > [IIndexPattern](./kibana-plugin-plugins-data-server.iindexpattern.md) > [timeFieldName](./kibana-plugin-plugins-data-server.iindexpattern.timefieldname.md) - -## IIndexPattern.timeFieldName property - -Signature: - -```typescript -timeFieldName?: string; -``` diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.iindexpattern.title.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.iindexpattern.title.md deleted file mode 100644 index 119963d7ff95d..0000000000000 --- a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.iindexpattern.title.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-plugins-data-server](./kibana-plugin-plugins-data-server.md) > [IIndexPattern](./kibana-plugin-plugins-data-server.iindexpattern.md) > [title](./kibana-plugin-plugins-data-server.iindexpattern.title.md) - -## IIndexPattern.title property - -Signature: - -```typescript -title: string; -``` diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.iindexpattern.type.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.iindexpattern.type.md deleted file mode 100644 index 6b89b71664b23..0000000000000 --- a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.iindexpattern.type.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-plugins-data-server](./kibana-plugin-plugins-data-server.md) > [IIndexPattern](./kibana-plugin-plugins-data-server.iindexpattern.md) > [type](./kibana-plugin-plugins-data-server.iindexpattern.type.md) - -## IIndexPattern.type property - -Signature: - -```typescript -type?: string; -``` diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpattern._constructor_.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpattern._constructor_.md new file mode 100644 index 0000000000000..22ee6f15933ea --- /dev/null +++ b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpattern._constructor_.md @@ -0,0 +1,20 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-server](./kibana-plugin-plugins-data-server.md) > [IndexPattern](./kibana-plugin-plugins-data-server.indexpattern.md) > [(constructor)](./kibana-plugin-plugins-data-server.indexpattern._constructor_.md) + +## IndexPattern.(constructor) + +Constructs a new instance of the `IndexPattern` class + +Signature: + +```typescript +constructor({ spec, fieldFormats, shortDotsEnable, metaFields, }: IndexPatternDeps); +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| { spec, fieldFormats, shortDotsEnable, metaFields, } | IndexPatternDeps | | + diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpattern.addscriptedfield.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpattern.addscriptedfield.md new file mode 100644 index 0000000000000..a86fea3106225 --- /dev/null +++ b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpattern.addscriptedfield.md @@ -0,0 +1,26 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-server](./kibana-plugin-plugins-data-server.md) > [IndexPattern](./kibana-plugin-plugins-data-server.indexpattern.md) > [addScriptedField](./kibana-plugin-plugins-data-server.indexpattern.addscriptedfield.md) + +## IndexPattern.addScriptedField() method + +Add scripted field to field list + +Signature: + +```typescript +addScriptedField(name: string, script: string, fieldType?: string): Promise; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| name | string | | +| script | string | | +| fieldType | string | | + +Returns: + +`Promise` + diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpattern.fieldformatmap.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpattern.fieldformatmap.md new file mode 100644 index 0000000000000..2f686bd313d58 --- /dev/null +++ b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpattern.fieldformatmap.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-server](./kibana-plugin-plugins-data-server.md) > [IndexPattern](./kibana-plugin-plugins-data-server.indexpattern.md) > [fieldFormatMap](./kibana-plugin-plugins-data-server.indexpattern.fieldformatmap.md) + +## IndexPattern.fieldFormatMap property + +Signature: + +```typescript +fieldFormatMap: Record; +``` diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpattern.fields.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpattern.fields.md new file mode 100644 index 0000000000000..5b22014486c02 --- /dev/null +++ b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpattern.fields.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-server](./kibana-plugin-plugins-data-server.md) > [IndexPattern](./kibana-plugin-plugins-data-server.indexpattern.md) > [fields](./kibana-plugin-plugins-data-server.indexpattern.fields.md) + +## IndexPattern.fields property + +Signature: + +```typescript +fields: IIndexPatternFieldList & { + toSpec: () => IndexPatternFieldMap; + }; +``` diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpattern.flattenhit.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpattern.flattenhit.md new file mode 100644 index 0000000000000..33c6dedc6dcd8 --- /dev/null +++ b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpattern.flattenhit.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-server](./kibana-plugin-plugins-data-server.md) > [IndexPattern](./kibana-plugin-plugins-data-server.indexpattern.md) > [flattenHit](./kibana-plugin-plugins-data-server.indexpattern.flattenhit.md) + +## IndexPattern.flattenHit property + +Signature: + +```typescript +flattenHit: (hit: Record, deep?: boolean) => Record; +``` diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpattern.formatfield.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpattern.formatfield.md new file mode 100644 index 0000000000000..07db8a0805b07 --- /dev/null +++ b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpattern.formatfield.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-server](./kibana-plugin-plugins-data-server.md) > [IndexPattern](./kibana-plugin-plugins-data-server.indexpattern.md) > [formatField](./kibana-plugin-plugins-data-server.indexpattern.formatfield.md) + +## IndexPattern.formatField property + +Signature: + +```typescript +formatField: FormatFieldFn; +``` diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpattern.formathit.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpattern.formathit.md new file mode 100644 index 0000000000000..75f282a8991fc --- /dev/null +++ b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpattern.formathit.md @@ -0,0 +1,14 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-server](./kibana-plugin-plugins-data-server.md) > [IndexPattern](./kibana-plugin-plugins-data-server.indexpattern.md) > [formatHit](./kibana-plugin-plugins-data-server.indexpattern.formathit.md) + +## IndexPattern.formatHit property + +Signature: + +```typescript +formatHit: { + (hit: Record, type?: string): any; + formatField: FormatFieldFn; + }; +``` diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpattern.getaggregationrestrictions.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpattern.getaggregationrestrictions.md new file mode 100644 index 0000000000000..b655e779e4fa4 --- /dev/null +++ b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpattern.getaggregationrestrictions.md @@ -0,0 +1,29 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-server](./kibana-plugin-plugins-data-server.md) > [IndexPattern](./kibana-plugin-plugins-data-server.indexpattern.md) > [getAggregationRestrictions](./kibana-plugin-plugins-data-server.indexpattern.getaggregationrestrictions.md) + +## IndexPattern.getAggregationRestrictions() method + +Signature: + +```typescript +getAggregationRestrictions(): Record> | undefined; +``` +Returns: + +`Record> | undefined` + diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpattern.getassavedobjectbody.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpattern.getassavedobjectbody.md new file mode 100644 index 0000000000000..f1bdb2f729414 --- /dev/null +++ b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpattern.getassavedobjectbody.md @@ -0,0 +1,35 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-server](./kibana-plugin-plugins-data-server.md) > [IndexPattern](./kibana-plugin-plugins-data-server.indexpattern.md) > [getAsSavedObjectBody](./kibana-plugin-plugins-data-server.indexpattern.getassavedobjectbody.md) + +## IndexPattern.getAsSavedObjectBody() method + +Returns index pattern as saved object body for saving + +Signature: + +```typescript +getAsSavedObjectBody(): { + title: string; + timeFieldName: string | undefined; + intervalName: string | undefined; + sourceFilters: string | undefined; + fields: string | undefined; + fieldFormatMap: string | undefined; + type: string | undefined; + typeMeta: string | undefined; + }; +``` +Returns: + +`{ + title: string; + timeFieldName: string | undefined; + intervalName: string | undefined; + sourceFilters: string | undefined; + fields: string | undefined; + fieldFormatMap: string | undefined; + type: string | undefined; + typeMeta: string | undefined; + }` + diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpattern.getcomputedfields.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpattern.getcomputedfields.md new file mode 100644 index 0000000000000..eab6ae9bf9033 --- /dev/null +++ b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpattern.getcomputedfields.md @@ -0,0 +1,29 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-server](./kibana-plugin-plugins-data-server.md) > [IndexPattern](./kibana-plugin-plugins-data-server.indexpattern.md) > [getComputedFields](./kibana-plugin-plugins-data-server.indexpattern.getcomputedfields.md) + +## IndexPattern.getComputedFields() method + +Signature: + +```typescript +getComputedFields(): { + storedFields: string[]; + scriptFields: any; + docvalueFields: { + field: any; + format: string; + }[]; + }; +``` +Returns: + +`{ + storedFields: string[]; + scriptFields: any; + docvalueFields: { + field: any; + format: string; + }[]; + }` + diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpattern.getfieldbyname.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpattern.getfieldbyname.md new file mode 100644 index 0000000000000..712be3b72828a --- /dev/null +++ b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpattern.getfieldbyname.md @@ -0,0 +1,22 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-server](./kibana-plugin-plugins-data-server.md) > [IndexPattern](./kibana-plugin-plugins-data-server.indexpattern.md) > [getFieldByName](./kibana-plugin-plugins-data-server.indexpattern.getfieldbyname.md) + +## IndexPattern.getFieldByName() method + +Signature: + +```typescript +getFieldByName(name: string): IndexPatternField | undefined; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| name | string | | + +Returns: + +`IndexPatternField | undefined` + diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpattern.getformatterforfield.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpattern.getformatterforfield.md new file mode 100644 index 0000000000000..7dc2756009f4e --- /dev/null +++ b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpattern.getformatterforfield.md @@ -0,0 +1,24 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-server](./kibana-plugin-plugins-data-server.md) > [IndexPattern](./kibana-plugin-plugins-data-server.indexpattern.md) > [getFormatterForField](./kibana-plugin-plugins-data-server.indexpattern.getformatterforfield.md) + +## IndexPattern.getFormatterForField() method + +Provide a field, get its formatter + +Signature: + +```typescript +getFormatterForField(field: IndexPatternField | IndexPatternField['spec'] | IFieldType): FieldFormat; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| field | IndexPatternField | IndexPatternField['spec'] | IFieldType | | + +Returns: + +`FieldFormat` + diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpattern.getnonscriptedfields.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpattern.getnonscriptedfields.md new file mode 100644 index 0000000000000..89d79d9b750fa --- /dev/null +++ b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpattern.getnonscriptedfields.md @@ -0,0 +1,15 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-server](./kibana-plugin-plugins-data-server.md) > [IndexPattern](./kibana-plugin-plugins-data-server.indexpattern.md) > [getNonScriptedFields](./kibana-plugin-plugins-data-server.indexpattern.getnonscriptedfields.md) + +## IndexPattern.getNonScriptedFields() method + +Signature: + +```typescript +getNonScriptedFields(): IndexPatternField[]; +``` +Returns: + +`IndexPatternField[]` + diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpattern.getoriginalsavedobjectbody.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpattern.getoriginalsavedobjectbody.md new file mode 100644 index 0000000000000..324f9d0152ab5 --- /dev/null +++ b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpattern.getoriginalsavedobjectbody.md @@ -0,0 +1,22 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-server](./kibana-plugin-plugins-data-server.md) > [IndexPattern](./kibana-plugin-plugins-data-server.indexpattern.md) > [getOriginalSavedObjectBody](./kibana-plugin-plugins-data-server.indexpattern.getoriginalsavedobjectbody.md) + +## IndexPattern.getOriginalSavedObjectBody property + +Get last saved saved object fields + +Signature: + +```typescript +getOriginalSavedObjectBody: () => { + title?: string | undefined; + timeFieldName?: string | undefined; + intervalName?: string | undefined; + fields?: string | undefined; + sourceFilters?: string | undefined; + fieldFormatMap?: string | undefined; + typeMeta?: string | undefined; + type?: string | undefined; + }; +``` diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpattern.getscriptedfields.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpattern.getscriptedfields.md new file mode 100644 index 0000000000000..edfff8ec5efac --- /dev/null +++ b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpattern.getscriptedfields.md @@ -0,0 +1,15 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-server](./kibana-plugin-plugins-data-server.md) > [IndexPattern](./kibana-plugin-plugins-data-server.indexpattern.md) > [getScriptedFields](./kibana-plugin-plugins-data-server.indexpattern.getscriptedfields.md) + +## IndexPattern.getScriptedFields() method + +Signature: + +```typescript +getScriptedFields(): IndexPatternField[]; +``` +Returns: + +`IndexPatternField[]` + diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpattern.getsourcefiltering.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpattern.getsourcefiltering.md new file mode 100644 index 0000000000000..240f9b4fb0aa2 --- /dev/null +++ b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpattern.getsourcefiltering.md @@ -0,0 +1,21 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-server](./kibana-plugin-plugins-data-server.md) > [IndexPattern](./kibana-plugin-plugins-data-server.indexpattern.md) > [getSourceFiltering](./kibana-plugin-plugins-data-server.indexpattern.getsourcefiltering.md) + +## IndexPattern.getSourceFiltering() method + +Get the source filtering configuration for that index. + +Signature: + +```typescript +getSourceFiltering(): { + excludes: any[]; + }; +``` +Returns: + +`{ + excludes: any[]; + }` + diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpattern.gettimefield.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpattern.gettimefield.md new file mode 100644 index 0000000000000..b5806f883fb9f --- /dev/null +++ b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpattern.gettimefield.md @@ -0,0 +1,15 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-server](./kibana-plugin-plugins-data-server.md) > [IndexPattern](./kibana-plugin-plugins-data-server.indexpattern.md) > [getTimeField](./kibana-plugin-plugins-data-server.indexpattern.gettimefield.md) + +## IndexPattern.getTimeField() method + +Signature: + +```typescript +getTimeField(): IndexPatternField | undefined; +``` +Returns: + +`IndexPatternField | undefined` + diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpattern.id.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpattern.id.md new file mode 100644 index 0000000000000..8fad82bd06705 --- /dev/null +++ b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpattern.id.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-server](./kibana-plugin-plugins-data-server.md) > [IndexPattern](./kibana-plugin-plugins-data-server.indexpattern.md) > [id](./kibana-plugin-plugins-data-server.indexpattern.id.md) + +## IndexPattern.id property + +Signature: + +```typescript +id?: string; +``` diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpattern.intervalname.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpattern.intervalname.md new file mode 100644 index 0000000000000..caaa6929235f8 --- /dev/null +++ b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpattern.intervalname.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-server](./kibana-plugin-plugins-data-server.md) > [IndexPattern](./kibana-plugin-plugins-data-server.indexpattern.md) > [intervalName](./kibana-plugin-plugins-data-server.indexpattern.intervalname.md) + +## IndexPattern.intervalName property + +Signature: + +```typescript +intervalName: string | undefined; +``` diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpattern.istimebased.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpattern.istimebased.md new file mode 100644 index 0000000000000..790744979942d --- /dev/null +++ b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpattern.istimebased.md @@ -0,0 +1,15 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-server](./kibana-plugin-plugins-data-server.md) > [IndexPattern](./kibana-plugin-plugins-data-server.indexpattern.md) > [isTimeBased](./kibana-plugin-plugins-data-server.indexpattern.istimebased.md) + +## IndexPattern.isTimeBased() method + +Signature: + +```typescript +isTimeBased(): boolean; +``` +Returns: + +`boolean` + diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpattern.istimenanosbased.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpattern.istimenanosbased.md new file mode 100644 index 0000000000000..22fb60eba4f6e --- /dev/null +++ b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpattern.istimenanosbased.md @@ -0,0 +1,15 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-server](./kibana-plugin-plugins-data-server.md) > [IndexPattern](./kibana-plugin-plugins-data-server.indexpattern.md) > [isTimeNanosBased](./kibana-plugin-plugins-data-server.indexpattern.istimenanosbased.md) + +## IndexPattern.isTimeNanosBased() method + +Signature: + +```typescript +isTimeNanosBased(): boolean; +``` +Returns: + +`boolean` + diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpattern.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpattern.md new file mode 100644 index 0000000000000..603864234d34b --- /dev/null +++ b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpattern.md @@ -0,0 +1,58 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-server](./kibana-plugin-plugins-data-server.md) > [IndexPattern](./kibana-plugin-plugins-data-server.indexpattern.md) + +## IndexPattern class + +Signature: + +```typescript +export declare class IndexPattern implements IIndexPattern +``` + +## Constructors + +| Constructor | Modifiers | Description | +| --- | --- | --- | +| [(constructor)({ spec, fieldFormats, shortDotsEnable, metaFields, })](./kibana-plugin-plugins-data-server.indexpattern._constructor_.md) | | Constructs a new instance of the IndexPattern class | + +## Properties + +| Property | Modifiers | Type | Description | +| --- | --- | --- | --- | +| [fieldFormatMap](./kibana-plugin-plugins-data-server.indexpattern.fieldformatmap.md) | | Record<string, any> | | +| [fields](./kibana-plugin-plugins-data-server.indexpattern.fields.md) | | IIndexPatternFieldList & {
toSpec: () => IndexPatternFieldMap;
} | | +| [flattenHit](./kibana-plugin-plugins-data-server.indexpattern.flattenhit.md) | | (hit: Record<string, any>, deep?: boolean) => Record<string, any> | | +| [formatField](./kibana-plugin-plugins-data-server.indexpattern.formatfield.md) | | FormatFieldFn | | +| [formatHit](./kibana-plugin-plugins-data-server.indexpattern.formathit.md) | | {
(hit: Record<string, any>, type?: string): any;
formatField: FormatFieldFn;
} | | +| [getOriginalSavedObjectBody](./kibana-plugin-plugins-data-server.indexpattern.getoriginalsavedobjectbody.md) | | () => {
title?: string | undefined;
timeFieldName?: string | undefined;
intervalName?: string | undefined;
fields?: string | undefined;
sourceFilters?: string | undefined;
fieldFormatMap?: string | undefined;
typeMeta?: string | undefined;
type?: string | undefined;
} | Get last saved saved object fields | +| [id](./kibana-plugin-plugins-data-server.indexpattern.id.md) | | string | | +| [intervalName](./kibana-plugin-plugins-data-server.indexpattern.intervalname.md) | | string | undefined | | +| [metaFields](./kibana-plugin-plugins-data-server.indexpattern.metafields.md) | | string[] | | +| [resetOriginalSavedObjectBody](./kibana-plugin-plugins-data-server.indexpattern.resetoriginalsavedobjectbody.md) | | () => void | Reset last saved saved object fields. used after saving | +| [sourceFilters](./kibana-plugin-plugins-data-server.indexpattern.sourcefilters.md) | | SourceFilter[] | | +| [timeFieldName](./kibana-plugin-plugins-data-server.indexpattern.timefieldname.md) | | string | undefined | | +| [title](./kibana-plugin-plugins-data-server.indexpattern.title.md) | | string | | +| [type](./kibana-plugin-plugins-data-server.indexpattern.type.md) | | string | undefined | | +| [typeMeta](./kibana-plugin-plugins-data-server.indexpattern.typemeta.md) | | TypeMeta | | +| [version](./kibana-plugin-plugins-data-server.indexpattern.version.md) | | string | undefined | | + +## Methods + +| Method | Modifiers | Description | +| --- | --- | --- | +| [addScriptedField(name, script, fieldType)](./kibana-plugin-plugins-data-server.indexpattern.addscriptedfield.md) | | Add scripted field to field list | +| [getAggregationRestrictions()](./kibana-plugin-plugins-data-server.indexpattern.getaggregationrestrictions.md) | | | +| [getAsSavedObjectBody()](./kibana-plugin-plugins-data-server.indexpattern.getassavedobjectbody.md) | | Returns index pattern as saved object body for saving | +| [getComputedFields()](./kibana-plugin-plugins-data-server.indexpattern.getcomputedfields.md) | | | +| [getFieldByName(name)](./kibana-plugin-plugins-data-server.indexpattern.getfieldbyname.md) | | | +| [getFormatterForField(field)](./kibana-plugin-plugins-data-server.indexpattern.getformatterforfield.md) | | Provide a field, get its formatter | +| [getNonScriptedFields()](./kibana-plugin-plugins-data-server.indexpattern.getnonscriptedfields.md) | | | +| [getScriptedFields()](./kibana-plugin-plugins-data-server.indexpattern.getscriptedfields.md) | | | +| [getSourceFiltering()](./kibana-plugin-plugins-data-server.indexpattern.getsourcefiltering.md) | | Get the source filtering configuration for that index. | +| [getTimeField()](./kibana-plugin-plugins-data-server.indexpattern.gettimefield.md) | | | +| [isTimeBased()](./kibana-plugin-plugins-data-server.indexpattern.istimebased.md) | | | +| [isTimeNanosBased()](./kibana-plugin-plugins-data-server.indexpattern.istimenanosbased.md) | | | +| [removeScriptedField(fieldName)](./kibana-plugin-plugins-data-server.indexpattern.removescriptedfield.md) | | Remove scripted field from field list | +| [toSpec()](./kibana-plugin-plugins-data-server.indexpattern.tospec.md) | | | + diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpattern.metafields.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpattern.metafields.md new file mode 100644 index 0000000000000..a2c7c806d6057 --- /dev/null +++ b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpattern.metafields.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-server](./kibana-plugin-plugins-data-server.md) > [IndexPattern](./kibana-plugin-plugins-data-server.indexpattern.md) > [metaFields](./kibana-plugin-plugins-data-server.indexpattern.metafields.md) + +## IndexPattern.metaFields property + +Signature: + +```typescript +metaFields: string[]; +``` diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpattern.removescriptedfield.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpattern.removescriptedfield.md new file mode 100644 index 0000000000000..3162a7f42dd12 --- /dev/null +++ b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpattern.removescriptedfield.md @@ -0,0 +1,24 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-server](./kibana-plugin-plugins-data-server.md) > [IndexPattern](./kibana-plugin-plugins-data-server.indexpattern.md) > [removeScriptedField](./kibana-plugin-plugins-data-server.indexpattern.removescriptedfield.md) + +## IndexPattern.removeScriptedField() method + +Remove scripted field from field list + +Signature: + +```typescript +removeScriptedField(fieldName: string): void; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fieldName | string | | + +Returns: + +`void` + diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpattern.resetoriginalsavedobjectbody.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpattern.resetoriginalsavedobjectbody.md new file mode 100644 index 0000000000000..18ec7070bd577 --- /dev/null +++ b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpattern.resetoriginalsavedobjectbody.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-server](./kibana-plugin-plugins-data-server.md) > [IndexPattern](./kibana-plugin-plugins-data-server.indexpattern.md) > [resetOriginalSavedObjectBody](./kibana-plugin-plugins-data-server.indexpattern.resetoriginalsavedobjectbody.md) + +## IndexPattern.resetOriginalSavedObjectBody property + +Reset last saved saved object fields. used after saving + +Signature: + +```typescript +resetOriginalSavedObjectBody: () => void; +``` diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpattern.sourcefilters.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpattern.sourcefilters.md new file mode 100644 index 0000000000000..d359bef2f30a9 --- /dev/null +++ b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpattern.sourcefilters.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-server](./kibana-plugin-plugins-data-server.md) > [IndexPattern](./kibana-plugin-plugins-data-server.indexpattern.md) > [sourceFilters](./kibana-plugin-plugins-data-server.indexpattern.sourcefilters.md) + +## IndexPattern.sourceFilters property + +Signature: + +```typescript +sourceFilters?: SourceFilter[]; +``` diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpattern.timefieldname.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpattern.timefieldname.md new file mode 100644 index 0000000000000..35740afa4e3dc --- /dev/null +++ b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpattern.timefieldname.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-server](./kibana-plugin-plugins-data-server.md) > [IndexPattern](./kibana-plugin-plugins-data-server.indexpattern.md) > [timeFieldName](./kibana-plugin-plugins-data-server.indexpattern.timefieldname.md) + +## IndexPattern.timeFieldName property + +Signature: + +```typescript +timeFieldName: string | undefined; +``` diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpattern.title.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpattern.title.md new file mode 100644 index 0000000000000..4cebde989aebd --- /dev/null +++ b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpattern.title.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-server](./kibana-plugin-plugins-data-server.md) > [IndexPattern](./kibana-plugin-plugins-data-server.indexpattern.md) > [title](./kibana-plugin-plugins-data-server.indexpattern.title.md) + +## IndexPattern.title property + +Signature: + +```typescript +title: string; +``` diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpattern.tospec.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpattern.tospec.md new file mode 100644 index 0000000000000..5d76b8f00853b --- /dev/null +++ b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpattern.tospec.md @@ -0,0 +1,15 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-server](./kibana-plugin-plugins-data-server.md) > [IndexPattern](./kibana-plugin-plugins-data-server.indexpattern.md) > [toSpec](./kibana-plugin-plugins-data-server.indexpattern.tospec.md) + +## IndexPattern.toSpec() method + +Signature: + +```typescript +toSpec(): IndexPatternSpec; +``` +Returns: + +`IndexPatternSpec` + diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpattern.type.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpattern.type.md new file mode 100644 index 0000000000000..01154ab5444d1 --- /dev/null +++ b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpattern.type.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-server](./kibana-plugin-plugins-data-server.md) > [IndexPattern](./kibana-plugin-plugins-data-server.indexpattern.md) > [type](./kibana-plugin-plugins-data-server.indexpattern.type.md) + +## IndexPattern.type property + +Signature: + +```typescript +type: string | undefined; +``` diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpattern.typemeta.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpattern.typemeta.md new file mode 100644 index 0000000000000..b16bcec404d97 --- /dev/null +++ b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpattern.typemeta.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-server](./kibana-plugin-plugins-data-server.md) > [IndexPattern](./kibana-plugin-plugins-data-server.indexpattern.md) > [typeMeta](./kibana-plugin-plugins-data-server.indexpattern.typemeta.md) + +## IndexPattern.typeMeta property + +Signature: + +```typescript +typeMeta?: TypeMeta; +``` diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpattern.version.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpattern.version.md new file mode 100644 index 0000000000000..e4297d8389111 --- /dev/null +++ b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpattern.version.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-server](./kibana-plugin-plugins-data-server.md) > [IndexPattern](./kibana-plugin-plugins-data-server.indexpattern.md) > [version](./kibana-plugin-plugins-data-server.indexpattern.version.md) + +## IndexPattern.version property + +Signature: + +```typescript +version: string | undefined; +``` diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpatternattributes.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpatternattributes.md index 4a5b61f5c179b..40b029da00469 100644 --- a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpatternattributes.md +++ b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpatternattributes.md @@ -4,12 +4,6 @@ ## IndexPatternAttributes interface -> Warning: This API is now obsolete. -> -> - -Use data plugin interface instead - Signature: ```typescript diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpatternfielddescriptor.aggregatable.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpatternfielddescriptor.aggregatable.md deleted file mode 100644 index 92994b851ec85..0000000000000 --- a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpatternfielddescriptor.aggregatable.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-plugins-data-server](./kibana-plugin-plugins-data-server.md) > [IndexPatternFieldDescriptor](./kibana-plugin-plugins-data-server.indexpatternfielddescriptor.md) > [aggregatable](./kibana-plugin-plugins-data-server.indexpatternfielddescriptor.aggregatable.md) - -## IndexPatternFieldDescriptor.aggregatable property - -Signature: - -```typescript -aggregatable: boolean; -``` diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpatternfielddescriptor.estypes.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpatternfielddescriptor.estypes.md deleted file mode 100644 index f24ba9a48d85e..0000000000000 --- a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpatternfielddescriptor.estypes.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-plugins-data-server](./kibana-plugin-plugins-data-server.md) > [IndexPatternFieldDescriptor](./kibana-plugin-plugins-data-server.indexpatternfielddescriptor.md) > [esTypes](./kibana-plugin-plugins-data-server.indexpatternfielddescriptor.estypes.md) - -## IndexPatternFieldDescriptor.esTypes property - -Signature: - -```typescript -esTypes: string[]; -``` diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpatternfielddescriptor.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpatternfielddescriptor.md deleted file mode 100644 index d84d0cba06ac6..0000000000000 --- a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpatternfielddescriptor.md +++ /dev/null @@ -1,24 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-plugins-data-server](./kibana-plugin-plugins-data-server.md) > [IndexPatternFieldDescriptor](./kibana-plugin-plugins-data-server.indexpatternfielddescriptor.md) - -## IndexPatternFieldDescriptor interface - -Signature: - -```typescript -export interface FieldDescriptor -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [aggregatable](./kibana-plugin-plugins-data-server.indexpatternfielddescriptor.aggregatable.md) | boolean | | -| [esTypes](./kibana-plugin-plugins-data-server.indexpatternfielddescriptor.estypes.md) | string[] | | -| [name](./kibana-plugin-plugins-data-server.indexpatternfielddescriptor.name.md) | string | | -| [readFromDocValues](./kibana-plugin-plugins-data-server.indexpatternfielddescriptor.readfromdocvalues.md) | boolean | | -| [searchable](./kibana-plugin-plugins-data-server.indexpatternfielddescriptor.searchable.md) | boolean | | -| [subType](./kibana-plugin-plugins-data-server.indexpatternfielddescriptor.subtype.md) | FieldSubType | | -| [type](./kibana-plugin-plugins-data-server.indexpatternfielddescriptor.type.md) | string | | - diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpatternfielddescriptor.name.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpatternfielddescriptor.name.md deleted file mode 100644 index 16ea60c5b8ae2..0000000000000 --- a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpatternfielddescriptor.name.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-plugins-data-server](./kibana-plugin-plugins-data-server.md) > [IndexPatternFieldDescriptor](./kibana-plugin-plugins-data-server.indexpatternfielddescriptor.md) > [name](./kibana-plugin-plugins-data-server.indexpatternfielddescriptor.name.md) - -## IndexPatternFieldDescriptor.name property - -Signature: - -```typescript -name: string; -``` diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpatternfielddescriptor.readfromdocvalues.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpatternfielddescriptor.readfromdocvalues.md deleted file mode 100644 index fc8667196c879..0000000000000 --- a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpatternfielddescriptor.readfromdocvalues.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-plugins-data-server](./kibana-plugin-plugins-data-server.md) > [IndexPatternFieldDescriptor](./kibana-plugin-plugins-data-server.indexpatternfielddescriptor.md) > [readFromDocValues](./kibana-plugin-plugins-data-server.indexpatternfielddescriptor.readfromdocvalues.md) - -## IndexPatternFieldDescriptor.readFromDocValues property - -Signature: - -```typescript -readFromDocValues: boolean; -``` diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpatternfielddescriptor.searchable.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpatternfielddescriptor.searchable.md deleted file mode 100644 index 7d159c65b40bd..0000000000000 --- a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpatternfielddescriptor.searchable.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-plugins-data-server](./kibana-plugin-plugins-data-server.md) > [IndexPatternFieldDescriptor](./kibana-plugin-plugins-data-server.indexpatternfielddescriptor.md) > [searchable](./kibana-plugin-plugins-data-server.indexpatternfielddescriptor.searchable.md) - -## IndexPatternFieldDescriptor.searchable property - -Signature: - -```typescript -searchable: boolean; -``` diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpatternfielddescriptor.subtype.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpatternfielddescriptor.subtype.md deleted file mode 100644 index 7053eaf08138c..0000000000000 --- a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpatternfielddescriptor.subtype.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-plugins-data-server](./kibana-plugin-plugins-data-server.md) > [IndexPatternFieldDescriptor](./kibana-plugin-plugins-data-server.indexpatternfielddescriptor.md) > [subType](./kibana-plugin-plugins-data-server.indexpatternfielddescriptor.subtype.md) - -## IndexPatternFieldDescriptor.subType property - -Signature: - -```typescript -subType?: FieldSubType; -``` diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpatternfielddescriptor.type.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpatternfielddescriptor.type.md deleted file mode 100644 index bb571d1bee14a..0000000000000 --- a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpatternfielddescriptor.type.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-plugins-data-server](./kibana-plugin-plugins-data-server.md) > [IndexPatternFieldDescriptor](./kibana-plugin-plugins-data-server.indexpatternfielddescriptor.md) > [type](./kibana-plugin-plugins-data-server.indexpatternfielddescriptor.type.md) - -## IndexPatternFieldDescriptor.type property - -Signature: - -```typescript -type: string; -``` diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpatternsfetcher.getfieldsforwildcard.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpatternsfetcher.getfieldsforwildcard.md index 6bd3bbf2433cd..52382372d6d96 100644 --- a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpatternsfetcher.getfieldsforwildcard.md +++ b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpatternsfetcher.getfieldsforwildcard.md @@ -12,6 +12,9 @@ Get a list of field objects for an index pattern that may contain wildcards getFieldsForWildcard(options: { pattern: string | string[]; metaFields?: string[]; + fieldCapsOptions?: { + allowNoIndices: boolean; + }; }): Promise; ``` @@ -19,7 +22,7 @@ getFieldsForWildcard(options: { | Parameter | Type | Description | | --- | --- | --- | -| options | {
pattern: string | string[];
metaFields?: string[];
} | | +| options | {
pattern: string | string[];
metaFields?: string[];
fieldCapsOptions?: {
allowNoIndices: boolean;
};
} | | Returns: diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpatternsservice.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpatternsservice.md new file mode 100644 index 0000000000000..aa78c055f4f5c --- /dev/null +++ b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpatternsservice.md @@ -0,0 +1,19 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-server](./kibana-plugin-plugins-data-server.md) > [IndexPatternsService](./kibana-plugin-plugins-data-server.indexpatternsservice.md) + +## IndexPatternsService class + +Signature: + +```typescript +export declare class IndexPatternsService implements Plugin +``` + +## Methods + +| Method | Modifiers | Description | +| --- | --- | --- | +| [setup(core)](./kibana-plugin-plugins-data-server.indexpatternsservice.setup.md) | | | +| [start(core, { fieldFormats, logger })](./kibana-plugin-plugins-data-server.indexpatternsservice.start.md) | | | + diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpatternsservice.setup.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpatternsservice.setup.md new file mode 100644 index 0000000000000..a354fbc2a477b --- /dev/null +++ b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpatternsservice.setup.md @@ -0,0 +1,22 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-server](./kibana-plugin-plugins-data-server.md) > [IndexPatternsService](./kibana-plugin-plugins-data-server.indexpatternsservice.md) > [setup](./kibana-plugin-plugins-data-server.indexpatternsservice.setup.md) + +## IndexPatternsService.setup() method + +Signature: + +```typescript +setup(core: CoreSetup): void; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| core | CoreSetup | | + +Returns: + +`void` + diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpatternsservice.start.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpatternsservice.start.md new file mode 100644 index 0000000000000..e7c331bad64e8 --- /dev/null +++ b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpatternsservice.start.md @@ -0,0 +1,27 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-server](./kibana-plugin-plugins-data-server.md) > [IndexPatternsService](./kibana-plugin-plugins-data-server.indexpatternsservice.md) > [start](./kibana-plugin-plugins-data-server.indexpatternsservice.start.md) + +## IndexPatternsService.start() method + +Signature: + +```typescript +start(core: CoreStart, { fieldFormats, logger }: IndexPatternsServiceStartDeps): { + indexPatternsServiceFactory: (savedObjectsClient: SavedObjectsClientContract) => Promise; + }; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| core | CoreStart | | +| { fieldFormats, logger } | IndexPatternsServiceStartDeps | | + +Returns: + +`{ + indexPatternsServiceFactory: (savedObjectsClient: SavedObjectsClientContract) => Promise; + }` + diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.isearchsetup.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.isearchsetup.md index ac2ae13372f7a..3e27140e8bc08 100644 --- a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.isearchsetup.md +++ b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.isearchsetup.md @@ -15,6 +15,6 @@ export interface ISearchSetup | Property | Type | Description | | --- | --- | --- | | [aggs](./kibana-plugin-plugins-data-server.isearchsetup.aggs.md) | AggsSetup | | -| [registerSearchStrategy](./kibana-plugin-plugins-data-server.isearchsetup.registersearchstrategy.md) | <SearchStrategyRequest extends IEsSearchRequest = IEsSearchRequest, SearchStrategyResponse extends IEsSearchResponse = IEsSearchResponse>(name: string, strategy: ISearchStrategy<SearchStrategyRequest, SearchStrategyResponse>) => void | Extension point exposed for other plugins to register their own search strategies. | +| [registerSearchStrategy](./kibana-plugin-plugins-data-server.isearchsetup.registersearchstrategy.md) | <SearchStrategyRequest extends IKibanaSearchRequest = IEsSearchRequest, SearchStrategyResponse extends IKibanaSearchResponse = IEsSearchResponse>(name: string, strategy: ISearchStrategy<SearchStrategyRequest, SearchStrategyResponse>) => void | Extension point exposed for other plugins to register their own search strategies. | | [usage](./kibana-plugin-plugins-data-server.isearchsetup.usage.md) | SearchUsage | Used internally for telemetry | diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.isearchsetup.registersearchstrategy.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.isearchsetup.registersearchstrategy.md index f20c6f4911062..81571d343495c 100644 --- a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.isearchsetup.registersearchstrategy.md +++ b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.isearchsetup.registersearchstrategy.md @@ -9,5 +9,5 @@ Extension point exposed for other plugins to register their own search strategie Signature: ```typescript -registerSearchStrategy: (name: string, strategy: ISearchStrategy) => void; +registerSearchStrategy: (name: string, strategy: ISearchStrategy) => void; ``` diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.isearchstart.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.isearchstart.md index 577532d22b3d3..9c47ea1a166d5 100644 --- a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.isearchstart.md +++ b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.isearchstart.md @@ -7,7 +7,7 @@ Signature: ```typescript -export interface ISearchStart +export interface ISearchStart ``` ## Properties @@ -16,5 +16,6 @@ export interface ISearchStartAggsStart | | | [getSearchStrategy](./kibana-plugin-plugins-data-server.isearchstart.getsearchstrategy.md) | (name: string) => ISearchStrategy<SearchStrategyRequest, SearchStrategyResponse> | Get other registered search strategies. For example, if a new strategy needs to use the already-registered ES search strategy, it can use this function to accomplish that. | -| [search](./kibana-plugin-plugins-data-server.isearchstart.search.md) | (context: RequestHandlerContext, request: IEsSearchRequest, options: ISearchOptions) => Promise<IEsSearchResponse> | | +| [search](./kibana-plugin-plugins-data-server.isearchstart.search.md) | (context: RequestHandlerContext, request: SearchStrategyRequest, options: ISearchOptions) => Promise<SearchStrategyResponse> | | +| [searchSource](./kibana-plugin-plugins-data-server.isearchstart.searchsource.md) | {
asScoped: (request: KibanaRequest) => Promise<ISearchStartSearchSource>;
} | | diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.isearchstart.search.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.isearchstart.search.md index 33ca818afc769..fdcd4d6768db5 100644 --- a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.isearchstart.search.md +++ b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.isearchstart.search.md @@ -7,5 +7,5 @@ Signature: ```typescript -search: (context: RequestHandlerContext, request: IEsSearchRequest, options: ISearchOptions) => Promise; +search: (context: RequestHandlerContext, request: SearchStrategyRequest, options: ISearchOptions) => Promise; ``` diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.isearchstart.searchsource.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.isearchstart.searchsource.md new file mode 100644 index 0000000000000..66a43fe29c43b --- /dev/null +++ b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.isearchstart.searchsource.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-server](./kibana-plugin-plugins-data-server.md) > [ISearchStart](./kibana-plugin-plugins-data-server.isearchstart.md) > [searchSource](./kibana-plugin-plugins-data-server.isearchstart.searchsource.md) + +## ISearchStart.searchSource property + +Signature: + +```typescript +searchSource: { + asScoped: (request: KibanaRequest) => Promise; + }; +``` diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.isearchstrategy.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.isearchstrategy.md index dc076455ab272..3d2caf417f3cb 100644 --- a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.isearchstrategy.md +++ b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.isearchstrategy.md @@ -9,7 +9,7 @@ Search strategy interface contains a search method that takes in a request and r Signature: ```typescript -export interface ISearchStrategy +export interface ISearchStrategy ``` ## Properties diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.md index 3c477e17503f4..f1eecd6e49b02 100644 --- a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.md +++ b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.md @@ -9,7 +9,9 @@ | Class | Description | | --- | --- | | [AggParamType](./kibana-plugin-plugins-data-server.aggparamtype.md) | | +| [IndexPattern](./kibana-plugin-plugins-data-server.indexpattern.md) | | | [IndexPatternsFetcher](./kibana-plugin-plugins-data-server.indexpatternsfetcher.md) | | +| [IndexPatternsService](./kibana-plugin-plugins-data-server.indexpatternsservice.md) | | | [OptionedParamType](./kibana-plugin-plugins-data-server.optionedparamtype.md) | | | [Plugin](./kibana-plugin-plugins-data-server.plugin.md) | | @@ -41,14 +43,12 @@ | --- | --- | | [AggParamOption](./kibana-plugin-plugins-data-server.aggparamoption.md) | | | [EsQueryConfig](./kibana-plugin-plugins-data-server.esqueryconfig.md) | | +| [FieldDescriptor](./kibana-plugin-plugins-data-server.fielddescriptor.md) | | | [FieldFormatConfig](./kibana-plugin-plugins-data-server.fieldformatconfig.md) | | | [IEsSearchRequest](./kibana-plugin-plugins-data-server.iessearchrequest.md) | | -| [IEsSearchResponse](./kibana-plugin-plugins-data-server.iessearchresponse.md) | | | [IFieldSubType](./kibana-plugin-plugins-data-server.ifieldsubtype.md) | | | [IFieldType](./kibana-plugin-plugins-data-server.ifieldtype.md) | | -| [IIndexPattern](./kibana-plugin-plugins-data-server.iindexpattern.md) | | -| [IndexPatternAttributes](./kibana-plugin-plugins-data-server.indexpatternattributes.md) | Use data plugin interface instead | -| [IndexPatternFieldDescriptor](./kibana-plugin-plugins-data-server.indexpatternfielddescriptor.md) | | +| [IndexPatternAttributes](./kibana-plugin-plugins-data-server.indexpatternattributes.md) | | | [ISearchOptions](./kibana-plugin-plugins-data-server.isearchoptions.md) | | | [ISearchSetup](./kibana-plugin-plugins-data-server.isearchsetup.md) | | | [ISearchStart](./kibana-plugin-plugins-data-server.isearchstart.md) | | @@ -91,6 +91,7 @@ | [Filter](./kibana-plugin-plugins-data-server.filter.md) | | | [IAggConfig](./kibana-plugin-plugins-data-server.iaggconfig.md) | AggConfig This class represents an aggregation, which is displayed in the left-hand nav of the Visualize app. | | [IAggType](./kibana-plugin-plugins-data-server.iaggtype.md) | | +| [IEsSearchResponse](./kibana-plugin-plugins-data-server.iessearchresponse.md) | | | [IFieldFormatsRegistry](./kibana-plugin-plugins-data-server.ifieldformatsregistry.md) | | | [IFieldParamType](./kibana-plugin-plugins-data-server.ifieldparamtype.md) | | | [IMetricAggType](./kibana-plugin-plugins-data-server.imetricaggtype.md) | | diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.plugin.start.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.plugin.start.md index 455c5ecdd8195..215eac9829451 100644 --- a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.plugin.start.md +++ b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.plugin.start.md @@ -8,13 +8,13 @@ ```typescript start(core: CoreStart): { - search: ISearchStart>; fieldFormats: { fieldFormatServiceFactory: (uiSettings: import("../../../core/server").IUiSettingsClient) => Promise; }; indexPatterns: { - indexPatternsServiceFactory: (kibanaRequest: import("../../../core/server").KibanaRequest) => Promise; + indexPatternsServiceFactory: (savedObjectsClient: Pick) => Promise; }; + search: ISearchStart>; }; ``` @@ -27,12 +27,12 @@ start(core: CoreStart): { Returns: `{ - search: ISearchStart>; fieldFormats: { fieldFormatServiceFactory: (uiSettings: import("../../../core/server").IUiSettingsClient) => Promise; }; indexPatterns: { - indexPatternsServiceFactory: (kibanaRequest: import("../../../core/server").KibanaRequest) => Promise; + indexPatternsServiceFactory: (savedObjectsClient: Pick) => Promise; }; + search: ISearchStart>; }` diff --git a/docs/development/plugins/embeddable/public/index.md b/docs/development/plugins/embeddable/public/index.md new file mode 100644 index 0000000000000..5de9666f6d0b9 --- /dev/null +++ b/docs/development/plugins/embeddable/public/index.md @@ -0,0 +1,12 @@ + + +[Home](./index.md) + +## API Reference + +## Packages + +| Package | Description | +| --- | --- | +| [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) | | + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.action_add_panel.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.action_add_panel.md new file mode 100644 index 0000000000000..37c7a546d11ed --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.action_add_panel.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [ACTION\_ADD\_PANEL](./kibana-plugin-plugins-embeddable-public.action_add_panel.md) + +## ACTION\_ADD\_PANEL variable + +Signature: + +```typescript +ACTION_ADD_PANEL = "ACTION_ADD_PANEL" +``` diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.action_edit_panel.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.action_edit_panel.md new file mode 100644 index 0000000000000..89f02e69f2260 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.action_edit_panel.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [ACTION\_EDIT\_PANEL](./kibana-plugin-plugins-embeddable-public.action_edit_panel.md) + +## ACTION\_EDIT\_PANEL variable + +Signature: + +```typescript +ACTION_EDIT_PANEL = "editPanel" +``` diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.adapters.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.adapters.md new file mode 100644 index 0000000000000..9635b36cdf05a --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.adapters.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [Adapters](./kibana-plugin-plugins-embeddable-public.adapters.md) + +## Adapters interface + +The interface that the adapters used to open an inspector have to fullfill. + +Signature: + +```typescript +export interface Adapters +``` diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.addpanelaction._constructor_.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.addpanelaction._constructor_.md new file mode 100644 index 0000000000000..388f0e064d866 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.addpanelaction._constructor_.md @@ -0,0 +1,24 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [AddPanelAction](./kibana-plugin-plugins-embeddable-public.addpanelaction.md) > [(constructor)](./kibana-plugin-plugins-embeddable-public.addpanelaction._constructor_.md) + +## AddPanelAction.(constructor) + +Constructs a new instance of the `AddPanelAction` class + +Signature: + +```typescript +constructor(getFactory: EmbeddableStart['getEmbeddableFactory'], getAllFactories: EmbeddableStart['getEmbeddableFactories'], overlays: OverlayStart, notifications: NotificationsStart, SavedObjectFinder: React.ComponentType); +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| getFactory | EmbeddableStart['getEmbeddableFactory'] | | +| getAllFactories | EmbeddableStart['getEmbeddableFactories'] | | +| overlays | OverlayStart | | +| notifications | NotificationsStart | | +| SavedObjectFinder | React.ComponentType<any> | | + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.addpanelaction.execute.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.addpanelaction.execute.md new file mode 100644 index 0000000000000..46629f3c654f8 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.addpanelaction.execute.md @@ -0,0 +1,22 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [AddPanelAction](./kibana-plugin-plugins-embeddable-public.addpanelaction.md) > [execute](./kibana-plugin-plugins-embeddable-public.addpanelaction.execute.md) + +## AddPanelAction.execute() method + +Signature: + +```typescript +execute(context: ActionExecutionContext): Promise; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| context | ActionExecutionContext<ActionContext> | | + +Returns: + +`Promise` + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.addpanelaction.getdisplayname.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.addpanelaction.getdisplayname.md new file mode 100644 index 0000000000000..b3a181861572b --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.addpanelaction.getdisplayname.md @@ -0,0 +1,15 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [AddPanelAction](./kibana-plugin-plugins-embeddable-public.addpanelaction.md) > [getDisplayName](./kibana-plugin-plugins-embeddable-public.addpanelaction.getdisplayname.md) + +## AddPanelAction.getDisplayName() method + +Signature: + +```typescript +getDisplayName(): string; +``` +Returns: + +`string` + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.addpanelaction.geticontype.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.addpanelaction.geticontype.md new file mode 100644 index 0000000000000..c02aa6613630b --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.addpanelaction.geticontype.md @@ -0,0 +1,15 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [AddPanelAction](./kibana-plugin-plugins-embeddable-public.addpanelaction.md) > [getIconType](./kibana-plugin-plugins-embeddable-public.addpanelaction.geticontype.md) + +## AddPanelAction.getIconType() method + +Signature: + +```typescript +getIconType(): string; +``` +Returns: + +`string` + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.addpanelaction.id.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.addpanelaction.id.md new file mode 100644 index 0000000000000..781fb8ed29372 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.addpanelaction.id.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [AddPanelAction](./kibana-plugin-plugins-embeddable-public.addpanelaction.md) > [id](./kibana-plugin-plugins-embeddable-public.addpanelaction.id.md) + +## AddPanelAction.id property + +Signature: + +```typescript +readonly id = "ACTION_ADD_PANEL"; +``` diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.addpanelaction.iscompatible.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.addpanelaction.iscompatible.md new file mode 100644 index 0000000000000..c8349b86cf348 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.addpanelaction.iscompatible.md @@ -0,0 +1,22 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [AddPanelAction](./kibana-plugin-plugins-embeddable-public.addpanelaction.md) > [isCompatible](./kibana-plugin-plugins-embeddable-public.addpanelaction.iscompatible.md) + +## AddPanelAction.isCompatible() method + +Signature: + +```typescript +isCompatible(context: ActionExecutionContext): Promise; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| context | ActionExecutionContext<ActionContext> | | + +Returns: + +`Promise` + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.addpanelaction.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.addpanelaction.md new file mode 100644 index 0000000000000..74a6c2b2183a2 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.addpanelaction.md @@ -0,0 +1,34 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [AddPanelAction](./kibana-plugin-plugins-embeddable-public.addpanelaction.md) + +## AddPanelAction class + +Signature: + +```typescript +export declare class AddPanelAction implements Action +``` + +## Constructors + +| Constructor | Modifiers | Description | +| --- | --- | --- | +| [(constructor)(getFactory, getAllFactories, overlays, notifications, SavedObjectFinder)](./kibana-plugin-plugins-embeddable-public.addpanelaction._constructor_.md) | | Constructs a new instance of the AddPanelAction class | + +## Properties + +| Property | Modifiers | Type | Description | +| --- | --- | --- | --- | +| [id](./kibana-plugin-plugins-embeddable-public.addpanelaction.id.md) | | | | +| [type](./kibana-plugin-plugins-embeddable-public.addpanelaction.type.md) | | | | + +## Methods + +| Method | Modifiers | Description | +| --- | --- | --- | +| [execute(context)](./kibana-plugin-plugins-embeddable-public.addpanelaction.execute.md) | | | +| [getDisplayName()](./kibana-plugin-plugins-embeddable-public.addpanelaction.getdisplayname.md) | | | +| [getIconType()](./kibana-plugin-plugins-embeddable-public.addpanelaction.geticontype.md) | | | +| [isCompatible(context)](./kibana-plugin-plugins-embeddable-public.addpanelaction.iscompatible.md) | | | + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.addpanelaction.type.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.addpanelaction.type.md new file mode 100644 index 0000000000000..d57974c984025 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.addpanelaction.type.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [AddPanelAction](./kibana-plugin-plugins-embeddable-public.addpanelaction.md) > [type](./kibana-plugin-plugins-embeddable-public.addpanelaction.type.md) + +## AddPanelAction.type property + +Signature: + +```typescript +readonly type = "ACTION_ADD_PANEL"; +``` diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.attribute_service_key.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.attribute_service_key.md new file mode 100644 index 0000000000000..9504d50cf92d3 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.attribute_service_key.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [ATTRIBUTE\_SERVICE\_KEY](./kibana-plugin-plugins-embeddable-public.attribute_service_key.md) + +## ATTRIBUTE\_SERVICE\_KEY variable + +The attribute service is a shared, generic service that embeddables can use to provide the functionality required to fulfill the requirements of the ReferenceOrValueEmbeddable interface. The attribute\_service can also be used as a higher level wrapper to transform an embeddable input shape that references a saved object into an embeddable input shape that contains that saved object's attributes by value. + +Signature: + +```typescript +ATTRIBUTE_SERVICE_KEY = "attributes" +``` diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.attributeservice._constructor_.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.attributeservice._constructor_.md new file mode 100644 index 0000000000000..930250be2018b --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.attributeservice._constructor_.md @@ -0,0 +1,25 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [AttributeService](./kibana-plugin-plugins-embeddable-public.attributeservice.md) > [(constructor)](./kibana-plugin-plugins-embeddable-public.attributeservice._constructor_.md) + +## AttributeService.(constructor) + +Constructs a new instance of the `AttributeService` class + +Signature: + +```typescript +constructor(type: string, showSaveModal: (saveModal: React.ReactElement, I18nContext: I18nStart['Context']) => void, i18nContext: I18nStart['Context'], toasts: NotificationsStart['toasts'], options: AttributeServiceOptions, getEmbeddableFactory?: (embeddableFactoryId: string) => EmbeddableFactory); +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| type | string | | +| showSaveModal | (saveModal: React.ReactElement, I18nContext: I18nStart['Context']) => void | | +| i18nContext | I18nStart['Context'] | | +| toasts | NotificationsStart['toasts'] | | +| options | AttributeServiceOptions<SavedObjectAttributes> | | +| getEmbeddableFactory | (embeddableFactoryId: string) => EmbeddableFactory | | + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.attributeservice.getexplicitinputfromembeddable.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.attributeservice.getexplicitinputfromembeddable.md new file mode 100644 index 0000000000000..e3f27723e1a70 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.attributeservice.getexplicitinputfromembeddable.md @@ -0,0 +1,22 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [AttributeService](./kibana-plugin-plugins-embeddable-public.attributeservice.md) > [getExplicitInputFromEmbeddable](./kibana-plugin-plugins-embeddable-public.attributeservice.getexplicitinputfromembeddable.md) + +## AttributeService.getExplicitInputFromEmbeddable() method + +Signature: + +```typescript +getExplicitInputFromEmbeddable(embeddable: IEmbeddable): ValType | RefType; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| embeddable | IEmbeddable | | + +Returns: + +`ValType | RefType` + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.attributeservice.getinputasreftype.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.attributeservice.getinputasreftype.md new file mode 100644 index 0000000000000..7908327c594d8 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.attributeservice.getinputasreftype.md @@ -0,0 +1,16 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [AttributeService](./kibana-plugin-plugins-embeddable-public.attributeservice.md) > [getInputAsRefType](./kibana-plugin-plugins-embeddable-public.attributeservice.getinputasreftype.md) + +## AttributeService.getInputAsRefType property + +Signature: + +```typescript +getInputAsRefType: (input: ValType | RefType, saveOptions?: { + showSaveModal: boolean; + saveModalTitle?: string | undefined; + } | { + title: string; + } | undefined) => Promise; +``` diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.attributeservice.getinputasvaluetype.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.attributeservice.getinputasvaluetype.md new file mode 100644 index 0000000000000..939194575cbb7 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.attributeservice.getinputasvaluetype.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [AttributeService](./kibana-plugin-plugins-embeddable-public.attributeservice.md) > [getInputAsValueType](./kibana-plugin-plugins-embeddable-public.attributeservice.getinputasvaluetype.md) + +## AttributeService.getInputAsValueType property + +Signature: + +```typescript +getInputAsValueType: (input: ValType | RefType) => Promise; +``` diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.attributeservice.inputisreftype.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.attributeservice.inputisreftype.md new file mode 100644 index 0000000000000..c17ad97c3eeed --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.attributeservice.inputisreftype.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [AttributeService](./kibana-plugin-plugins-embeddable-public.attributeservice.md) > [inputIsRefType](./kibana-plugin-plugins-embeddable-public.attributeservice.inputisreftype.md) + +## AttributeService.inputIsRefType property + +Signature: + +```typescript +inputIsRefType: (input: ValType | RefType) => input is RefType; +``` diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.attributeservice.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.attributeservice.md new file mode 100644 index 0000000000000..b63516c909d3c --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.attributeservice.md @@ -0,0 +1,40 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [AttributeService](./kibana-plugin-plugins-embeddable-public.attributeservice.md) + +## AttributeService class + +Signature: + +```typescript +export declare class AttributeService +``` + +## Constructors + +| Constructor | Modifiers | Description | +| --- | --- | --- | +| [(constructor)(type, showSaveModal, i18nContext, toasts, options, getEmbeddableFactory)](./kibana-plugin-plugins-embeddable-public.attributeservice._constructor_.md) | | Constructs a new instance of the AttributeService class | + +## Properties + +| Property | Modifiers | Type | Description | +| --- | --- | --- | --- | +| [getInputAsRefType](./kibana-plugin-plugins-embeddable-public.attributeservice.getinputasreftype.md) | | (input: ValType | RefType, saveOptions?: {
showSaveModal: boolean;
saveModalTitle?: string | undefined;
} | {
title: string;
} | undefined) => Promise<RefType> | | +| [getInputAsValueType](./kibana-plugin-plugins-embeddable-public.attributeservice.getinputasvaluetype.md) | | (input: ValType | RefType) => Promise<ValType> | | +| [inputIsRefType](./kibana-plugin-plugins-embeddable-public.attributeservice.inputisreftype.md) | | (input: ValType | RefType) => input is RefType | | + +## Methods + +| Method | Modifiers | Description | +| --- | --- | --- | +| [getExplicitInputFromEmbeddable(embeddable)](./kibana-plugin-plugins-embeddable-public.attributeservice.getexplicitinputfromembeddable.md) | | | +| [unwrapAttributes(input)](./kibana-plugin-plugins-embeddable-public.attributeservice.unwrapattributes.md) | | | +| [wrapAttributes(newAttributes, useRefType, input)](./kibana-plugin-plugins-embeddable-public.attributeservice.wrapattributes.md) | | | + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.attributeservice.unwrapattributes.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.attributeservice.unwrapattributes.md new file mode 100644 index 0000000000000..f08736a2240a3 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.attributeservice.unwrapattributes.md @@ -0,0 +1,22 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [AttributeService](./kibana-plugin-plugins-embeddable-public.attributeservice.md) > [unwrapAttributes](./kibana-plugin-plugins-embeddable-public.attributeservice.unwrapattributes.md) + +## AttributeService.unwrapAttributes() method + +Signature: + +```typescript +unwrapAttributes(input: RefType | ValType): Promise; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| input | RefType | ValType | | + +Returns: + +`Promise` + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.attributeservice.wrapattributes.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.attributeservice.wrapattributes.md new file mode 100644 index 0000000000000..e22a2ec3faeb4 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.attributeservice.wrapattributes.md @@ -0,0 +1,24 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [AttributeService](./kibana-plugin-plugins-embeddable-public.attributeservice.md) > [wrapAttributes](./kibana-plugin-plugins-embeddable-public.attributeservice.wrapattributes.md) + +## AttributeService.wrapAttributes() method + +Signature: + +```typescript +wrapAttributes(newAttributes: SavedObjectAttributes, useRefType: boolean, input?: ValType | RefType): Promise>; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| newAttributes | SavedObjectAttributes | | +| useRefType | boolean | | +| input | ValType | RefType | | + +Returns: + +`Promise>` + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.chartactioncontext.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.chartactioncontext.md new file mode 100644 index 0000000000000..1c9fc27d53f19 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.chartactioncontext.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [ChartActionContext](./kibana-plugin-plugins-embeddable-public.chartactioncontext.md) + +## ChartActionContext type + +Signature: + +```typescript +export declare type ChartActionContext = ValueClickContext | RangeSelectContext; +``` diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.container._constructor_.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.container._constructor_.md new file mode 100644 index 0000000000000..c571bae7c7613 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.container._constructor_.md @@ -0,0 +1,23 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [Container](./kibana-plugin-plugins-embeddable-public.container.md) > [(constructor)](./kibana-plugin-plugins-embeddable-public.container._constructor_.md) + +## Container.(constructor) + +Constructs a new instance of the `Container` class + +Signature: + +```typescript +constructor(input: TContainerInput, output: TContainerOutput, getFactory: EmbeddableStart['getEmbeddableFactory'], parent?: Container); +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| input | TContainerInput | | +| output | TContainerOutput | | +| getFactory | EmbeddableStart['getEmbeddableFactory'] | | +| parent | Container | | + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.container.addnewembeddable.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.container.addnewembeddable.md new file mode 100644 index 0000000000000..1a7b32fea5361 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.container.addnewembeddable.md @@ -0,0 +1,23 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [Container](./kibana-plugin-plugins-embeddable-public.container.md) > [addNewEmbeddable](./kibana-plugin-plugins-embeddable-public.container.addnewembeddable.md) + +## Container.addNewEmbeddable() method + +Signature: + +```typescript +addNewEmbeddable = IEmbeddable>(type: string, explicitInput: Partial): Promise; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| type | string | | +| explicitInput | Partial<EEI> | | + +Returns: + +`Promise` + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.container.children.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.container.children.md new file mode 100644 index 0000000000000..e8f140219ed9c --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.container.children.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [Container](./kibana-plugin-plugins-embeddable-public.container.md) > [children](./kibana-plugin-plugins-embeddable-public.container.children.md) + +## Container.children property + +Signature: + +```typescript +protected readonly children: { + [key: string]: IEmbeddable | ErrorEmbeddable; + }; +``` diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.container.createnewpanelstate.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.container.createnewpanelstate.md new file mode 100644 index 0000000000000..cb084192ccf23 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.container.createnewpanelstate.md @@ -0,0 +1,23 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [Container](./kibana-plugin-plugins-embeddable-public.container.md) > [createNewPanelState](./kibana-plugin-plugins-embeddable-public.container.createnewpanelstate.md) + +## Container.createNewPanelState() method + +Signature: + +```typescript +protected createNewPanelState>(factory: EmbeddableFactory, partial?: Partial): PanelState; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| factory | EmbeddableFactory<TEmbeddableInput, any, TEmbeddable> | | +| partial | Partial<TEmbeddableInput> | | + +Returns: + +`PanelState` + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.container.destroy.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.container.destroy.md new file mode 100644 index 0000000000000..d2776fb9e5944 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.container.destroy.md @@ -0,0 +1,15 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [Container](./kibana-plugin-plugins-embeddable-public.container.md) > [destroy](./kibana-plugin-plugins-embeddable-public.container.destroy.md) + +## Container.destroy() method + +Signature: + +```typescript +destroy(): void; +``` +Returns: + +`void` + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.container.getchild.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.container.getchild.md new file mode 100644 index 0000000000000..56d6a8a105bc7 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.container.getchild.md @@ -0,0 +1,22 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [Container](./kibana-plugin-plugins-embeddable-public.container.md) > [getChild](./kibana-plugin-plugins-embeddable-public.container.getchild.md) + +## Container.getChild() method + +Signature: + +```typescript +getChild(id: string): E; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| id | string | | + +Returns: + +`E` + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.container.getchildids.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.container.getchildids.md new file mode 100644 index 0000000000000..83a9b134cad3f --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.container.getchildids.md @@ -0,0 +1,15 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [Container](./kibana-plugin-plugins-embeddable-public.container.md) > [getChildIds](./kibana-plugin-plugins-embeddable-public.container.getchildids.md) + +## Container.getChildIds() method + +Signature: + +```typescript +getChildIds(): string[]; +``` +Returns: + +`string[]` + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.container.getfactory.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.container.getfactory.md new file mode 100644 index 0000000000000..f4ac95abbf372 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.container.getfactory.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [Container](./kibana-plugin-plugins-embeddable-public.container.md) > [getFactory](./kibana-plugin-plugins-embeddable-public.container.getfactory.md) + +## Container.getFactory property + +Signature: + +```typescript +protected readonly getFactory: EmbeddableStart['getEmbeddableFactory']; +``` diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.container.getinheritedinput.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.container.getinheritedinput.md new file mode 100644 index 0000000000000..4c5823b890e65 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.container.getinheritedinput.md @@ -0,0 +1,24 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [Container](./kibana-plugin-plugins-embeddable-public.container.md) > [getInheritedInput](./kibana-plugin-plugins-embeddable-public.container.getinheritedinput.md) + +## Container.getInheritedInput() method + +Return state that comes from the container and is passed down to the child. For instance, time range and filters are common inherited input state. Note that any state stored in `this.input.panels[embeddableId].explicitInput` will override inherited input. + +Signature: + +```typescript +protected abstract getInheritedInput(id: string): TChildInput; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| id | string | | + +Returns: + +`TChildInput` + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.container.getinputforchild.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.container.getinputforchild.md new file mode 100644 index 0000000000000..803356d554012 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.container.getinputforchild.md @@ -0,0 +1,22 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [Container](./kibana-plugin-plugins-embeddable-public.container.md) > [getInputForChild](./kibana-plugin-plugins-embeddable-public.container.getinputforchild.md) + +## Container.getInputForChild() method + +Signature: + +```typescript +getInputForChild(embeddableId: string): TEmbeddableInput; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| embeddableId | string | | + +Returns: + +`TEmbeddableInput` + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.container.getpanelstate.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.container.getpanelstate.md new file mode 100644 index 0000000000000..5981284e0497c --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.container.getpanelstate.md @@ -0,0 +1,22 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [Container](./kibana-plugin-plugins-embeddable-public.container.md) > [getPanelState](./kibana-plugin-plugins-embeddable-public.container.getpanelstate.md) + +## Container.getPanelState() method + +Signature: + +```typescript +protected getPanelState(embeddableId: string): PanelState; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| embeddableId | string | | + +Returns: + +`PanelState` + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.container.iscontainer.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.container.iscontainer.md new file mode 100644 index 0000000000000..af65381de78f7 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.container.iscontainer.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [Container](./kibana-plugin-plugins-embeddable-public.container.md) > [isContainer](./kibana-plugin-plugins-embeddable-public.container.iscontainer.md) + +## Container.isContainer property + +Signature: + +```typescript +readonly isContainer: boolean; +``` diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.container.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.container.md new file mode 100644 index 0000000000000..d14adc31e4123 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.container.md @@ -0,0 +1,43 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [Container](./kibana-plugin-plugins-embeddable-public.container.md) + +## Container class + +Signature: + +```typescript +export declare abstract class Container = {}, TContainerInput extends ContainerInput = ContainerInput, TContainerOutput extends ContainerOutput = ContainerOutput> extends Embeddable implements IContainer +``` + +## Constructors + +| Constructor | Modifiers | Description | +| --- | --- | --- | +| [(constructor)(input, output, getFactory, parent)](./kibana-plugin-plugins-embeddable-public.container._constructor_.md) | | Constructs a new instance of the Container class | + +## Properties + +| Property | Modifiers | Type | Description | +| --- | --- | --- | --- | +| [children](./kibana-plugin-plugins-embeddable-public.container.children.md) | | {
[key: string]: IEmbeddable<any, any> | ErrorEmbeddable;
} | | +| [getFactory](./kibana-plugin-plugins-embeddable-public.container.getfactory.md) | | EmbeddableStart['getEmbeddableFactory'] | | +| [isContainer](./kibana-plugin-plugins-embeddable-public.container.iscontainer.md) | | boolean | | + +## Methods + +| Method | Modifiers | Description | +| --- | --- | --- | +| [addNewEmbeddable(type, explicitInput)](./kibana-plugin-plugins-embeddable-public.container.addnewembeddable.md) | | | +| [createNewPanelState(factory, partial)](./kibana-plugin-plugins-embeddable-public.container.createnewpanelstate.md) | | | +| [destroy()](./kibana-plugin-plugins-embeddable-public.container.destroy.md) | | | +| [getChild(id)](./kibana-plugin-plugins-embeddable-public.container.getchild.md) | | | +| [getChildIds()](./kibana-plugin-plugins-embeddable-public.container.getchildids.md) | | | +| [getInheritedInput(id)](./kibana-plugin-plugins-embeddable-public.container.getinheritedinput.md) | | Return state that comes from the container and is passed down to the child. For instance, time range and filters are common inherited input state. Note that any state stored in this.input.panels[embeddableId].explicitInput will override inherited input. | +| [getInputForChild(embeddableId)](./kibana-plugin-plugins-embeddable-public.container.getinputforchild.md) | | | +| [getPanelState(embeddableId)](./kibana-plugin-plugins-embeddable-public.container.getpanelstate.md) | | | +| [reload()](./kibana-plugin-plugins-embeddable-public.container.reload.md) | | | +| [removeEmbeddable(embeddableId)](./kibana-plugin-plugins-embeddable-public.container.removeembeddable.md) | | | +| [untilEmbeddableLoaded(id)](./kibana-plugin-plugins-embeddable-public.container.untilembeddableloaded.md) | | | +| [updateInputForChild(id, changes)](./kibana-plugin-plugins-embeddable-public.container.updateinputforchild.md) | | | + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.container.reload.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.container.reload.md new file mode 100644 index 0000000000000..902da827ac46c --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.container.reload.md @@ -0,0 +1,15 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [Container](./kibana-plugin-plugins-embeddable-public.container.md) > [reload](./kibana-plugin-plugins-embeddable-public.container.reload.md) + +## Container.reload() method + +Signature: + +```typescript +reload(): void; +``` +Returns: + +`void` + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.container.removeembeddable.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.container.removeembeddable.md new file mode 100644 index 0000000000000..44594c0649d46 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.container.removeembeddable.md @@ -0,0 +1,22 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [Container](./kibana-plugin-plugins-embeddable-public.container.md) > [removeEmbeddable](./kibana-plugin-plugins-embeddable-public.container.removeembeddable.md) + +## Container.removeEmbeddable() method + +Signature: + +```typescript +removeEmbeddable(embeddableId: string): void; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| embeddableId | string | | + +Returns: + +`void` + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.container.untilembeddableloaded.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.container.untilembeddableloaded.md new file mode 100644 index 0000000000000..45c115f370694 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.container.untilembeddableloaded.md @@ -0,0 +1,22 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [Container](./kibana-plugin-plugins-embeddable-public.container.md) > [untilEmbeddableLoaded](./kibana-plugin-plugins-embeddable-public.container.untilembeddableloaded.md) + +## Container.untilEmbeddableLoaded() method + +Signature: + +```typescript +untilEmbeddableLoaded(id: string): Promise; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| id | string | | + +Returns: + +`Promise` + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.container.updateinputforchild.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.container.updateinputforchild.md new file mode 100644 index 0000000000000..ae25f373a907b --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.container.updateinputforchild.md @@ -0,0 +1,23 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [Container](./kibana-plugin-plugins-embeddable-public.container.md) > [updateInputForChild](./kibana-plugin-plugins-embeddable-public.container.updateinputforchild.md) + +## Container.updateInputForChild() method + +Signature: + +```typescript +updateInputForChild(id: string, changes: Partial): void; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| id | string | | +| changes | Partial<EEI> | | + +Returns: + +`void` + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.containerinput.hidepaneltitles.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.containerinput.hidepaneltitles.md new file mode 100644 index 0000000000000..5bb80ae411a78 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.containerinput.hidepaneltitles.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [ContainerInput](./kibana-plugin-plugins-embeddable-public.containerinput.md) > [hidePanelTitles](./kibana-plugin-plugins-embeddable-public.containerinput.hidepaneltitles.md) + +## ContainerInput.hidePanelTitles property + +Signature: + +```typescript +hidePanelTitles?: boolean; +``` diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.containerinput.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.containerinput.md new file mode 100644 index 0000000000000..dc24507b71cfb --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.containerinput.md @@ -0,0 +1,19 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [ContainerInput](./kibana-plugin-plugins-embeddable-public.containerinput.md) + +## ContainerInput interface + +Signature: + +```typescript +export interface ContainerInput extends EmbeddableInput +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [hidePanelTitles](./kibana-plugin-plugins-embeddable-public.containerinput.hidepaneltitles.md) | boolean | | +| [panels](./kibana-plugin-plugins-embeddable-public.containerinput.panels.md) | {
[key: string]: PanelState<PanelExplicitInput & EmbeddableInput & {
id: string;
}>;
} | | + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.containerinput.panels.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.containerinput.panels.md new file mode 100644 index 0000000000000..82d45ebe9a10e --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.containerinput.panels.md @@ -0,0 +1,15 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [ContainerInput](./kibana-plugin-plugins-embeddable-public.containerinput.md) > [panels](./kibana-plugin-plugins-embeddable-public.containerinput.panels.md) + +## ContainerInput.panels property + +Signature: + +```typescript +panels: { + [key: string]: PanelState; + }; +``` diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.containeroutput.embeddableloaded.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.containeroutput.embeddableloaded.md new file mode 100644 index 0000000000000..3f0db4eba0bc3 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.containeroutput.embeddableloaded.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [ContainerOutput](./kibana-plugin-plugins-embeddable-public.containeroutput.md) > [embeddableLoaded](./kibana-plugin-plugins-embeddable-public.containeroutput.embeddableloaded.md) + +## ContainerOutput.embeddableLoaded property + +Signature: + +```typescript +embeddableLoaded: { + [key: string]: boolean; + }; +``` diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.containeroutput.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.containeroutput.md new file mode 100644 index 0000000000000..f448f0f3ac059 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.containeroutput.md @@ -0,0 +1,18 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [ContainerOutput](./kibana-plugin-plugins-embeddable-public.containeroutput.md) + +## ContainerOutput interface + +Signature: + +```typescript +export interface ContainerOutput extends EmbeddableOutput +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [embeddableLoaded](./kibana-plugin-plugins-embeddable-public.containeroutput.embeddableloaded.md) | {
[key: string]: boolean;
} | | + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.context_menu_trigger.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.context_menu_trigger.md new file mode 100644 index 0000000000000..bcfcf6a321661 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.context_menu_trigger.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [CONTEXT\_MENU\_TRIGGER](./kibana-plugin-plugins-embeddable-public.context_menu_trigger.md) + +## CONTEXT\_MENU\_TRIGGER variable + +Signature: + +```typescript +CONTEXT_MENU_TRIGGER = "CONTEXT_MENU_TRIGGER" +``` diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.contextmenutrigger.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.contextmenutrigger.md new file mode 100644 index 0000000000000..0a88e1e0a2ea8 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.contextmenutrigger.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [contextMenuTrigger](./kibana-plugin-plugins-embeddable-public.contextmenutrigger.md) + +## contextMenuTrigger variable + +Signature: + +```typescript +contextMenuTrigger: Trigger<'CONTEXT_MENU_TRIGGER'> +``` diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.defaultembeddablefactoryprovider.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.defaultembeddablefactoryprovider.md new file mode 100644 index 0000000000000..08047a7a441b8 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.defaultembeddablefactoryprovider.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [defaultEmbeddableFactoryProvider](./kibana-plugin-plugins-embeddable-public.defaultembeddablefactoryprovider.md) + +## defaultEmbeddableFactoryProvider variable + +Signature: + +```typescript +defaultEmbeddableFactoryProvider: = IEmbeddable, T extends SavedObjectAttributes = SavedObjectAttributes>(def: EmbeddableFactoryDefinition) => EmbeddableFactory +``` diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.editpanelaction._constructor_.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.editpanelaction._constructor_.md new file mode 100644 index 0000000000000..55bb3d76b99d8 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.editpanelaction._constructor_.md @@ -0,0 +1,22 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [EditPanelAction](./kibana-plugin-plugins-embeddable-public.editpanelaction.md) > [(constructor)](./kibana-plugin-plugins-embeddable-public.editpanelaction._constructor_.md) + +## EditPanelAction.(constructor) + +Constructs a new instance of the `EditPanelAction` class + +Signature: + +```typescript +constructor(getEmbeddableFactory: EmbeddableStart['getEmbeddableFactory'], application: ApplicationStart, stateTransfer?: EmbeddableStateTransfer | undefined); +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| getEmbeddableFactory | EmbeddableStart['getEmbeddableFactory'] | | +| application | ApplicationStart | | +| stateTransfer | EmbeddableStateTransfer | undefined | | + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.editpanelaction.currentappid.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.editpanelaction.currentappid.md new file mode 100644 index 0000000000000..db94b1482d8b5 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.editpanelaction.currentappid.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [EditPanelAction](./kibana-plugin-plugins-embeddable-public.editpanelaction.md) > [currentAppId](./kibana-plugin-plugins-embeddable-public.editpanelaction.currentappid.md) + +## EditPanelAction.currentAppId property + +Signature: + +```typescript +currentAppId: string | undefined; +``` diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.editpanelaction.execute.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.editpanelaction.execute.md new file mode 100644 index 0000000000000..6cfd88f17ba85 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.editpanelaction.execute.md @@ -0,0 +1,22 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [EditPanelAction](./kibana-plugin-plugins-embeddable-public.editpanelaction.md) > [execute](./kibana-plugin-plugins-embeddable-public.editpanelaction.execute.md) + +## EditPanelAction.execute() method + +Signature: + +```typescript +execute(context: ActionContext): Promise; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| context | ActionContext | | + +Returns: + +`Promise` + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.editpanelaction.getapptarget.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.editpanelaction.getapptarget.md new file mode 100644 index 0000000000000..c9ede0f48b285 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.editpanelaction.getapptarget.md @@ -0,0 +1,22 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [EditPanelAction](./kibana-plugin-plugins-embeddable-public.editpanelaction.md) > [getAppTarget](./kibana-plugin-plugins-embeddable-public.editpanelaction.getapptarget.md) + +## EditPanelAction.getAppTarget() method + +Signature: + +```typescript +getAppTarget({ embeddable }: ActionContext): NavigationContext | undefined; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| { embeddable } | ActionContext | | + +Returns: + +`NavigationContext | undefined` + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.editpanelaction.getdisplayname.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.editpanelaction.getdisplayname.md new file mode 100644 index 0000000000000..227fdb8877149 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.editpanelaction.getdisplayname.md @@ -0,0 +1,22 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [EditPanelAction](./kibana-plugin-plugins-embeddable-public.editpanelaction.md) > [getDisplayName](./kibana-plugin-plugins-embeddable-public.editpanelaction.getdisplayname.md) + +## EditPanelAction.getDisplayName() method + +Signature: + +```typescript +getDisplayName({ embeddable }: ActionContext): string; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| { embeddable } | ActionContext | | + +Returns: + +`string` + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.editpanelaction.gethref.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.editpanelaction.gethref.md new file mode 100644 index 0000000000000..1139278ab781f --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.editpanelaction.gethref.md @@ -0,0 +1,22 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [EditPanelAction](./kibana-plugin-plugins-embeddable-public.editpanelaction.md) > [getHref](./kibana-plugin-plugins-embeddable-public.editpanelaction.gethref.md) + +## EditPanelAction.getHref() method + +Signature: + +```typescript +getHref({ embeddable }: ActionContext): Promise; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| { embeddable } | ActionContext | | + +Returns: + +`Promise` + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.editpanelaction.geticontype.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.editpanelaction.geticontype.md new file mode 100644 index 0000000000000..bc5a1f054ca75 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.editpanelaction.geticontype.md @@ -0,0 +1,15 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [EditPanelAction](./kibana-plugin-plugins-embeddable-public.editpanelaction.md) > [getIconType](./kibana-plugin-plugins-embeddable-public.editpanelaction.geticontype.md) + +## EditPanelAction.getIconType() method + +Signature: + +```typescript +getIconType(): string; +``` +Returns: + +`string` + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.editpanelaction.id.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.editpanelaction.id.md new file mode 100644 index 0000000000000..d8b0888b51801 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.editpanelaction.id.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [EditPanelAction](./kibana-plugin-plugins-embeddable-public.editpanelaction.md) > [id](./kibana-plugin-plugins-embeddable-public.editpanelaction.id.md) + +## EditPanelAction.id property + +Signature: + +```typescript +readonly id = "editPanel"; +``` diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.editpanelaction.iscompatible.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.editpanelaction.iscompatible.md new file mode 100644 index 0000000000000..7f2714f14f0e9 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.editpanelaction.iscompatible.md @@ -0,0 +1,22 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [EditPanelAction](./kibana-plugin-plugins-embeddable-public.editpanelaction.md) > [isCompatible](./kibana-plugin-plugins-embeddable-public.editpanelaction.iscompatible.md) + +## EditPanelAction.isCompatible() method + +Signature: + +```typescript +isCompatible({ embeddable }: ActionContext): Promise; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| { embeddable } | ActionContext | | + +Returns: + +`Promise` + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.editpanelaction.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.editpanelaction.md new file mode 100644 index 0000000000000..a39eae812ebfc --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.editpanelaction.md @@ -0,0 +1,38 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [EditPanelAction](./kibana-plugin-plugins-embeddable-public.editpanelaction.md) + +## EditPanelAction class + +Signature: + +```typescript +export declare class EditPanelAction implements Action +``` + +## Constructors + +| Constructor | Modifiers | Description | +| --- | --- | --- | +| [(constructor)(getEmbeddableFactory, application, stateTransfer)](./kibana-plugin-plugins-embeddable-public.editpanelaction._constructor_.md) | | Constructs a new instance of the EditPanelAction class | + +## Properties + +| Property | Modifiers | Type | Description | +| --- | --- | --- | --- | +| [currentAppId](./kibana-plugin-plugins-embeddable-public.editpanelaction.currentappid.md) | | string | undefined | | +| [id](./kibana-plugin-plugins-embeddable-public.editpanelaction.id.md) | | | | +| [order](./kibana-plugin-plugins-embeddable-public.editpanelaction.order.md) | | number | | +| [type](./kibana-plugin-plugins-embeddable-public.editpanelaction.type.md) | | | | + +## Methods + +| Method | Modifiers | Description | +| --- | --- | --- | +| [execute(context)](./kibana-plugin-plugins-embeddable-public.editpanelaction.execute.md) | | | +| [getAppTarget({ embeddable })](./kibana-plugin-plugins-embeddable-public.editpanelaction.getapptarget.md) | | | +| [getDisplayName({ embeddable })](./kibana-plugin-plugins-embeddable-public.editpanelaction.getdisplayname.md) | | | +| [getHref({ embeddable })](./kibana-plugin-plugins-embeddable-public.editpanelaction.gethref.md) | | | +| [getIconType()](./kibana-plugin-plugins-embeddable-public.editpanelaction.geticontype.md) | | | +| [isCompatible({ embeddable })](./kibana-plugin-plugins-embeddable-public.editpanelaction.iscompatible.md) | | | + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.editpanelaction.order.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.editpanelaction.order.md new file mode 100644 index 0000000000000..0ec5cde54b279 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.editpanelaction.order.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [EditPanelAction](./kibana-plugin-plugins-embeddable-public.editpanelaction.md) > [order](./kibana-plugin-plugins-embeddable-public.editpanelaction.order.md) + +## EditPanelAction.order property + +Signature: + +```typescript +order: number; +``` diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.editpanelaction.type.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.editpanelaction.type.md new file mode 100644 index 0000000000000..329f08abaaa3c --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.editpanelaction.type.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [EditPanelAction](./kibana-plugin-plugins-embeddable-public.editpanelaction.md) > [type](./kibana-plugin-plugins-embeddable-public.editpanelaction.type.md) + +## EditPanelAction.type property + +Signature: + +```typescript +readonly type = "editPanel"; +``` diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddable._constructor_.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddable._constructor_.md new file mode 100644 index 0000000000000..c5e8788bf5d4d --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddable._constructor_.md @@ -0,0 +1,22 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [Embeddable](./kibana-plugin-plugins-embeddable-public.embeddable.md) > [(constructor)](./kibana-plugin-plugins-embeddable-public.embeddable._constructor_.md) + +## Embeddable.(constructor) + +Constructs a new instance of the `Embeddable` class + +Signature: + +```typescript +constructor(input: TEmbeddableInput, output: TEmbeddableOutput, parent?: IContainer); +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| input | TEmbeddableInput | | +| output | TEmbeddableOutput | | +| parent | IContainer | | + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddable.destroy.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddable.destroy.md new file mode 100644 index 0000000000000..1ff16eec0b750 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddable.destroy.md @@ -0,0 +1,17 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [Embeddable](./kibana-plugin-plugins-embeddable-public.embeddable.md) > [destroy](./kibana-plugin-plugins-embeddable-public.embeddable.destroy.md) + +## Embeddable.destroy() method + +Called when this embeddable is no longer used, this should be the place for implementors to add any additional clean up tasks, like unmounting and unsubscribing. + +Signature: + +```typescript +destroy(): void; +``` +Returns: + +`void` + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddable.getinput.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddable.getinput.md new file mode 100644 index 0000000000000..f4a0724d42680 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddable.getinput.md @@ -0,0 +1,15 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [Embeddable](./kibana-plugin-plugins-embeddable-public.embeddable.md) > [getInput](./kibana-plugin-plugins-embeddable-public.embeddable.getinput.md) + +## Embeddable.getInput() method + +Signature: + +```typescript +getInput(): Readonly; +``` +Returns: + +`Readonly` + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddable.getinput_.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddable.getinput_.md new file mode 100644 index 0000000000000..e4910d3eb1bf2 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddable.getinput_.md @@ -0,0 +1,15 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [Embeddable](./kibana-plugin-plugins-embeddable-public.embeddable.md) > [getInput$](./kibana-plugin-plugins-embeddable-public.embeddable.getinput_.md) + +## Embeddable.getInput$() method + +Signature: + +```typescript +getInput$(): Readonly>; +``` +Returns: + +`Readonly>` + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddable.getinspectoradapters.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddable.getinspectoradapters.md new file mode 100644 index 0000000000000..490eaca32e685 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddable.getinspectoradapters.md @@ -0,0 +1,17 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [Embeddable](./kibana-plugin-plugins-embeddable-public.embeddable.md) > [getInspectorAdapters](./kibana-plugin-plugins-embeddable-public.embeddable.getinspectoradapters.md) + +## Embeddable.getInspectorAdapters() method + +An embeddable can return inspector adapters if it want the inspector to be available via the context menu of that panel. Inspector adapters that will be used to open an inspector for. + +Signature: + +```typescript +getInspectorAdapters(): Adapters | undefined; +``` +Returns: + +`Adapters | undefined` + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddable.getiscontainer.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddable.getiscontainer.md new file mode 100644 index 0000000000000..cb9945ea31293 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddable.getiscontainer.md @@ -0,0 +1,15 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [Embeddable](./kibana-plugin-plugins-embeddable-public.embeddable.md) > [getIsContainer](./kibana-plugin-plugins-embeddable-public.embeddable.getiscontainer.md) + +## Embeddable.getIsContainer() method + +Signature: + +```typescript +getIsContainer(): this is IContainer; +``` +Returns: + +`this is IContainer` + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddable.getoutput.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddable.getoutput.md new file mode 100644 index 0000000000000..b24c5aefddb40 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddable.getoutput.md @@ -0,0 +1,15 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [Embeddable](./kibana-plugin-plugins-embeddable-public.embeddable.md) > [getOutput](./kibana-plugin-plugins-embeddable-public.embeddable.getoutput.md) + +## Embeddable.getOutput() method + +Signature: + +```typescript +getOutput(): Readonly; +``` +Returns: + +`Readonly` + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddable.getoutput_.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddable.getoutput_.md new file mode 100644 index 0000000000000..34b5f864dd0c8 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddable.getoutput_.md @@ -0,0 +1,15 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [Embeddable](./kibana-plugin-plugins-embeddable-public.embeddable.md) > [getOutput$](./kibana-plugin-plugins-embeddable-public.embeddable.getoutput_.md) + +## Embeddable.getOutput$() method + +Signature: + +```typescript +getOutput$(): Readonly>; +``` +Returns: + +`Readonly>` + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddable.getroot.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddable.getroot.md new file mode 100644 index 0000000000000..79397911d5bc7 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddable.getroot.md @@ -0,0 +1,17 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [Embeddable](./kibana-plugin-plugins-embeddable-public.embeddable.md) > [getRoot](./kibana-plugin-plugins-embeddable-public.embeddable.getroot.md) + +## Embeddable.getRoot() method + +Returns the top most parent embeddable, or itself if this embeddable is not within a parent. + +Signature: + +```typescript +getRoot(): IEmbeddable | IContainer; +``` +Returns: + +`IEmbeddable | IContainer` + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddable.gettitle.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddable.gettitle.md new file mode 100644 index 0000000000000..4dc1900b4b011 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddable.gettitle.md @@ -0,0 +1,15 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [Embeddable](./kibana-plugin-plugins-embeddable-public.embeddable.md) > [getTitle](./kibana-plugin-plugins-embeddable-public.embeddable.gettitle.md) + +## Embeddable.getTitle() method + +Signature: + +```typescript +getTitle(): string; +``` +Returns: + +`string` + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddable.id.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddable.id.md new file mode 100644 index 0000000000000..348934b9fb65c --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddable.id.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [Embeddable](./kibana-plugin-plugins-embeddable-public.embeddable.md) > [id](./kibana-plugin-plugins-embeddable-public.embeddable.id.md) + +## Embeddable.id property + +Signature: + +```typescript +readonly id: string; +``` diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddable.input.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddable.input.md new file mode 100644 index 0000000000000..4541aeacd5bc8 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddable.input.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [Embeddable](./kibana-plugin-plugins-embeddable-public.embeddable.md) > [input](./kibana-plugin-plugins-embeddable-public.embeddable.input.md) + +## Embeddable.input property + +Signature: + +```typescript +protected input: TEmbeddableInput; +``` diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddable.iscontainer.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddable.iscontainer.md new file mode 100644 index 0000000000000..db15653d40c4c --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddable.iscontainer.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [Embeddable](./kibana-plugin-plugins-embeddable-public.embeddable.md) > [isContainer](./kibana-plugin-plugins-embeddable-public.embeddable.iscontainer.md) + +## Embeddable.isContainer property + +Signature: + +```typescript +readonly isContainer: boolean; +``` diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddable.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddable.md new file mode 100644 index 0000000000000..295cc10b1bb19 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddable.md @@ -0,0 +1,51 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [Embeddable](./kibana-plugin-plugins-embeddable-public.embeddable.md) + +## Embeddable class + +Signature: + +```typescript +export declare abstract class Embeddable implements IEmbeddable +``` + +## Constructors + +| Constructor | Modifiers | Description | +| --- | --- | --- | +| [(constructor)(input, output, parent)](./kibana-plugin-plugins-embeddable-public.embeddable._constructor_.md) | | Constructs a new instance of the Embeddable class | + +## Properties + +| Property | Modifiers | Type | Description | +| --- | --- | --- | --- | +| [id](./kibana-plugin-plugins-embeddable-public.embeddable.id.md) | | string | | +| [input](./kibana-plugin-plugins-embeddable-public.embeddable.input.md) | | TEmbeddableInput | | +| [isContainer](./kibana-plugin-plugins-embeddable-public.embeddable.iscontainer.md) | | boolean | | +| [output](./kibana-plugin-plugins-embeddable-public.embeddable.output.md) | | TEmbeddableOutput | | +| [parent](./kibana-plugin-plugins-embeddable-public.embeddable.parent.md) | | IContainer | | +| [renderComplete](./kibana-plugin-plugins-embeddable-public.embeddable.rendercomplete.md) | | RenderCompleteDispatcher | | +| [runtimeId](./kibana-plugin-plugins-embeddable-public.embeddable.runtimeid.md) | | number | | +| [runtimeId](./kibana-plugin-plugins-embeddable-public.embeddable.runtimeid.md) | static | number | | +| [type](./kibana-plugin-plugins-embeddable-public.embeddable.type.md) | | string | | + +## Methods + +| Method | Modifiers | Description | +| --- | --- | --- | +| [destroy()](./kibana-plugin-plugins-embeddable-public.embeddable.destroy.md) | | Called when this embeddable is no longer used, this should be the place for implementors to add any additional clean up tasks, like unmounting and unsubscribing. | +| [getInput()](./kibana-plugin-plugins-embeddable-public.embeddable.getinput.md) | | | +| [getInput$()](./kibana-plugin-plugins-embeddable-public.embeddable.getinput_.md) | | | +| [getInspectorAdapters()](./kibana-plugin-plugins-embeddable-public.embeddable.getinspectoradapters.md) | | An embeddable can return inspector adapters if it want the inspector to be available via the context menu of that panel. Inspector adapters that will be used to open an inspector for. | +| [getIsContainer()](./kibana-plugin-plugins-embeddable-public.embeddable.getiscontainer.md) | | | +| [getOutput()](./kibana-plugin-plugins-embeddable-public.embeddable.getoutput.md) | | | +| [getOutput$()](./kibana-plugin-plugins-embeddable-public.embeddable.getoutput_.md) | | | +| [getRoot()](./kibana-plugin-plugins-embeddable-public.embeddable.getroot.md) | | Returns the top most parent embeddable, or itself if this embeddable is not within a parent. | +| [getTitle()](./kibana-plugin-plugins-embeddable-public.embeddable.gettitle.md) | | | +| [reload()](./kibana-plugin-plugins-embeddable-public.embeddable.reload.md) | | Reload will be called when there is a request to refresh the data or view, even if the input data did not change. | +| [render(el)](./kibana-plugin-plugins-embeddable-public.embeddable.render.md) | | | +| [supportedTriggers()](./kibana-plugin-plugins-embeddable-public.embeddable.supportedtriggers.md) | | | +| [updateInput(changes)](./kibana-plugin-plugins-embeddable-public.embeddable.updateinput.md) | | | +| [updateOutput(outputChanges)](./kibana-plugin-plugins-embeddable-public.embeddable.updateoutput.md) | | | + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddable.output.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddable.output.md new file mode 100644 index 0000000000000..db854e2a69cec --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddable.output.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [Embeddable](./kibana-plugin-plugins-embeddable-public.embeddable.md) > [output](./kibana-plugin-plugins-embeddable-public.embeddable.output.md) + +## Embeddable.output property + +Signature: + +```typescript +protected output: TEmbeddableOutput; +``` diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddable.parent.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddable.parent.md new file mode 100644 index 0000000000000..bfd82f53e96f1 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddable.parent.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [Embeddable](./kibana-plugin-plugins-embeddable-public.embeddable.md) > [parent](./kibana-plugin-plugins-embeddable-public.embeddable.parent.md) + +## Embeddable.parent property + +Signature: + +```typescript +readonly parent?: IContainer; +``` diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddable.reload.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddable.reload.md new file mode 100644 index 0000000000000..e3b06f414cb5b --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddable.reload.md @@ -0,0 +1,17 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [Embeddable](./kibana-plugin-plugins-embeddable-public.embeddable.md) > [reload](./kibana-plugin-plugins-embeddable-public.embeddable.reload.md) + +## Embeddable.reload() method + +Reload will be called when there is a request to refresh the data or view, even if the input data did not change. + +Signature: + +```typescript +abstract reload(): void; +``` +Returns: + +`void` + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddable.render.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddable.render.md new file mode 100644 index 0000000000000..171a3c6a30a85 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddable.render.md @@ -0,0 +1,22 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [Embeddable](./kibana-plugin-plugins-embeddable-public.embeddable.md) > [render](./kibana-plugin-plugins-embeddable-public.embeddable.render.md) + +## Embeddable.render() method + +Signature: + +```typescript +render(el: HTMLElement): void; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| el | HTMLElement | | + +Returns: + +`void` + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddable.rendercomplete.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddable.rendercomplete.md new file mode 100644 index 0000000000000..c86bb2e998044 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddable.rendercomplete.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [Embeddable](./kibana-plugin-plugins-embeddable-public.embeddable.md) > [renderComplete](./kibana-plugin-plugins-embeddable-public.embeddable.rendercomplete.md) + +## Embeddable.renderComplete property + +Signature: + +```typescript +protected renderComplete: RenderCompleteDispatcher; +``` diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddable.runtimeid.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddable.runtimeid.md new file mode 100644 index 0000000000000..a5cdd12b6f198 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddable.runtimeid.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [Embeddable](./kibana-plugin-plugins-embeddable-public.embeddable.md) > [runtimeId](./kibana-plugin-plugins-embeddable-public.embeddable.runtimeid.md) + +## Embeddable.runtimeId property + +Signature: + +```typescript +static runtimeId: number; +``` diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddable.supportedtriggers.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddable.supportedtriggers.md new file mode 100644 index 0000000000000..16676bc732b1c --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddable.supportedtriggers.md @@ -0,0 +1,15 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [Embeddable](./kibana-plugin-plugins-embeddable-public.embeddable.md) > [supportedTriggers](./kibana-plugin-plugins-embeddable-public.embeddable.supportedtriggers.md) + +## Embeddable.supportedTriggers() method + +Signature: + +```typescript +supportedTriggers(): Array; +``` +Returns: + +`Array` + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddable.type.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddable.type.md new file mode 100644 index 0000000000000..bb3ae7384686c --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddable.type.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [Embeddable](./kibana-plugin-plugins-embeddable-public.embeddable.md) > [type](./kibana-plugin-plugins-embeddable-public.embeddable.type.md) + +## Embeddable.type property + +Signature: + +```typescript +abstract readonly type: string; +``` diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddable.updateinput.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddable.updateinput.md new file mode 100644 index 0000000000000..36c46bb71c6b6 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddable.updateinput.md @@ -0,0 +1,22 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [Embeddable](./kibana-plugin-plugins-embeddable-public.embeddable.md) > [updateInput](./kibana-plugin-plugins-embeddable-public.embeddable.updateinput.md) + +## Embeddable.updateInput() method + +Signature: + +```typescript +updateInput(changes: Partial): void; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| changes | Partial<TEmbeddableInput> | | + +Returns: + +`void` + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddable.updateoutput.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddable.updateoutput.md new file mode 100644 index 0000000000000..0b0244e7a5853 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddable.updateoutput.md @@ -0,0 +1,22 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [Embeddable](./kibana-plugin-plugins-embeddable-public.embeddable.md) > [updateOutput](./kibana-plugin-plugins-embeddable-public.embeddable.updateoutput.md) + +## Embeddable.updateOutput() method + +Signature: + +```typescript +protected updateOutput(outputChanges: Partial): void; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| outputChanges | Partial<TEmbeddableOutput> | | + +Returns: + +`void` + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablechildpanel._constructor_.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablechildpanel._constructor_.md new file mode 100644 index 0000000000000..76412de0d5419 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablechildpanel._constructor_.md @@ -0,0 +1,20 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [EmbeddableChildPanel](./kibana-plugin-plugins-embeddable-public.embeddablechildpanel.md) > [(constructor)](./kibana-plugin-plugins-embeddable-public.embeddablechildpanel._constructor_.md) + +## EmbeddableChildPanel.(constructor) + +Constructs a new instance of the `EmbeddableChildPanel` class + +Signature: + +```typescript +constructor(props: EmbeddableChildPanelProps); +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| props | EmbeddableChildPanelProps | | + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablechildpanel.componentdidmount.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablechildpanel.componentdidmount.md new file mode 100644 index 0000000000000..5302d3e986d94 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablechildpanel.componentdidmount.md @@ -0,0 +1,15 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [EmbeddableChildPanel](./kibana-plugin-plugins-embeddable-public.embeddablechildpanel.md) > [componentDidMount](./kibana-plugin-plugins-embeddable-public.embeddablechildpanel.componentdidmount.md) + +## EmbeddableChildPanel.componentDidMount() method + +Signature: + +```typescript +componentDidMount(): Promise; +``` +Returns: + +`Promise` + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablechildpanel.componentwillunmount.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablechildpanel.componentwillunmount.md new file mode 100644 index 0000000000000..17c23a5ba2fd1 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablechildpanel.componentwillunmount.md @@ -0,0 +1,15 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [EmbeddableChildPanel](./kibana-plugin-plugins-embeddable-public.embeddablechildpanel.md) > [componentWillUnmount](./kibana-plugin-plugins-embeddable-public.embeddablechildpanel.componentwillunmount.md) + +## EmbeddableChildPanel.componentWillUnmount() method + +Signature: + +```typescript +componentWillUnmount(): void; +``` +Returns: + +`void` + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablechildpanel.embeddable.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablechildpanel.embeddable.md new file mode 100644 index 0000000000000..298697167e127 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablechildpanel.embeddable.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [EmbeddableChildPanel](./kibana-plugin-plugins-embeddable-public.embeddablechildpanel.md) > [embeddable](./kibana-plugin-plugins-embeddable-public.embeddablechildpanel.embeddable.md) + +## EmbeddableChildPanel.embeddable property + +Signature: + +```typescript +embeddable: IEmbeddable | ErrorEmbeddable; +``` diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablechildpanel.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablechildpanel.md new file mode 100644 index 0000000000000..d52033b4fd6ad --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablechildpanel.md @@ -0,0 +1,35 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [EmbeddableChildPanel](./kibana-plugin-plugins-embeddable-public.embeddablechildpanel.md) + +## EmbeddableChildPanel class + +This component can be used by embeddable containers using react to easily render children. It waits for the child to be initialized, showing a loading indicator until that is complete. + +Signature: + +```typescript +export declare class EmbeddableChildPanel extends React.Component +``` + +## Constructors + +| Constructor | Modifiers | Description | +| --- | --- | --- | +| [(constructor)(props)](./kibana-plugin-plugins-embeddable-public.embeddablechildpanel._constructor_.md) | | Constructs a new instance of the EmbeddableChildPanel class | + +## Properties + +| Property | Modifiers | Type | Description | +| --- | --- | --- | --- | +| [embeddable](./kibana-plugin-plugins-embeddable-public.embeddablechildpanel.embeddable.md) | | IEmbeddable | ErrorEmbeddable | | +| [mounted](./kibana-plugin-plugins-embeddable-public.embeddablechildpanel.mounted.md) | | boolean | | + +## Methods + +| Method | Modifiers | Description | +| --- | --- | --- | +| [componentDidMount()](./kibana-plugin-plugins-embeddable-public.embeddablechildpanel.componentdidmount.md) | | | +| [componentWillUnmount()](./kibana-plugin-plugins-embeddable-public.embeddablechildpanel.componentwillunmount.md) | | | +| [render()](./kibana-plugin-plugins-embeddable-public.embeddablechildpanel.render.md) | | | + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablechildpanel.mounted.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablechildpanel.mounted.md new file mode 100644 index 0000000000000..169f27ea5afa6 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablechildpanel.mounted.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [EmbeddableChildPanel](./kibana-plugin-plugins-embeddable-public.embeddablechildpanel.md) > [mounted](./kibana-plugin-plugins-embeddable-public.embeddablechildpanel.mounted.md) + +## EmbeddableChildPanel.mounted property + +Signature: + +```typescript +mounted: boolean; +``` diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablechildpanel.render.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablechildpanel.render.md new file mode 100644 index 0000000000000..01d70eb5f628f --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablechildpanel.render.md @@ -0,0 +1,15 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [EmbeddableChildPanel](./kibana-plugin-plugins-embeddable-public.embeddablechildpanel.md) > [render](./kibana-plugin-plugins-embeddable-public.embeddablechildpanel.render.md) + +## EmbeddableChildPanel.render() method + +Signature: + +```typescript +render(): JSX.Element; +``` +Returns: + +`JSX.Element` + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablechildpanelprops.classname.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablechildpanelprops.classname.md new file mode 100644 index 0000000000000..d18dea31545d9 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablechildpanelprops.classname.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [EmbeddableChildPanelProps](./kibana-plugin-plugins-embeddable-public.embeddablechildpanelprops.md) > [className](./kibana-plugin-plugins-embeddable-public.embeddablechildpanelprops.classname.md) + +## EmbeddableChildPanelProps.className property + +Signature: + +```typescript +className?: string; +``` diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablechildpanelprops.container.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablechildpanelprops.container.md new file mode 100644 index 0000000000000..91120f955b15e --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablechildpanelprops.container.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [EmbeddableChildPanelProps](./kibana-plugin-plugins-embeddable-public.embeddablechildpanelprops.md) > [container](./kibana-plugin-plugins-embeddable-public.embeddablechildpanelprops.container.md) + +## EmbeddableChildPanelProps.container property + +Signature: + +```typescript +container: IContainer; +``` diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablechildpanelprops.embeddableid.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablechildpanelprops.embeddableid.md new file mode 100644 index 0000000000000..6765010e1b696 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablechildpanelprops.embeddableid.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [EmbeddableChildPanelProps](./kibana-plugin-plugins-embeddable-public.embeddablechildpanelprops.md) > [embeddableId](./kibana-plugin-plugins-embeddable-public.embeddablechildpanelprops.embeddableid.md) + +## EmbeddableChildPanelProps.embeddableId property + +Signature: + +```typescript +embeddableId: string; +``` diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablechildpanelprops.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablechildpanelprops.md new file mode 100644 index 0000000000000..7ed3bd1e20768 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablechildpanelprops.md @@ -0,0 +1,21 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [EmbeddableChildPanelProps](./kibana-plugin-plugins-embeddable-public.embeddablechildpanelprops.md) + +## EmbeddableChildPanelProps interface + +Signature: + +```typescript +export interface EmbeddableChildPanelProps +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [className](./kibana-plugin-plugins-embeddable-public.embeddablechildpanelprops.classname.md) | string | | +| [container](./kibana-plugin-plugins-embeddable-public.embeddablechildpanelprops.container.md) | IContainer | | +| [embeddableId](./kibana-plugin-plugins-embeddable-public.embeddablechildpanelprops.embeddableid.md) | string | | +| [PanelComponent](./kibana-plugin-plugins-embeddable-public.embeddablechildpanelprops.panelcomponent.md) | EmbeddableStart['EmbeddablePanel'] | | + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablechildpanelprops.panelcomponent.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablechildpanelprops.panelcomponent.md new file mode 100644 index 0000000000000..e1bb6b41d3887 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablechildpanelprops.panelcomponent.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [EmbeddableChildPanelProps](./kibana-plugin-plugins-embeddable-public.embeddablechildpanelprops.md) > [PanelComponent](./kibana-plugin-plugins-embeddable-public.embeddablechildpanelprops.panelcomponent.md) + +## EmbeddableChildPanelProps.PanelComponent property + +Signature: + +```typescript +PanelComponent: EmbeddableStart['EmbeddablePanel']; +``` diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablecontext.embeddable.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablecontext.embeddable.md new file mode 100644 index 0000000000000..06e51958a2d1e --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablecontext.embeddable.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [EmbeddableContext](./kibana-plugin-plugins-embeddable-public.embeddablecontext.md) > [embeddable](./kibana-plugin-plugins-embeddable-public.embeddablecontext.embeddable.md) + +## EmbeddableContext.embeddable property + +Signature: + +```typescript +embeddable: IEmbeddable; +``` diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablecontext.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablecontext.md new file mode 100644 index 0000000000000..a2c2d9245eabe --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablecontext.md @@ -0,0 +1,18 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [EmbeddableContext](./kibana-plugin-plugins-embeddable-public.embeddablecontext.md) + +## EmbeddableContext interface + +Signature: + +```typescript +export interface EmbeddableContext +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [embeddable](./kibana-plugin-plugins-embeddable-public.embeddablecontext.embeddable.md) | IEmbeddable | | + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddableeditorstate.embeddableid.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddableeditorstate.embeddableid.md new file mode 100644 index 0000000000000..d998e982cc9d5 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddableeditorstate.embeddableid.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [EmbeddableEditorState](./kibana-plugin-plugins-embeddable-public.embeddableeditorstate.md) > [embeddableId](./kibana-plugin-plugins-embeddable-public.embeddableeditorstate.embeddableid.md) + +## EmbeddableEditorState.embeddableId property + +Signature: + +```typescript +embeddableId?: string; +``` diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddableeditorstate.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddableeditorstate.md new file mode 100644 index 0000000000000..63302f50204fe --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddableeditorstate.md @@ -0,0 +1,22 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [EmbeddableEditorState](./kibana-plugin-plugins-embeddable-public.embeddableeditorstate.md) + +## EmbeddableEditorState interface + +A state package that contains information an editor will need to create or edit an embeddable then redirect back. + +Signature: + +```typescript +export interface EmbeddableEditorState +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [embeddableId](./kibana-plugin-plugins-embeddable-public.embeddableeditorstate.embeddableid.md) | string | | +| [originatingApp](./kibana-plugin-plugins-embeddable-public.embeddableeditorstate.originatingapp.md) | string | | +| [valueInput](./kibana-plugin-plugins-embeddable-public.embeddableeditorstate.valueinput.md) | EmbeddableInput | | + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddableeditorstate.originatingapp.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddableeditorstate.originatingapp.md new file mode 100644 index 0000000000000..640b0894ef2c7 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddableeditorstate.originatingapp.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [EmbeddableEditorState](./kibana-plugin-plugins-embeddable-public.embeddableeditorstate.md) > [originatingApp](./kibana-plugin-plugins-embeddable-public.embeddableeditorstate.originatingapp.md) + +## EmbeddableEditorState.originatingApp property + +Signature: + +```typescript +originatingApp: string; +``` diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddableeditorstate.valueinput.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddableeditorstate.valueinput.md new file mode 100644 index 0000000000000..61ebfc61634b8 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddableeditorstate.valueinput.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [EmbeddableEditorState](./kibana-plugin-plugins-embeddable-public.embeddableeditorstate.md) > [valueInput](./kibana-plugin-plugins-embeddable-public.embeddableeditorstate.valueinput.md) + +## EmbeddableEditorState.valueInput property + +Signature: + +```typescript +valueInput?: EmbeddableInput; +``` diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablefactory.cancreatenew.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablefactory.cancreatenew.md new file mode 100644 index 0000000000000..78bcb4f31a5be --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablefactory.cancreatenew.md @@ -0,0 +1,17 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [EmbeddableFactory](./kibana-plugin-plugins-embeddable-public.embeddablefactory.md) > [canCreateNew](./kibana-plugin-plugins-embeddable-public.embeddablefactory.cancreatenew.md) + +## EmbeddableFactory.canCreateNew() method + +If false, this type of embeddable can't be created with the "createNew" functionality. Instead, use createFromSavedObject, where an existing saved object must first exist. + +Signature: + +```typescript +canCreateNew(): boolean; +``` +Returns: + +`boolean` + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablefactory.create.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablefactory.create.md new file mode 100644 index 0000000000000..130c8cb760625 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablefactory.create.md @@ -0,0 +1,27 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [EmbeddableFactory](./kibana-plugin-plugins-embeddable-public.embeddablefactory.md) > [create](./kibana-plugin-plugins-embeddable-public.embeddablefactory.create.md) + +## EmbeddableFactory.create() method + +Resolves to undefined if a new Embeddable cannot be directly created and the user will instead be redirected elsewhere. + +This will likely change in future iterations when we improve in place editing capabilities. + +Signature: + +```typescript +create(initialInput: TEmbeddableInput, parent?: IContainer): Promise; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| initialInput | TEmbeddableInput | | +| parent | IContainer | | + +Returns: + +`Promise` + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablefactory.createfromsavedobject.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablefactory.createfromsavedobject.md new file mode 100644 index 0000000000000..7a411988ca3b0 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablefactory.createfromsavedobject.md @@ -0,0 +1,26 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [EmbeddableFactory](./kibana-plugin-plugins-embeddable-public.embeddablefactory.md) > [createFromSavedObject](./kibana-plugin-plugins-embeddable-public.embeddablefactory.createfromsavedobject.md) + +## EmbeddableFactory.createFromSavedObject() method + +Creates a new embeddable instance based off the saved object id. + +Signature: + +```typescript +createFromSavedObject(savedObjectId: string, input: Partial, parent?: IContainer): Promise; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| savedObjectId | string | | +| input | Partial<TEmbeddableInput> | some input may come from a parent, or user, if it's not stored with the saved object. For example, the time range of the parent container. | +| parent | IContainer | | + +Returns: + +`Promise` + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablefactory.getdefaultinput.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablefactory.getdefaultinput.md new file mode 100644 index 0000000000000..bf1ca6abd9ba0 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablefactory.getdefaultinput.md @@ -0,0 +1,24 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [EmbeddableFactory](./kibana-plugin-plugins-embeddable-public.embeddablefactory.md) > [getDefaultInput](./kibana-plugin-plugins-embeddable-public.embeddablefactory.getdefaultinput.md) + +## EmbeddableFactory.getDefaultInput() method + +Can be used to get any default input, to be passed in to during the creation process. Default input will not be stored in a parent container, so any inherited input from a container will trump default input parameters. + +Signature: + +```typescript +getDefaultInput(partial: Partial): Partial; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| partial | Partial<TEmbeddableInput> | | + +Returns: + +`Partial` + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablefactory.getdisplayname.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablefactory.getdisplayname.md new file mode 100644 index 0000000000000..5b97645d4947d --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablefactory.getdisplayname.md @@ -0,0 +1,17 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [EmbeddableFactory](./kibana-plugin-plugins-embeddable-public.embeddablefactory.md) > [getDisplayName](./kibana-plugin-plugins-embeddable-public.embeddablefactory.getdisplayname.md) + +## EmbeddableFactory.getDisplayName() method + +Returns a display name for this type of embeddable. Used in "Create new... " options in the add panel for containers. + +Signature: + +```typescript +getDisplayName(): string; +``` +Returns: + +`string` + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablefactory.getexplicitinput.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablefactory.getexplicitinput.md new file mode 100644 index 0000000000000..3ec05f50005d0 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablefactory.getexplicitinput.md @@ -0,0 +1,17 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [EmbeddableFactory](./kibana-plugin-plugins-embeddable-public.embeddablefactory.md) > [getExplicitInput](./kibana-plugin-plugins-embeddable-public.embeddablefactory.getexplicitinput.md) + +## EmbeddableFactory.getExplicitInput() method + +Can be used to request explicit input from the user, to be passed in to `EmbeddableFactory:create`. Explicit input is stored on the parent container for this embeddable. It overrides any inherited input passed down from the parent container. + +Signature: + +```typescript +getExplicitInput(): Promise>; +``` +Returns: + +`Promise>` + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablefactory.iscontainertype.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablefactory.iscontainertype.md new file mode 100644 index 0000000000000..f3ba375ab575c --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablefactory.iscontainertype.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [EmbeddableFactory](./kibana-plugin-plugins-embeddable-public.embeddablefactory.md) > [isContainerType](./kibana-plugin-plugins-embeddable-public.embeddablefactory.iscontainertype.md) + +## EmbeddableFactory.isContainerType property + +True if is this factory create embeddables that are Containers. Used in the add panel to conditionally show whether these can be added to another container. It's just not supported right now, but once nested containers are officially supported we can probably get rid of this interface. + +Signature: + +```typescript +readonly isContainerType: boolean; +``` diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablefactory.iseditable.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablefactory.iseditable.md new file mode 100644 index 0000000000000..f1ad10dfaa1f6 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablefactory.iseditable.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [EmbeddableFactory](./kibana-plugin-plugins-embeddable-public.embeddablefactory.md) > [isEditable](./kibana-plugin-plugins-embeddable-public.embeddablefactory.iseditable.md) + +## EmbeddableFactory.isEditable property + +Returns whether the current user should be allowed to edit this type of embeddable. Most of the time this should be based off the capabilities service, hence it's async. + +Signature: + +```typescript +readonly isEditable: () => Promise; +``` diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablefactory.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablefactory.md new file mode 100644 index 0000000000000..d543cf3d096df --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablefactory.md @@ -0,0 +1,34 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [EmbeddableFactory](./kibana-plugin-plugins-embeddable-public.embeddablefactory.md) + +## EmbeddableFactory interface + +EmbeddableFactories create and initialize an embeddable instance + +Signature: + +```typescript +export interface EmbeddableFactory = IEmbeddable, TSavedObjectAttributes extends SavedObjectAttributes = SavedObjectAttributes> extends PersistableState +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [isContainerType](./kibana-plugin-plugins-embeddable-public.embeddablefactory.iscontainertype.md) | boolean | True if is this factory create embeddables that are Containers. Used in the add panel to conditionally show whether these can be added to another container. It's just not supported right now, but once nested containers are officially supported we can probably get rid of this interface. | +| [isEditable](./kibana-plugin-plugins-embeddable-public.embeddablefactory.iseditable.md) | () => Promise<boolean> | Returns whether the current user should be allowed to edit this type of embeddable. Most of the time this should be based off the capabilities service, hence it's async. | +| [savedObjectMetaData](./kibana-plugin-plugins-embeddable-public.embeddablefactory.savedobjectmetadata.md) | SavedObjectMetaData<TSavedObjectAttributes> | | +| [type](./kibana-plugin-plugins-embeddable-public.embeddablefactory.type.md) | string | | + +## Methods + +| Method | Description | +| --- | --- | +| [canCreateNew()](./kibana-plugin-plugins-embeddable-public.embeddablefactory.cancreatenew.md) | If false, this type of embeddable can't be created with the "createNew" functionality. Instead, use createFromSavedObject, where an existing saved object must first exist. | +| [create(initialInput, parent)](./kibana-plugin-plugins-embeddable-public.embeddablefactory.create.md) | Resolves to undefined if a new Embeddable cannot be directly created and the user will instead be redirected elsewhere.This will likely change in future iterations when we improve in place editing capabilities. | +| [createFromSavedObject(savedObjectId, input, parent)](./kibana-plugin-plugins-embeddable-public.embeddablefactory.createfromsavedobject.md) | Creates a new embeddable instance based off the saved object id. | +| [getDefaultInput(partial)](./kibana-plugin-plugins-embeddable-public.embeddablefactory.getdefaultinput.md) | Can be used to get any default input, to be passed in to during the creation process. Default input will not be stored in a parent container, so any inherited input from a container will trump default input parameters. | +| [getDisplayName()](./kibana-plugin-plugins-embeddable-public.embeddablefactory.getdisplayname.md) | Returns a display name for this type of embeddable. Used in "Create new... " options in the add panel for containers. | +| [getExplicitInput()](./kibana-plugin-plugins-embeddable-public.embeddablefactory.getexplicitinput.md) | Can be used to request explicit input from the user, to be passed in to EmbeddableFactory:create. Explicit input is stored on the parent container for this embeddable. It overrides any inherited input passed down from the parent container. | + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablefactory.savedobjectmetadata.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablefactory.savedobjectmetadata.md new file mode 100644 index 0000000000000..ec5bf420aac3e --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablefactory.savedobjectmetadata.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [EmbeddableFactory](./kibana-plugin-plugins-embeddable-public.embeddablefactory.md) > [savedObjectMetaData](./kibana-plugin-plugins-embeddable-public.embeddablefactory.savedobjectmetadata.md) + +## EmbeddableFactory.savedObjectMetaData property + +Signature: + +```typescript +readonly savedObjectMetaData?: SavedObjectMetaData; +``` diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablefactory.type.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablefactory.type.md new file mode 100644 index 0000000000000..307f808de9bcd --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablefactory.type.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [EmbeddableFactory](./kibana-plugin-plugins-embeddable-public.embeddablefactory.md) > [type](./kibana-plugin-plugins-embeddable-public.embeddablefactory.type.md) + +## EmbeddableFactory.type property + +Signature: + +```typescript +readonly type: string; +``` diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablefactorydefinition.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablefactorydefinition.md new file mode 100644 index 0000000000000..4e342d3cf73a1 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablefactorydefinition.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [EmbeddableFactoryDefinition](./kibana-plugin-plugins-embeddable-public.embeddablefactorydefinition.md) + +## EmbeddableFactoryDefinition type + +Signature: + +```typescript +export declare type EmbeddableFactoryDefinition = IEmbeddable, T extends SavedObjectAttributes = SavedObjectAttributes> = Pick, 'create' | 'type' | 'isEditable' | 'getDisplayName'> & Partial, 'createFromSavedObject' | 'isContainerType' | 'getExplicitInput' | 'savedObjectMetaData' | 'canCreateNew' | 'getDefaultInput' | 'telemetry' | 'extract' | 'inject'>>; +``` diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablefactorynotfounderror._constructor_.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablefactorynotfounderror._constructor_.md new file mode 100644 index 0000000000000..273126936ce91 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablefactorynotfounderror._constructor_.md @@ -0,0 +1,20 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [EmbeddableFactoryNotFoundError](./kibana-plugin-plugins-embeddable-public.embeddablefactorynotfounderror.md) > [(constructor)](./kibana-plugin-plugins-embeddable-public.embeddablefactorynotfounderror._constructor_.md) + +## EmbeddableFactoryNotFoundError.(constructor) + +Constructs a new instance of the `EmbeddableFactoryNotFoundError` class + +Signature: + +```typescript +constructor(type: string); +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| type | string | | + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablefactorynotfounderror.code.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablefactorynotfounderror.code.md new file mode 100644 index 0000000000000..2ad75d3e68ba4 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablefactorynotfounderror.code.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [EmbeddableFactoryNotFoundError](./kibana-plugin-plugins-embeddable-public.embeddablefactorynotfounderror.md) > [code](./kibana-plugin-plugins-embeddable-public.embeddablefactorynotfounderror.code.md) + +## EmbeddableFactoryNotFoundError.code property + +Signature: + +```typescript +code: string; +``` diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablefactorynotfounderror.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablefactorynotfounderror.md new file mode 100644 index 0000000000000..028271d36fee0 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablefactorynotfounderror.md @@ -0,0 +1,24 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [EmbeddableFactoryNotFoundError](./kibana-plugin-plugins-embeddable-public.embeddablefactorynotfounderror.md) + +## EmbeddableFactoryNotFoundError class + +Signature: + +```typescript +export declare class EmbeddableFactoryNotFoundError extends Error +``` + +## Constructors + +| Constructor | Modifiers | Description | +| --- | --- | --- | +| [(constructor)(type)](./kibana-plugin-plugins-embeddable-public.embeddablefactorynotfounderror._constructor_.md) | | Constructs a new instance of the EmbeddableFactoryNotFoundError class | + +## Properties + +| Property | Modifiers | Type | Description | +| --- | --- | --- | --- | +| [code](./kibana-plugin-plugins-embeddable-public.embeddablefactorynotfounderror.code.md) | | string | | + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddableinput.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddableinput.md new file mode 100644 index 0000000000000..d1d97d50f5948 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddableinput.md @@ -0,0 +1,23 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [EmbeddableInput](./kibana-plugin-plugins-embeddable-public.embeddableinput.md) + +## EmbeddableInput type + +Signature: + +```typescript +export declare type EmbeddableInput = { + viewMode?: ViewMode; + title?: string; + id: string; + lastReloadRequestTime?: number; + hidePanelTitles?: boolean; + enhancements?: SerializableState; + disabledActions?: string[]; + disableTriggers?: boolean; + timeRange?: TimeRange; + query?: Query; + filters?: Filter[]; +}; +``` diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddableinstanceconfiguration.id.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddableinstanceconfiguration.id.md new file mode 100644 index 0000000000000..2298c6fb111a0 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddableinstanceconfiguration.id.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [EmbeddableInstanceConfiguration](./kibana-plugin-plugins-embeddable-public.embeddableinstanceconfiguration.md) > [id](./kibana-plugin-plugins-embeddable-public.embeddableinstanceconfiguration.id.md) + +## EmbeddableInstanceConfiguration.id property + +Signature: + +```typescript +id: string; +``` diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddableinstanceconfiguration.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddableinstanceconfiguration.md new file mode 100644 index 0000000000000..84f6bcefef447 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddableinstanceconfiguration.md @@ -0,0 +1,19 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [EmbeddableInstanceConfiguration](./kibana-plugin-plugins-embeddable-public.embeddableinstanceconfiguration.md) + +## EmbeddableInstanceConfiguration interface + +Signature: + +```typescript +export interface EmbeddableInstanceConfiguration +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [id](./kibana-plugin-plugins-embeddable-public.embeddableinstanceconfiguration.id.md) | string | | +| [savedObjectId](./kibana-plugin-plugins-embeddable-public.embeddableinstanceconfiguration.savedobjectid.md) | string | | + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddableinstanceconfiguration.savedobjectid.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddableinstanceconfiguration.savedobjectid.md new file mode 100644 index 0000000000000..c1584403c5bba --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddableinstanceconfiguration.savedobjectid.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [EmbeddableInstanceConfiguration](./kibana-plugin-plugins-embeddable-public.embeddableinstanceconfiguration.md) > [savedObjectId](./kibana-plugin-plugins-embeddable-public.embeddableinstanceconfiguration.savedobjectid.md) + +## EmbeddableInstanceConfiguration.savedObjectId property + +Signature: + +```typescript +savedObjectId?: string; +``` diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddableoutput.defaulttitle.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddableoutput.defaulttitle.md new file mode 100644 index 0000000000000..c9d616a96e8e2 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddableoutput.defaulttitle.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [EmbeddableOutput](./kibana-plugin-plugins-embeddable-public.embeddableoutput.md) > [defaultTitle](./kibana-plugin-plugins-embeddable-public.embeddableoutput.defaulttitle.md) + +## EmbeddableOutput.defaultTitle property + +Signature: + +```typescript +defaultTitle?: string; +``` diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddableoutput.editable.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddableoutput.editable.md new file mode 100644 index 0000000000000..4bf84a8f2abf8 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddableoutput.editable.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [EmbeddableOutput](./kibana-plugin-plugins-embeddable-public.embeddableoutput.md) > [editable](./kibana-plugin-plugins-embeddable-public.embeddableoutput.editable.md) + +## EmbeddableOutput.editable property + +Signature: + +```typescript +editable?: boolean; +``` diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddableoutput.editapp.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddableoutput.editapp.md new file mode 100644 index 0000000000000..5c5acd6288ba4 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddableoutput.editapp.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [EmbeddableOutput](./kibana-plugin-plugins-embeddable-public.embeddableoutput.md) > [editApp](./kibana-plugin-plugins-embeddable-public.embeddableoutput.editapp.md) + +## EmbeddableOutput.editApp property + +Signature: + +```typescript +editApp?: string; +``` diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddableoutput.editpath.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddableoutput.editpath.md new file mode 100644 index 0000000000000..da282ece32f20 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddableoutput.editpath.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [EmbeddableOutput](./kibana-plugin-plugins-embeddable-public.embeddableoutput.md) > [editPath](./kibana-plugin-plugins-embeddable-public.embeddableoutput.editpath.md) + +## EmbeddableOutput.editPath property + +Signature: + +```typescript +editPath?: string; +``` diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddableoutput.editurl.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddableoutput.editurl.md new file mode 100644 index 0000000000000..a0c4bed4ad8bb --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddableoutput.editurl.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [EmbeddableOutput](./kibana-plugin-plugins-embeddable-public.embeddableoutput.md) > [editUrl](./kibana-plugin-plugins-embeddable-public.embeddableoutput.editurl.md) + +## EmbeddableOutput.editUrl property + +Signature: + +```typescript +editUrl?: string; +``` diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddableoutput.error.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddableoutput.error.md new file mode 100644 index 0000000000000..db3f27ecf295b --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddableoutput.error.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [EmbeddableOutput](./kibana-plugin-plugins-embeddable-public.embeddableoutput.md) > [error](./kibana-plugin-plugins-embeddable-public.embeddableoutput.error.md) + +## EmbeddableOutput.error property + +Signature: + +```typescript +error?: EmbeddableError; +``` diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddableoutput.loading.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddableoutput.loading.md new file mode 100644 index 0000000000000..a9472b1663f1a --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddableoutput.loading.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [EmbeddableOutput](./kibana-plugin-plugins-embeddable-public.embeddableoutput.md) > [loading](./kibana-plugin-plugins-embeddable-public.embeddableoutput.loading.md) + +## EmbeddableOutput.loading property + +Signature: + +```typescript +loading?: boolean; +``` diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddableoutput.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddableoutput.md new file mode 100644 index 0000000000000..92e1560c34e31 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddableoutput.md @@ -0,0 +1,26 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [EmbeddableOutput](./kibana-plugin-plugins-embeddable-public.embeddableoutput.md) + +## EmbeddableOutput interface + +Signature: + +```typescript +export interface EmbeddableOutput +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [defaultTitle](./kibana-plugin-plugins-embeddable-public.embeddableoutput.defaulttitle.md) | string | | +| [editable](./kibana-plugin-plugins-embeddable-public.embeddableoutput.editable.md) | boolean | | +| [editApp](./kibana-plugin-plugins-embeddable-public.embeddableoutput.editapp.md) | string | | +| [editPath](./kibana-plugin-plugins-embeddable-public.embeddableoutput.editpath.md) | string | | +| [editUrl](./kibana-plugin-plugins-embeddable-public.embeddableoutput.editurl.md) | string | | +| [error](./kibana-plugin-plugins-embeddable-public.embeddableoutput.error.md) | EmbeddableError | | +| [loading](./kibana-plugin-plugins-embeddable-public.embeddableoutput.loading.md) | boolean | | +| [savedObjectId](./kibana-plugin-plugins-embeddable-public.embeddableoutput.savedobjectid.md) | string | | +| [title](./kibana-plugin-plugins-embeddable-public.embeddableoutput.title.md) | string | | + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddableoutput.savedobjectid.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddableoutput.savedobjectid.md new file mode 100644 index 0000000000000..29aca26621d79 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddableoutput.savedobjectid.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [EmbeddableOutput](./kibana-plugin-plugins-embeddable-public.embeddableoutput.md) > [savedObjectId](./kibana-plugin-plugins-embeddable-public.embeddableoutput.savedobjectid.md) + +## EmbeddableOutput.savedObjectId property + +Signature: + +```typescript +savedObjectId?: string; +``` diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddableoutput.title.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddableoutput.title.md new file mode 100644 index 0000000000000..0748a60b38e0f --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddableoutput.title.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [EmbeddableOutput](./kibana-plugin-plugins-embeddable-public.embeddableoutput.md) > [title](./kibana-plugin-plugins-embeddable-public.embeddableoutput.title.md) + +## EmbeddableOutput.title property + +Signature: + +```typescript +title?: string; +``` diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablepackagestate.embeddableid.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablepackagestate.embeddableid.md new file mode 100644 index 0000000000000..de1598d92b6de --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablepackagestate.embeddableid.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [EmbeddablePackageState](./kibana-plugin-plugins-embeddable-public.embeddablepackagestate.md) > [embeddableId](./kibana-plugin-plugins-embeddable-public.embeddablepackagestate.embeddableid.md) + +## EmbeddablePackageState.embeddableId property + +Signature: + +```typescript +embeddableId?: string; +``` diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablepackagestate.input.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablepackagestate.input.md new file mode 100644 index 0000000000000..2f4b1a1fa4237 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablepackagestate.input.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [EmbeddablePackageState](./kibana-plugin-plugins-embeddable-public.embeddablepackagestate.md) > [input](./kibana-plugin-plugins-embeddable-public.embeddablepackagestate.input.md) + +## EmbeddablePackageState.input property + +Signature: + +```typescript +input: Optional | Optional; +``` diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablepackagestate.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablepackagestate.md new file mode 100644 index 0000000000000..1c0b1b8bf8b46 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablepackagestate.md @@ -0,0 +1,22 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [EmbeddablePackageState](./kibana-plugin-plugins-embeddable-public.embeddablepackagestate.md) + +## EmbeddablePackageState interface + +A state package that contains all fields necessary to create or update an embeddable by reference or by value in a container. + +Signature: + +```typescript +export interface EmbeddablePackageState +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [embeddableId](./kibana-plugin-plugins-embeddable-public.embeddablepackagestate.embeddableid.md) | string | | +| [input](./kibana-plugin-plugins-embeddable-public.embeddablepackagestate.input.md) | Optional<EmbeddableInput, 'id'> | Optional<SavedObjectEmbeddableInput, 'id'> | | +| [type](./kibana-plugin-plugins-embeddable-public.embeddablepackagestate.type.md) | string | | + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablepackagestate.type.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablepackagestate.type.md new file mode 100644 index 0000000000000..67ca5b8803dd5 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablepackagestate.type.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [EmbeddablePackageState](./kibana-plugin-plugins-embeddable-public.embeddablepackagestate.md) > [type](./kibana-plugin-plugins-embeddable-public.embeddablepackagestate.type.md) + +## EmbeddablePackageState.type property + +Signature: + +```typescript +type: string; +``` diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablepanel._constructor_.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablepanel._constructor_.md new file mode 100644 index 0000000000000..741e5df8a1590 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablepanel._constructor_.md @@ -0,0 +1,20 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [EmbeddablePanel](./kibana-plugin-plugins-embeddable-public.embeddablepanel.md) > [(constructor)](./kibana-plugin-plugins-embeddable-public.embeddablepanel._constructor_.md) + +## EmbeddablePanel.(constructor) + +Constructs a new instance of the `EmbeddablePanel` class + +Signature: + +```typescript +constructor(props: Props); +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| props | Props | | + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablepanel.closemycontextmenupanel.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablepanel.closemycontextmenupanel.md new file mode 100644 index 0000000000000..6869257675aa4 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablepanel.closemycontextmenupanel.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [EmbeddablePanel](./kibana-plugin-plugins-embeddable-public.embeddablepanel.md) > [closeMyContextMenuPanel](./kibana-plugin-plugins-embeddable-public.embeddablepanel.closemycontextmenupanel.md) + +## EmbeddablePanel.closeMyContextMenuPanel property + +Signature: + +```typescript +closeMyContextMenuPanel: () => void; +``` diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablepanel.componentdidmount.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablepanel.componentdidmount.md new file mode 100644 index 0000000000000..fb281dcf1107f --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablepanel.componentdidmount.md @@ -0,0 +1,15 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [EmbeddablePanel](./kibana-plugin-plugins-embeddable-public.embeddablepanel.md) > [componentDidMount](./kibana-plugin-plugins-embeddable-public.embeddablepanel.componentdidmount.md) + +## EmbeddablePanel.componentDidMount() method + +Signature: + +```typescript +componentDidMount(): void; +``` +Returns: + +`void` + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablepanel.componentwillunmount.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablepanel.componentwillunmount.md new file mode 100644 index 0000000000000..41050f9c7c82a --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablepanel.componentwillunmount.md @@ -0,0 +1,15 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [EmbeddablePanel](./kibana-plugin-plugins-embeddable-public.embeddablepanel.md) > [componentWillUnmount](./kibana-plugin-plugins-embeddable-public.embeddablepanel.componentwillunmount.md) + +## EmbeddablePanel.componentWillUnmount() method + +Signature: + +```typescript +componentWillUnmount(): void; +``` +Returns: + +`void` + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablepanel.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablepanel.md new file mode 100644 index 0000000000000..643649ede51ef --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablepanel.md @@ -0,0 +1,35 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [EmbeddablePanel](./kibana-plugin-plugins-embeddable-public.embeddablepanel.md) + +## EmbeddablePanel class + +Signature: + +```typescript +export declare class EmbeddablePanel extends React.Component +``` + +## Constructors + +| Constructor | Modifiers | Description | +| --- | --- | --- | +| [(constructor)(props)](./kibana-plugin-plugins-embeddable-public.embeddablepanel._constructor_.md) | | Constructs a new instance of the EmbeddablePanel class | + +## Properties + +| Property | Modifiers | Type | Description | +| --- | --- | --- | --- | +| [closeMyContextMenuPanel](./kibana-plugin-plugins-embeddable-public.embeddablepanel.closemycontextmenupanel.md) | | () => void | | +| [onBlur](./kibana-plugin-plugins-embeddable-public.embeddablepanel.onblur.md) | | (blurredPanelIndex: string) => void | | +| [onFocus](./kibana-plugin-plugins-embeddable-public.embeddablepanel.onfocus.md) | | (focusedPanelIndex: string) => void | | + +## Methods + +| Method | Modifiers | Description | +| --- | --- | --- | +| [componentDidMount()](./kibana-plugin-plugins-embeddable-public.embeddablepanel.componentdidmount.md) | | | +| [componentWillUnmount()](./kibana-plugin-plugins-embeddable-public.embeddablepanel.componentwillunmount.md) | | | +| [render()](./kibana-plugin-plugins-embeddable-public.embeddablepanel.render.md) | | | +| [UNSAFE\_componentWillMount()](./kibana-plugin-plugins-embeddable-public.embeddablepanel.unsafe_componentwillmount.md) | | | + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablepanel.onblur.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablepanel.onblur.md new file mode 100644 index 0000000000000..f1db746801818 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablepanel.onblur.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [EmbeddablePanel](./kibana-plugin-plugins-embeddable-public.embeddablepanel.md) > [onBlur](./kibana-plugin-plugins-embeddable-public.embeddablepanel.onblur.md) + +## EmbeddablePanel.onBlur property + +Signature: + +```typescript +onBlur: (blurredPanelIndex: string) => void; +``` diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablepanel.onfocus.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablepanel.onfocus.md new file mode 100644 index 0000000000000..3c9b713eab950 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablepanel.onfocus.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [EmbeddablePanel](./kibana-plugin-plugins-embeddable-public.embeddablepanel.md) > [onFocus](./kibana-plugin-plugins-embeddable-public.embeddablepanel.onfocus.md) + +## EmbeddablePanel.onFocus property + +Signature: + +```typescript +onFocus: (focusedPanelIndex: string) => void; +``` diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablepanel.render.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablepanel.render.md new file mode 100644 index 0000000000000..13e87df47a242 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablepanel.render.md @@ -0,0 +1,15 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [EmbeddablePanel](./kibana-plugin-plugins-embeddable-public.embeddablepanel.md) > [render](./kibana-plugin-plugins-embeddable-public.embeddablepanel.render.md) + +## EmbeddablePanel.render() method + +Signature: + +```typescript +render(): JSX.Element; +``` +Returns: + +`JSX.Element` + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablepanel.unsafe_componentwillmount.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablepanel.unsafe_componentwillmount.md new file mode 100644 index 0000000000000..286d7e9cee1f3 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablepanel.unsafe_componentwillmount.md @@ -0,0 +1,15 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [EmbeddablePanel](./kibana-plugin-plugins-embeddable-public.embeddablepanel.md) > [UNSAFE\_componentWillMount](./kibana-plugin-plugins-embeddable-public.embeddablepanel.unsafe_componentwillmount.md) + +## EmbeddablePanel.UNSAFE\_componentWillMount() method + +Signature: + +```typescript +UNSAFE_componentWillMount(): void; +``` +Returns: + +`void` + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablepanelhoc.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablepanelhoc.md new file mode 100644 index 0000000000000..3f57ac562e6d5 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablepanelhoc.md @@ -0,0 +1,14 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [EmbeddablePanelHOC](./kibana-plugin-plugins-embeddable-public.embeddablepanelhoc.md) + +## EmbeddablePanelHOC type + +Signature: + +```typescript +export declare type EmbeddablePanelHOC = React.FC<{ + embeddable: IEmbeddable; + hideHeader?: boolean; +}>; +``` diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablerenderer.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablerenderer.md new file mode 100644 index 0000000000000..1bc55e6007910 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablerenderer.md @@ -0,0 +1,32 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [EmbeddableRenderer](./kibana-plugin-plugins-embeddable-public.embeddablerenderer.md) + +## EmbeddableRenderer variable + +Helper react component to render an embeddable Can be used if you have an embeddable object or an embeddable factory Supports updating input by passing `input` prop + +Signature: + +```typescript +EmbeddableRenderer: (props: EmbeddableRendererProps) => JSX.Element +``` + +## Remarks + +This component shouldn't be used inside an embeddable container to render embeddable children because children may lose inherited input, here is why: + +When passing `input` inside a prop, internally there is a call: + +```ts +embeddable.updateInput(input); + +``` +If you are simply rendering an embeddable, it's no problem. + +However when you are dealing with containers, you want to be sure to only pass into updateInput the actual state that changed. This is because calling child.updateInput({ foo }) will make foo explicit state. It cannot be inherited from it's parent. + +For example, on a dashboard, the time range is inherited by all children, unless they had their time range set explicitly. This is how "per panel time range" works. That action calls embeddable.updateInput({ timeRange }), and the time range will no longer be inherited from the container. + +see: https://github.com/elastic/kibana/pull/67783\#discussion\_r435447657 for more details. refer to: examples/embeddable\_explorer for examples with correct usage of this component. + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablerendererprops.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablerendererprops.md new file mode 100644 index 0000000000000..c21864b1140e8 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablerendererprops.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [EmbeddableRendererProps](./kibana-plugin-plugins-embeddable-public.embeddablerendererprops.md) + +## EmbeddableRendererProps type + +This type is a publicly exposed props of [EmbeddableRenderer](./kibana-plugin-plugins-embeddable-public.embeddablerenderer.md) Union is used to validate that or factory or embeddable is passed in, but it can't be both simultaneously In case when embeddable is passed in, input is optional, because there is already an input inside of embeddable object In case when factory is used, then input is required, because it will be used as initial input to create an embeddable object + +Signature: + +```typescript +export declare type EmbeddableRendererProps = EmbeddableRendererPropsWithEmbeddable | EmbeddableRendererWithFactory; +``` diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddableroot._constructor_.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddableroot._constructor_.md new file mode 100644 index 0000000000000..4e0a2a6880d29 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddableroot._constructor_.md @@ -0,0 +1,20 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [EmbeddableRoot](./kibana-plugin-plugins-embeddable-public.embeddableroot.md) > [(constructor)](./kibana-plugin-plugins-embeddable-public.embeddableroot._constructor_.md) + +## EmbeddableRoot.(constructor) + +Constructs a new instance of the `EmbeddableRoot` class + +Signature: + +```typescript +constructor(props: Props); +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| props | Props | | + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddableroot.componentdidmount.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddableroot.componentdidmount.md new file mode 100644 index 0000000000000..7085339dd8868 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddableroot.componentdidmount.md @@ -0,0 +1,15 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [EmbeddableRoot](./kibana-plugin-plugins-embeddable-public.embeddableroot.md) > [componentDidMount](./kibana-plugin-plugins-embeddable-public.embeddableroot.componentdidmount.md) + +## EmbeddableRoot.componentDidMount() method + +Signature: + +```typescript +componentDidMount(): void; +``` +Returns: + +`void` + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddableroot.componentdidupdate.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddableroot.componentdidupdate.md new file mode 100644 index 0000000000000..386c8c61681d5 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddableroot.componentdidupdate.md @@ -0,0 +1,22 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [EmbeddableRoot](./kibana-plugin-plugins-embeddable-public.embeddableroot.md) > [componentDidUpdate](./kibana-plugin-plugins-embeddable-public.embeddableroot.componentdidupdate.md) + +## EmbeddableRoot.componentDidUpdate() method + +Signature: + +```typescript +componentDidUpdate(prevProps?: Props): void; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| prevProps | Props | | + +Returns: + +`void` + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddableroot.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddableroot.md new file mode 100644 index 0000000000000..49d8a184f334c --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddableroot.md @@ -0,0 +1,27 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [EmbeddableRoot](./kibana-plugin-plugins-embeddable-public.embeddableroot.md) + +## EmbeddableRoot class + +Signature: + +```typescript +export declare class EmbeddableRoot extends React.Component +``` + +## Constructors + +| Constructor | Modifiers | Description | +| --- | --- | --- | +| [(constructor)(props)](./kibana-plugin-plugins-embeddable-public.embeddableroot._constructor_.md) | | Constructs a new instance of the EmbeddableRoot class | + +## Methods + +| Method | Modifiers | Description | +| --- | --- | --- | +| [componentDidMount()](./kibana-plugin-plugins-embeddable-public.embeddableroot.componentdidmount.md) | | | +| [componentDidUpdate(prevProps)](./kibana-plugin-plugins-embeddable-public.embeddableroot.componentdidupdate.md) | | | +| [render()](./kibana-plugin-plugins-embeddable-public.embeddableroot.render.md) | | | +| [shouldComponentUpdate(newProps)](./kibana-plugin-plugins-embeddable-public.embeddableroot.shouldcomponentupdate.md) | | | + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddableroot.render.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddableroot.render.md new file mode 100644 index 0000000000000..d9b3820dede15 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddableroot.render.md @@ -0,0 +1,15 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [EmbeddableRoot](./kibana-plugin-plugins-embeddable-public.embeddableroot.md) > [render](./kibana-plugin-plugins-embeddable-public.embeddableroot.render.md) + +## EmbeddableRoot.render() method + +Signature: + +```typescript +render(): JSX.Element; +``` +Returns: + +`JSX.Element` + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddableroot.shouldcomponentupdate.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddableroot.shouldcomponentupdate.md new file mode 100644 index 0000000000000..36b08f72c0e40 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddableroot.shouldcomponentupdate.md @@ -0,0 +1,22 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [EmbeddableRoot](./kibana-plugin-plugins-embeddable-public.embeddableroot.md) > [shouldComponentUpdate](./kibana-plugin-plugins-embeddable-public.embeddableroot.shouldcomponentupdate.md) + +## EmbeddableRoot.shouldComponentUpdate() method + +Signature: + +```typescript +shouldComponentUpdate(newProps: Props): boolean; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| newProps | Props | | + +Returns: + +`boolean` + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablesetup.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablesetup.md new file mode 100644 index 0000000000000..97d6eda66bdcd --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablesetup.md @@ -0,0 +1,20 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [EmbeddableSetup](./kibana-plugin-plugins-embeddable-public.embeddablesetup.md) + +## EmbeddableSetup interface + +Signature: + +```typescript +export interface EmbeddableSetup +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [registerEmbeddableFactory](./kibana-plugin-plugins-embeddable-public.embeddablesetup.registerembeddablefactory.md) | <I extends EmbeddableInput, O extends EmbeddableOutput, E extends IEmbeddable<I, O> = IEmbeddable<I, O>>(id: string, factory: EmbeddableFactoryDefinition<I, O, E>) => () => EmbeddableFactory<I, O, E> | | +| [registerEnhancement](./kibana-plugin-plugins-embeddable-public.embeddablesetup.registerenhancement.md) | (enhancement: EnhancementRegistryDefinition) => void | | +| [setCustomEmbeddableFactoryProvider](./kibana-plugin-plugins-embeddable-public.embeddablesetup.setcustomembeddablefactoryprovider.md) | (customProvider: EmbeddableFactoryProvider) => void | | + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablesetup.registerembeddablefactory.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablesetup.registerembeddablefactory.md new file mode 100644 index 0000000000000..d9f63b30dfe6d --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablesetup.registerembeddablefactory.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [EmbeddableSetup](./kibana-plugin-plugins-embeddable-public.embeddablesetup.md) > [registerEmbeddableFactory](./kibana-plugin-plugins-embeddable-public.embeddablesetup.registerembeddablefactory.md) + +## EmbeddableSetup.registerEmbeddableFactory property + +Signature: + +```typescript +registerEmbeddableFactory: = IEmbeddable>(id: string, factory: EmbeddableFactoryDefinition) => () => EmbeddableFactory; +``` diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablesetup.registerenhancement.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablesetup.registerenhancement.md new file mode 100644 index 0000000000000..46baaf6dbf268 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablesetup.registerenhancement.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [EmbeddableSetup](./kibana-plugin-plugins-embeddable-public.embeddablesetup.md) > [registerEnhancement](./kibana-plugin-plugins-embeddable-public.embeddablesetup.registerenhancement.md) + +## EmbeddableSetup.registerEnhancement property + +Signature: + +```typescript +registerEnhancement: (enhancement: EnhancementRegistryDefinition) => void; +``` diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablesetup.setcustomembeddablefactoryprovider.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablesetup.setcustomembeddablefactoryprovider.md new file mode 100644 index 0000000000000..463ff80e5818b --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablesetup.setcustomembeddablefactoryprovider.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [EmbeddableSetup](./kibana-plugin-plugins-embeddable-public.embeddablesetup.md) > [setCustomEmbeddableFactoryProvider](./kibana-plugin-plugins-embeddable-public.embeddablesetup.setcustomembeddablefactoryprovider.md) + +## EmbeddableSetup.setCustomEmbeddableFactoryProvider property + +Signature: + +```typescript +setCustomEmbeddableFactoryProvider: (customProvider: EmbeddableFactoryProvider) => void; +``` diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablesetupdependencies.data.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablesetupdependencies.data.md new file mode 100644 index 0000000000000..d3a62657372ac --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablesetupdependencies.data.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [EmbeddableSetupDependencies](./kibana-plugin-plugins-embeddable-public.embeddablesetupdependencies.md) > [data](./kibana-plugin-plugins-embeddable-public.embeddablesetupdependencies.data.md) + +## EmbeddableSetupDependencies.data property + +Signature: + +```typescript +data: DataPublicPluginSetup; +``` diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablesetupdependencies.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablesetupdependencies.md new file mode 100644 index 0000000000000..fdd31ca75be2a --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablesetupdependencies.md @@ -0,0 +1,19 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [EmbeddableSetupDependencies](./kibana-plugin-plugins-embeddable-public.embeddablesetupdependencies.md) + +## EmbeddableSetupDependencies interface + +Signature: + +```typescript +export interface EmbeddableSetupDependencies +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [data](./kibana-plugin-plugins-embeddable-public.embeddablesetupdependencies.data.md) | DataPublicPluginSetup | | +| [uiActions](./kibana-plugin-plugins-embeddable-public.embeddablesetupdependencies.uiactions.md) | UiActionsSetup | | + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablesetupdependencies.uiactions.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablesetupdependencies.uiactions.md new file mode 100644 index 0000000000000..7eff6e2b0b28b --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablesetupdependencies.uiactions.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [EmbeddableSetupDependencies](./kibana-plugin-plugins-embeddable-public.embeddablesetupdependencies.md) > [uiActions](./kibana-plugin-plugins-embeddable-public.embeddablesetupdependencies.uiactions.md) + +## EmbeddableSetupDependencies.uiActions property + +Signature: + +```typescript +uiActions: UiActionsSetup; +``` diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablestart.embeddablepanel.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablestart.embeddablepanel.md new file mode 100644 index 0000000000000..b8c10bf0e4473 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablestart.embeddablepanel.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [EmbeddableStart](./kibana-plugin-plugins-embeddable-public.embeddablestart.md) > [EmbeddablePanel](./kibana-plugin-plugins-embeddable-public.embeddablestart.embeddablepanel.md) + +## EmbeddableStart.EmbeddablePanel property + +Signature: + +```typescript +EmbeddablePanel: EmbeddablePanelHOC; +``` diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablestart.getattributeservice.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablestart.getattributeservice.md new file mode 100644 index 0000000000000..ca75b756d199e --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablestart.getattributeservice.md @@ -0,0 +1,17 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [EmbeddableStart](./kibana-plugin-plugins-embeddable-public.embeddablestart.md) > [getAttributeService](./kibana-plugin-plugins-embeddable-public.embeddablestart.getattributeservice.md) + +## EmbeddableStart.getAttributeService property + +Signature: + +```typescript +getAttributeService:
(type: string, options: AttributeServiceOptions) => AttributeService; +``` diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablestart.getembeddablefactories.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablestart.getembeddablefactories.md new file mode 100644 index 0000000000000..cc6b1187903bf --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablestart.getembeddablefactories.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [EmbeddableStart](./kibana-plugin-plugins-embeddable-public.embeddablestart.md) > [getEmbeddableFactories](./kibana-plugin-plugins-embeddable-public.embeddablestart.getembeddablefactories.md) + +## EmbeddableStart.getEmbeddableFactories property + +Signature: + +```typescript +getEmbeddableFactories: () => IterableIterator; +``` diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablestart.getembeddablefactory.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablestart.getembeddablefactory.md new file mode 100644 index 0000000000000..d91878754bd7d --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablestart.getembeddablefactory.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [EmbeddableStart](./kibana-plugin-plugins-embeddable-public.embeddablestart.md) > [getEmbeddableFactory](./kibana-plugin-plugins-embeddable-public.embeddablestart.getembeddablefactory.md) + +## EmbeddableStart.getEmbeddableFactory property + +Signature: + +```typescript +getEmbeddableFactory: = IEmbeddable>(embeddableFactoryId: string) => EmbeddableFactory | undefined; +``` diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablestart.getembeddablepanel.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablestart.getembeddablepanel.md new file mode 100644 index 0000000000000..7ba24a62a3893 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablestart.getembeddablepanel.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [EmbeddableStart](./kibana-plugin-plugins-embeddable-public.embeddablestart.md) > [getEmbeddablePanel](./kibana-plugin-plugins-embeddable-public.embeddablestart.getembeddablepanel.md) + +## EmbeddableStart.getEmbeddablePanel property + +Signature: + +```typescript +getEmbeddablePanel: (stateTransfer?: EmbeddableStateTransfer) => EmbeddablePanelHOC; +``` diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablestart.getstatetransfer.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablestart.getstatetransfer.md new file mode 100644 index 0000000000000..dafc66b1a6e15 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablestart.getstatetransfer.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [EmbeddableStart](./kibana-plugin-plugins-embeddable-public.embeddablestart.md) > [getStateTransfer](./kibana-plugin-plugins-embeddable-public.embeddablestart.getstatetransfer.md) + +## EmbeddableStart.getStateTransfer property + +Signature: + +```typescript +getStateTransfer: (history?: ScopedHistory) => EmbeddableStateTransfer; +``` diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablestart.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablestart.md new file mode 100644 index 0000000000000..541575566d3f7 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablestart.md @@ -0,0 +1,23 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [EmbeddableStart](./kibana-plugin-plugins-embeddable-public.embeddablestart.md) + +## EmbeddableStart interface + +Signature: + +```typescript +export interface EmbeddableStart extends PersistableState +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [EmbeddablePanel](./kibana-plugin-plugins-embeddable-public.embeddablestart.embeddablepanel.md) | EmbeddablePanelHOC | | +| [getAttributeService](./kibana-plugin-plugins-embeddable-public.embeddablestart.getattributeservice.md) | <A extends {
title: string;
}, V extends EmbeddableInput & {
[ATTRIBUTE_SERVICE_KEY]: A;
} = EmbeddableInput & {
[ATTRIBUTE_SERVICE_KEY]: A;
}, R extends SavedObjectEmbeddableInput = SavedObjectEmbeddableInput>(type: string, options: AttributeServiceOptions<A>) => AttributeService<A, V, R> | | +| [getEmbeddableFactories](./kibana-plugin-plugins-embeddable-public.embeddablestart.getembeddablefactories.md) | () => IterableIterator<EmbeddableFactory> | | +| [getEmbeddableFactory](./kibana-plugin-plugins-embeddable-public.embeddablestart.getembeddablefactory.md) | <I extends EmbeddableInput = EmbeddableInput, O extends EmbeddableOutput = EmbeddableOutput, E extends IEmbeddable<I, O> = IEmbeddable<I, O>>(embeddableFactoryId: string) => EmbeddableFactory<I, O, E> | undefined | | +| [getEmbeddablePanel](./kibana-plugin-plugins-embeddable-public.embeddablestart.getembeddablepanel.md) | (stateTransfer?: EmbeddableStateTransfer) => EmbeddablePanelHOC | | +| [getStateTransfer](./kibana-plugin-plugins-embeddable-public.embeddablestart.getstatetransfer.md) | (history?: ScopedHistory) => EmbeddableStateTransfer | | + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablestartdependencies.data.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablestartdependencies.data.md new file mode 100644 index 0000000000000..0595609b11e49 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablestartdependencies.data.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [EmbeddableStartDependencies](./kibana-plugin-plugins-embeddable-public.embeddablestartdependencies.md) > [data](./kibana-plugin-plugins-embeddable-public.embeddablestartdependencies.data.md) + +## EmbeddableStartDependencies.data property + +Signature: + +```typescript +data: DataPublicPluginStart; +``` diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablestartdependencies.inspector.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablestartdependencies.inspector.md new file mode 100644 index 0000000000000..299cc945104ab --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablestartdependencies.inspector.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [EmbeddableStartDependencies](./kibana-plugin-plugins-embeddable-public.embeddablestartdependencies.md) > [inspector](./kibana-plugin-plugins-embeddable-public.embeddablestartdependencies.inspector.md) + +## EmbeddableStartDependencies.inspector property + +Signature: + +```typescript +inspector: InspectorStart; +``` diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablestartdependencies.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablestartdependencies.md new file mode 100644 index 0000000000000..5a1b5d1e06861 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablestartdependencies.md @@ -0,0 +1,20 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [EmbeddableStartDependencies](./kibana-plugin-plugins-embeddable-public.embeddablestartdependencies.md) + +## EmbeddableStartDependencies interface + +Signature: + +```typescript +export interface EmbeddableStartDependencies +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [data](./kibana-plugin-plugins-embeddable-public.embeddablestartdependencies.data.md) | DataPublicPluginStart | | +| [inspector](./kibana-plugin-plugins-embeddable-public.embeddablestartdependencies.inspector.md) | InspectorStart | | +| [uiActions](./kibana-plugin-plugins-embeddable-public.embeddablestartdependencies.uiactions.md) | UiActionsStart | | + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablestartdependencies.uiactions.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablestartdependencies.uiactions.md new file mode 100644 index 0000000000000..398ee3fbcbc50 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablestartdependencies.uiactions.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [EmbeddableStartDependencies](./kibana-plugin-plugins-embeddable-public.embeddablestartdependencies.md) > [uiActions](./kibana-plugin-plugins-embeddable-public.embeddablestartdependencies.uiactions.md) + +## EmbeddableStartDependencies.uiActions property + +Signature: + +```typescript +uiActions: UiActionsStart; +``` diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablestatetransfer._constructor_.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablestatetransfer._constructor_.md new file mode 100644 index 0000000000000..323ed5e38bde1 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablestatetransfer._constructor_.md @@ -0,0 +1,22 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [EmbeddableStateTransfer](./kibana-plugin-plugins-embeddable-public.embeddablestatetransfer.md) > [(constructor)](./kibana-plugin-plugins-embeddable-public.embeddablestatetransfer._constructor_.md) + +## EmbeddableStateTransfer.(constructor) + +Constructs a new instance of the `EmbeddableStateTransfer` class + +Signature: + +```typescript +constructor(navigateToApp: ApplicationStart['navigateToApp'], scopedHistory?: ScopedHistory | undefined, appList?: ReadonlyMap | undefined); +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| navigateToApp | ApplicationStart['navigateToApp'] | | +| scopedHistory | ScopedHistory<unknown> | undefined | | +| appList | ReadonlyMap<string, PublicAppInfo> | undefined | | + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablestatetransfer.getappnamefromid.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablestatetransfer.getappnamefromid.md new file mode 100644 index 0000000000000..f15574593e853 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablestatetransfer.getappnamefromid.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [EmbeddableStateTransfer](./kibana-plugin-plugins-embeddable-public.embeddablestatetransfer.md) > [getAppNameFromId](./kibana-plugin-plugins-embeddable-public.embeddablestatetransfer.getappnamefromid.md) + +## EmbeddableStateTransfer.getAppNameFromId property + +Fetches an internationalized app title when given an appId. + +Signature: + +```typescript +getAppNameFromId: (appId: string) => string | undefined; +``` diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablestatetransfer.getincomingeditorstate.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablestatetransfer.getincomingeditorstate.md new file mode 100644 index 0000000000000..2a0823a9bf835 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablestatetransfer.getincomingeditorstate.md @@ -0,0 +1,26 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [EmbeddableStateTransfer](./kibana-plugin-plugins-embeddable-public.embeddablestatetransfer.md) > [getIncomingEditorState](./kibana-plugin-plugins-embeddable-public.embeddablestatetransfer.getincomingeditorstate.md) + +## EmbeddableStateTransfer.getIncomingEditorState() method + +Fetches an [originating app](./kibana-plugin-plugins-embeddable-public.embeddableeditorstate.md) argument from the scoped history's location state. + +Signature: + +```typescript +getIncomingEditorState(options?: { + keysToRemoveAfterFetch?: string[]; + }): EmbeddableEditorState | undefined; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| options | {
keysToRemoveAfterFetch?: string[];
} | | + +Returns: + +`EmbeddableEditorState | undefined` + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablestatetransfer.getincomingembeddablepackage.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablestatetransfer.getincomingembeddablepackage.md new file mode 100644 index 0000000000000..2069f0ce084f9 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablestatetransfer.getincomingembeddablepackage.md @@ -0,0 +1,26 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [EmbeddableStateTransfer](./kibana-plugin-plugins-embeddable-public.embeddablestatetransfer.md) > [getIncomingEmbeddablePackage](./kibana-plugin-plugins-embeddable-public.embeddablestatetransfer.getincomingembeddablepackage.md) + +## EmbeddableStateTransfer.getIncomingEmbeddablePackage() method + +Fetches an [embeddable package](./kibana-plugin-plugins-embeddable-public.embeddablepackagestate.md) argument from the scoped history's location state. + +Signature: + +```typescript +getIncomingEmbeddablePackage(options?: { + keysToRemoveAfterFetch?: string[]; + }): EmbeddablePackageState | undefined; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| options | {
keysToRemoveAfterFetch?: string[];
} | | + +Returns: + +`EmbeddablePackageState | undefined` + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablestatetransfer.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablestatetransfer.md new file mode 100644 index 0000000000000..2b44693e14846 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablestatetransfer.md @@ -0,0 +1,35 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [EmbeddableStateTransfer](./kibana-plugin-plugins-embeddable-public.embeddablestatetransfer.md) + +## EmbeddableStateTransfer class + +A wrapper around the state object in which provides strongly typed helper methods for common incoming and outgoing states used by the embeddable infrastructure. + +Signature: + +```typescript +export declare class EmbeddableStateTransfer +``` + +## Constructors + +| Constructor | Modifiers | Description | +| --- | --- | --- | +| [(constructor)(navigateToApp, scopedHistory, appList)](./kibana-plugin-plugins-embeddable-public.embeddablestatetransfer._constructor_.md) | | Constructs a new instance of the EmbeddableStateTransfer class | + +## Properties + +| Property | Modifiers | Type | Description | +| --- | --- | --- | --- | +| [getAppNameFromId](./kibana-plugin-plugins-embeddable-public.embeddablestatetransfer.getappnamefromid.md) | | (appId: string) => string | undefined | Fetches an internationalized app title when given an appId. | + +## Methods + +| Method | Modifiers | Description | +| --- | --- | --- | +| [getIncomingEditorState(options)](./kibana-plugin-plugins-embeddable-public.embeddablestatetransfer.getincomingeditorstate.md) | | Fetches an [originating app](./kibana-plugin-plugins-embeddable-public.embeddableeditorstate.md) argument from the scoped history's location state. | +| [getIncomingEmbeddablePackage(options)](./kibana-plugin-plugins-embeddable-public.embeddablestatetransfer.getincomingembeddablepackage.md) | | Fetches an [embeddable package](./kibana-plugin-plugins-embeddable-public.embeddablepackagestate.md) argument from the scoped history's location state. | +| [navigateToEditor(appId, options)](./kibana-plugin-plugins-embeddable-public.embeddablestatetransfer.navigatetoeditor.md) | | A wrapper around the method which navigates to the specified appId with [embeddable editor state](./kibana-plugin-plugins-embeddable-public.embeddableeditorstate.md) | +| [navigateToWithEmbeddablePackage(appId, options)](./kibana-plugin-plugins-embeddable-public.embeddablestatetransfer.navigatetowithembeddablepackage.md) | | A wrapper around the method which navigates to the specified appId with [embeddable package state](./kibana-plugin-plugins-embeddable-public.embeddablepackagestate.md) | + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablestatetransfer.navigatetoeditor.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablestatetransfer.navigatetoeditor.md new file mode 100644 index 0000000000000..fa24784d9aac5 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablestatetransfer.navigatetoeditor.md @@ -0,0 +1,29 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [EmbeddableStateTransfer](./kibana-plugin-plugins-embeddable-public.embeddablestatetransfer.md) > [navigateToEditor](./kibana-plugin-plugins-embeddable-public.embeddablestatetransfer.navigatetoeditor.md) + +## EmbeddableStateTransfer.navigateToEditor() method + +A wrapper around the method which navigates to the specified appId with [embeddable editor state](./kibana-plugin-plugins-embeddable-public.embeddableeditorstate.md) + +Signature: + +```typescript +navigateToEditor(appId: string, options?: { + path?: string; + state: EmbeddableEditorState; + appendToExistingState?: boolean; + }): Promise; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| appId | string | | +| options | {
path?: string;
state: EmbeddableEditorState;
appendToExistingState?: boolean;
} | | + +Returns: + +`Promise` + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablestatetransfer.navigatetowithembeddablepackage.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablestatetransfer.navigatetowithembeddablepackage.md new file mode 100644 index 0000000000000..7173bc8b127cd --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablestatetransfer.navigatetowithembeddablepackage.md @@ -0,0 +1,29 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [EmbeddableStateTransfer](./kibana-plugin-plugins-embeddable-public.embeddablestatetransfer.md) > [navigateToWithEmbeddablePackage](./kibana-plugin-plugins-embeddable-public.embeddablestatetransfer.navigatetowithembeddablepackage.md) + +## EmbeddableStateTransfer.navigateToWithEmbeddablePackage() method + +A wrapper around the method which navigates to the specified appId with [embeddable package state](./kibana-plugin-plugins-embeddable-public.embeddablepackagestate.md) + +Signature: + +```typescript +navigateToWithEmbeddablePackage(appId: string, options?: { + path?: string; + state: EmbeddablePackageState; + appendToExistingState?: boolean; + }): Promise; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| appId | string | | +| options | {
path?: string;
state: EmbeddablePackageState;
appendToExistingState?: boolean;
} | | + +Returns: + +`Promise` + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.enhancementregistrydefinition.id.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.enhancementregistrydefinition.id.md new file mode 100644 index 0000000000000..083b3931bcf7d --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.enhancementregistrydefinition.id.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [EnhancementRegistryDefinition](./kibana-plugin-plugins-embeddable-public.enhancementregistrydefinition.md) > [id](./kibana-plugin-plugins-embeddable-public.enhancementregistrydefinition.id.md) + +## EnhancementRegistryDefinition.id property + +Signature: + +```typescript +id: string; +``` diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.enhancementregistrydefinition.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.enhancementregistrydefinition.md new file mode 100644 index 0000000000000..c54ebe4b1712d --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.enhancementregistrydefinition.md @@ -0,0 +1,18 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [EnhancementRegistryDefinition](./kibana-plugin-plugins-embeddable-public.enhancementregistrydefinition.md) + +## EnhancementRegistryDefinition interface + +Signature: + +```typescript +export interface EnhancementRegistryDefinition

extends PersistableStateDefinition

+``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [id](./kibana-plugin-plugins-embeddable-public.enhancementregistrydefinition.id.md) | string | | + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.errorembeddable._constructor_.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.errorembeddable._constructor_.md new file mode 100644 index 0000000000000..0facb07b41692 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.errorembeddable._constructor_.md @@ -0,0 +1,22 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [ErrorEmbeddable](./kibana-plugin-plugins-embeddable-public.errorembeddable.md) > [(constructor)](./kibana-plugin-plugins-embeddable-public.errorembeddable._constructor_.md) + +## ErrorEmbeddable.(constructor) + +Constructs a new instance of the `ErrorEmbeddable` class + +Signature: + +```typescript +constructor(error: Error | string, input: EmbeddableInput, parent?: IContainer); +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| error | Error | string | | +| input | EmbeddableInput | | +| parent | IContainer | | + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.errorembeddable.destroy.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.errorembeddable.destroy.md new file mode 100644 index 0000000000000..eeb605f2140ec --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.errorembeddable.destroy.md @@ -0,0 +1,15 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [ErrorEmbeddable](./kibana-plugin-plugins-embeddable-public.errorembeddable.md) > [destroy](./kibana-plugin-plugins-embeddable-public.errorembeddable.destroy.md) + +## ErrorEmbeddable.destroy() method + +Signature: + +```typescript +destroy(): void; +``` +Returns: + +`void` + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.errorembeddable.error.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.errorembeddable.error.md new file mode 100644 index 0000000000000..7e4def3d52923 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.errorembeddable.error.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [ErrorEmbeddable](./kibana-plugin-plugins-embeddable-public.errorembeddable.md) > [error](./kibana-plugin-plugins-embeddable-public.errorembeddable.error.md) + +## ErrorEmbeddable.error property + +Signature: + +```typescript +error: Error | string; +``` diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.errorembeddable.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.errorembeddable.md new file mode 100644 index 0000000000000..75f3fc6d503d5 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.errorembeddable.md @@ -0,0 +1,33 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [ErrorEmbeddable](./kibana-plugin-plugins-embeddable-public.errorembeddable.md) + +## ErrorEmbeddable class + +Signature: + +```typescript +export declare class ErrorEmbeddable extends Embeddable +``` + +## Constructors + +| Constructor | Modifiers | Description | +| --- | --- | --- | +| [(constructor)(error, input, parent)](./kibana-plugin-plugins-embeddable-public.errorembeddable._constructor_.md) | | Constructs a new instance of the ErrorEmbeddable class | + +## Properties + +| Property | Modifiers | Type | Description | +| --- | --- | --- | --- | +| [error](./kibana-plugin-plugins-embeddable-public.errorembeddable.error.md) | | Error | string | | +| [type](./kibana-plugin-plugins-embeddable-public.errorembeddable.type.md) | | | | + +## Methods + +| Method | Modifiers | Description | +| --- | --- | --- | +| [destroy()](./kibana-plugin-plugins-embeddable-public.errorembeddable.destroy.md) | | | +| [reload()](./kibana-plugin-plugins-embeddable-public.errorembeddable.reload.md) | | | +| [render(dom)](./kibana-plugin-plugins-embeddable-public.errorembeddable.render.md) | | | + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.errorembeddable.reload.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.errorembeddable.reload.md new file mode 100644 index 0000000000000..14d7c9fcf7ee0 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.errorembeddable.reload.md @@ -0,0 +1,15 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [ErrorEmbeddable](./kibana-plugin-plugins-embeddable-public.errorembeddable.md) > [reload](./kibana-plugin-plugins-embeddable-public.errorembeddable.reload.md) + +## ErrorEmbeddable.reload() method + +Signature: + +```typescript +reload(): void; +``` +Returns: + +`void` + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.errorembeddable.render.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.errorembeddable.render.md new file mode 100644 index 0000000000000..70c9d169f3f7e --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.errorembeddable.render.md @@ -0,0 +1,22 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [ErrorEmbeddable](./kibana-plugin-plugins-embeddable-public.errorembeddable.md) > [render](./kibana-plugin-plugins-embeddable-public.errorembeddable.render.md) + +## ErrorEmbeddable.render() method + +Signature: + +```typescript +render(dom: HTMLElement): void; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| dom | HTMLElement | | + +Returns: + +`void` + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.errorembeddable.type.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.errorembeddable.type.md new file mode 100644 index 0000000000000..d407e743a89af --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.errorembeddable.type.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [ErrorEmbeddable](./kibana-plugin-plugins-embeddable-public.errorembeddable.md) > [type](./kibana-plugin-plugins-embeddable-public.errorembeddable.type.md) + +## ErrorEmbeddable.type property + +Signature: + +```typescript +readonly type = "error"; +``` diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.icontainer.addnewembeddable.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.icontainer.addnewembeddable.md new file mode 100644 index 0000000000000..ca0095580a0ba --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.icontainer.addnewembeddable.md @@ -0,0 +1,25 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [IContainer](./kibana-plugin-plugins-embeddable-public.icontainer.md) > [addNewEmbeddable](./kibana-plugin-plugins-embeddable-public.icontainer.addnewembeddable.md) + +## IContainer.addNewEmbeddable() method + +Adds a new embeddable to the container. `explicitInput` may partially specify the required embeddable input, but the remainder must come from inherited container state. + +Signature: + +```typescript +addNewEmbeddable = Embeddable>(type: string, explicitInput: Partial): Promise; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| type | string | | +| explicitInput | Partial<EEI> | | + +Returns: + +`Promise` + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.icontainer.getchild.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.icontainer.getchild.md new file mode 100644 index 0000000000000..4355cfb68ad3f --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.icontainer.getchild.md @@ -0,0 +1,24 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [IContainer](./kibana-plugin-plugins-embeddable-public.icontainer.md) > [getChild](./kibana-plugin-plugins-embeddable-public.icontainer.getchild.md) + +## IContainer.getChild() method + +Returns the child embeddable with the given id. + +Signature: + +```typescript +getChild = Embeddable>(id: string): E; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| id | string | | + +Returns: + +`E` + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.icontainer.getinputforchild.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.icontainer.getinputforchild.md new file mode 100644 index 0000000000000..e5afc0eac3ce0 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.icontainer.getinputforchild.md @@ -0,0 +1,24 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [IContainer](./kibana-plugin-plugins-embeddable-public.icontainer.md) > [getInputForChild](./kibana-plugin-plugins-embeddable-public.icontainer.getinputforchild.md) + +## IContainer.getInputForChild() method + +Returns the input for the given child. Uses a combination of explicit input for the child stored on the parent and derived/inherited input taken from the container itself. + +Signature: + +```typescript +getInputForChild(id: string): EEI; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| id | string | | + +Returns: + +`EEI` + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.icontainer.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.icontainer.md new file mode 100644 index 0000000000000..cba430069c7a4 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.icontainer.md @@ -0,0 +1,23 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [IContainer](./kibana-plugin-plugins-embeddable-public.icontainer.md) + +## IContainer interface + +Signature: + +```typescript +export interface IContainer = ContainerInput, O extends ContainerOutput = ContainerOutput> extends IEmbeddable +``` + +## Methods + +| Method | Description | +| --- | --- | +| [addNewEmbeddable(type, explicitInput)](./kibana-plugin-plugins-embeddable-public.icontainer.addnewembeddable.md) | Adds a new embeddable to the container. explicitInput may partially specify the required embeddable input, but the remainder must come from inherited container state. | +| [getChild(id)](./kibana-plugin-plugins-embeddable-public.icontainer.getchild.md) | Returns the child embeddable with the given id. | +| [getInputForChild(id)](./kibana-plugin-plugins-embeddable-public.icontainer.getinputforchild.md) | Returns the input for the given child. Uses a combination of explicit input for the child stored on the parent and derived/inherited input taken from the container itself. | +| [removeEmbeddable(embeddableId)](./kibana-plugin-plugins-embeddable-public.icontainer.removeembeddable.md) | Removes the embeddable with the given id. | +| [untilEmbeddableLoaded(id)](./kibana-plugin-plugins-embeddable-public.icontainer.untilembeddableloaded.md) | Call if you want to wait until an embeddable with that id has finished loading. | +| [updateInputForChild(id, changes)](./kibana-plugin-plugins-embeddable-public.icontainer.updateinputforchild.md) | Changes the input for a given child. Note, this will override any inherited state taken from the container itself. | + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.icontainer.removeembeddable.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.icontainer.removeembeddable.md new file mode 100644 index 0000000000000..94a991ca20a14 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.icontainer.removeembeddable.md @@ -0,0 +1,24 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [IContainer](./kibana-plugin-plugins-embeddable-public.icontainer.md) > [removeEmbeddable](./kibana-plugin-plugins-embeddable-public.icontainer.removeembeddable.md) + +## IContainer.removeEmbeddable() method + +Removes the embeddable with the given id. + +Signature: + +```typescript +removeEmbeddable(embeddableId: string): void; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| embeddableId | string | | + +Returns: + +`void` + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.icontainer.untilembeddableloaded.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.icontainer.untilembeddableloaded.md new file mode 100644 index 0000000000000..0d6d4a3d8ccf0 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.icontainer.untilembeddableloaded.md @@ -0,0 +1,24 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [IContainer](./kibana-plugin-plugins-embeddable-public.icontainer.md) > [untilEmbeddableLoaded](./kibana-plugin-plugins-embeddable-public.icontainer.untilembeddableloaded.md) + +## IContainer.untilEmbeddableLoaded() method + +Call if you want to wait until an embeddable with that id has finished loading. + +Signature: + +```typescript +untilEmbeddableLoaded(id: string): Promise; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| id | string | | + +Returns: + +`Promise` + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.icontainer.updateinputforchild.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.icontainer.updateinputforchild.md new file mode 100644 index 0000000000000..04a82b0065516 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.icontainer.updateinputforchild.md @@ -0,0 +1,25 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [IContainer](./kibana-plugin-plugins-embeddable-public.icontainer.md) > [updateInputForChild](./kibana-plugin-plugins-embeddable-public.icontainer.updateinputforchild.md) + +## IContainer.updateInputForChild() method + +Changes the input for a given child. Note, this will override any inherited state taken from the container itself. + +Signature: + +```typescript +updateInputForChild(id: string, changes: Partial): void; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| id | string | | +| changes | Partial<EEI> | | + +Returns: + +`void` + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.iembeddable.destroy.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.iembeddable.destroy.md new file mode 100644 index 0000000000000..7fc636f40f3c2 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.iembeddable.destroy.md @@ -0,0 +1,17 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [IEmbeddable](./kibana-plugin-plugins-embeddable-public.iembeddable.md) > [destroy](./kibana-plugin-plugins-embeddable-public.iembeddable.destroy.md) + +## IEmbeddable.destroy() method + +Cleans up subscriptions, destroy nodes mounted from calls to render. + +Signature: + +```typescript +destroy(): void; +``` +Returns: + +`void` + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.iembeddable.enhancements.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.iembeddable.enhancements.md new file mode 100644 index 0000000000000..9183cd6887872 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.iembeddable.enhancements.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [IEmbeddable](./kibana-plugin-plugins-embeddable-public.iembeddable.md) > [enhancements](./kibana-plugin-plugins-embeddable-public.iembeddable.enhancements.md) + +## IEmbeddable.enhancements property + +Extra abilities added to Embeddable by `*_enhanced` plugins. + +Signature: + +```typescript +enhancements?: object; +``` diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.iembeddable.getinput.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.iembeddable.getinput.md new file mode 100644 index 0000000000000..2fd8db07fa342 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.iembeddable.getinput.md @@ -0,0 +1,21 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [IEmbeddable](./kibana-plugin-plugins-embeddable-public.iembeddable.md) > [getInput](./kibana-plugin-plugins-embeddable-public.iembeddable.getinput.md) + +## IEmbeddable.getInput() method + +Get the input used to instantiate this embeddable. The input is a serialized representation of this embeddable instance and can be used to clone or re-instantiate it. Input state: + +- Can be updated externally - Can change multiple times for a single embeddable instance. + +Examples: title, pie slice colors, custom search columns and sort order. + +Signature: + +```typescript +getInput(): Readonly; +``` +Returns: + +`Readonly` + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.iembeddable.getinput_.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.iembeddable.getinput_.md new file mode 100644 index 0000000000000..ad91ad56b3d72 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.iembeddable.getinput_.md @@ -0,0 +1,17 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [IEmbeddable](./kibana-plugin-plugins-embeddable-public.iembeddable.md) > [getInput$](./kibana-plugin-plugins-embeddable-public.iembeddable.getinput_.md) + +## IEmbeddable.getInput$() method + +Returns an observable which will be notified when input state changes. + +Signature: + +```typescript +getInput$(): Readonly>; +``` +Returns: + +`Readonly>` + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.iembeddable.getinspectoradapters.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.iembeddable.getinspectoradapters.md new file mode 100644 index 0000000000000..84b083acac6f4 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.iembeddable.getinspectoradapters.md @@ -0,0 +1,17 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [IEmbeddable](./kibana-plugin-plugins-embeddable-public.iembeddable.md) > [getInspectorAdapters](./kibana-plugin-plugins-embeddable-public.iembeddable.getinspectoradapters.md) + +## IEmbeddable.getInspectorAdapters() method + +An embeddable can return inspector adapters if it wants the inspector to be available via the context menu of that panel. Inspector adapters that will be used to open an inspector for. + +Signature: + +```typescript +getInspectorAdapters(): Adapters | undefined; +``` +Returns: + +`Adapters | undefined` + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.iembeddable.getiscontainer.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.iembeddable.getiscontainer.md new file mode 100644 index 0000000000000..f9bfbbc4ca9bd --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.iembeddable.getiscontainer.md @@ -0,0 +1,17 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [IEmbeddable](./kibana-plugin-plugins-embeddable-public.iembeddable.md) > [getIsContainer](./kibana-plugin-plugins-embeddable-public.iembeddable.getiscontainer.md) + +## IEmbeddable.getIsContainer() method + +A functional representation of the isContainer variable, but helpful for typescript to know the shape if this returns true + +Signature: + +```typescript +getIsContainer(): this is IContainer; +``` +Returns: + +`this is IContainer` + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.iembeddable.getoutput.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.iembeddable.getoutput.md new file mode 100644 index 0000000000000..7e4e4fd3d4329 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.iembeddable.getoutput.md @@ -0,0 +1,21 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [IEmbeddable](./kibana-plugin-plugins-embeddable-public.iembeddable.md) > [getOutput](./kibana-plugin-plugins-embeddable-public.iembeddable.getoutput.md) + +## IEmbeddable.getOutput() method + +Output state is: + +- State that should not change once the embeddable is instantiated, or - State that is derived from the input state, or - State that only the embeddable instance itself knows about, or the factory. + +Examples: editUrl, title taken from a saved object, if your input state was first name and last name, your output state could be greeting. + +Signature: + +```typescript +getOutput(): Readonly; +``` +Returns: + +`Readonly` + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.iembeddable.getoutput_.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.iembeddable.getoutput_.md new file mode 100644 index 0000000000000..11ec3e0d1c8ea --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.iembeddable.getoutput_.md @@ -0,0 +1,17 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [IEmbeddable](./kibana-plugin-plugins-embeddable-public.iembeddable.md) > [getOutput$](./kibana-plugin-plugins-embeddable-public.iembeddable.getoutput_.md) + +## IEmbeddable.getOutput$() method + +Returns an observable which will be notified when output state changes. + +Signature: + +```typescript +getOutput$(): Readonly>; +``` +Returns: + +`Readonly>` + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.iembeddable.getroot.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.iembeddable.getroot.md new file mode 100644 index 0000000000000..eacec168b4d8a --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.iembeddable.getroot.md @@ -0,0 +1,17 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [IEmbeddable](./kibana-plugin-plugins-embeddable-public.iembeddable.md) > [getRoot](./kibana-plugin-plugins-embeddable-public.iembeddable.getroot.md) + +## IEmbeddable.getRoot() method + +Returns the top most parent embeddable, or itself if this embeddable is not within a parent. + +Signature: + +```typescript +getRoot(): IEmbeddable | IContainer; +``` +Returns: + +`IEmbeddable | IContainer` + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.iembeddable.gettitle.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.iembeddable.gettitle.md new file mode 100644 index 0000000000000..eed80882f4b93 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.iembeddable.gettitle.md @@ -0,0 +1,17 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [IEmbeddable](./kibana-plugin-plugins-embeddable-public.iembeddable.md) > [getTitle](./kibana-plugin-plugins-embeddable-public.iembeddable.gettitle.md) + +## IEmbeddable.getTitle() method + +Returns the title of this embeddable. + +Signature: + +```typescript +getTitle(): string | undefined; +``` +Returns: + +`string | undefined` + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.iembeddable.id.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.iembeddable.id.md new file mode 100644 index 0000000000000..7d2f5b9c7e71b --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.iembeddable.id.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [IEmbeddable](./kibana-plugin-plugins-embeddable-public.iembeddable.md) > [id](./kibana-plugin-plugins-embeddable-public.iembeddable.id.md) + +## IEmbeddable.id property + +A unique identifier for this embeddable. Mainly only used by containers to map their Panel States to a child embeddable instance. + +Signature: + +```typescript +readonly id: string; +``` diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.iembeddable.iscontainer.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.iembeddable.iscontainer.md new file mode 100644 index 0000000000000..93b910ee6f6a1 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.iembeddable.iscontainer.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [IEmbeddable](./kibana-plugin-plugins-embeddable-public.iembeddable.md) > [isContainer](./kibana-plugin-plugins-embeddable-public.iembeddable.iscontainer.md) + +## IEmbeddable.isContainer property + +Is this embeddable an instance of a Container class, can it contain nested embeddables? + +Signature: + +```typescript +readonly isContainer: boolean; +``` diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.iembeddable.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.iembeddable.md new file mode 100644 index 0000000000000..b3b6f961e56d1 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.iembeddable.md @@ -0,0 +1,41 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [IEmbeddable](./kibana-plugin-plugins-embeddable-public.iembeddable.md) + +## IEmbeddable interface + +Signature: + +```typescript +export interface IEmbeddable +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [enhancements](./kibana-plugin-plugins-embeddable-public.iembeddable.enhancements.md) | object | Extra abilities added to Embeddable by *_enhanced plugins. | +| [id](./kibana-plugin-plugins-embeddable-public.iembeddable.id.md) | string | A unique identifier for this embeddable. Mainly only used by containers to map their Panel States to a child embeddable instance. | +| [isContainer](./kibana-plugin-plugins-embeddable-public.iembeddable.iscontainer.md) | boolean | Is this embeddable an instance of a Container class, can it contain nested embeddables? | +| [parent](./kibana-plugin-plugins-embeddable-public.iembeddable.parent.md) | IContainer | If this embeddable is nested inside a container, this will contain a reference to its parent. | +| [runtimeId](./kibana-plugin-plugins-embeddable-public.iembeddable.runtimeid.md) | number | Unique ID an embeddable is assigned each time it is initialized. This ID is different for different instances of the same embeddable. For example, if the same dashboard is rendered twice on the screen, all embeddable instances will have a unique runtimeId. | +| [type](./kibana-plugin-plugins-embeddable-public.iembeddable.type.md) | string | The type of embeddable, this is what will be used to take a serialized embeddable and find the correct factory for which to create an instance of it. | + +## Methods + +| Method | Description | +| --- | --- | +| [destroy()](./kibana-plugin-plugins-embeddable-public.iembeddable.destroy.md) | Cleans up subscriptions, destroy nodes mounted from calls to render. | +| [getInput()](./kibana-plugin-plugins-embeddable-public.iembeddable.getinput.md) | Get the input used to instantiate this embeddable. The input is a serialized representation of this embeddable instance and can be used to clone or re-instantiate it. Input state:- Can be updated externally - Can change multiple times for a single embeddable instance.Examples: title, pie slice colors, custom search columns and sort order. | +| [getInput$()](./kibana-plugin-plugins-embeddable-public.iembeddable.getinput_.md) | Returns an observable which will be notified when input state changes. | +| [getInspectorAdapters()](./kibana-plugin-plugins-embeddable-public.iembeddable.getinspectoradapters.md) | An embeddable can return inspector adapters if it wants the inspector to be available via the context menu of that panel. Inspector adapters that will be used to open an inspector for. | +| [getIsContainer()](./kibana-plugin-plugins-embeddable-public.iembeddable.getiscontainer.md) | A functional representation of the isContainer variable, but helpful for typescript to know the shape if this returns true | +| [getOutput()](./kibana-plugin-plugins-embeddable-public.iembeddable.getoutput.md) | Output state is:- State that should not change once the embeddable is instantiated, or - State that is derived from the input state, or - State that only the embeddable instance itself knows about, or the factory.Examples: editUrl, title taken from a saved object, if your input state was first name and last name, your output state could be greeting. | +| [getOutput$()](./kibana-plugin-plugins-embeddable-public.iembeddable.getoutput_.md) | Returns an observable which will be notified when output state changes. | +| [getRoot()](./kibana-plugin-plugins-embeddable-public.iembeddable.getroot.md) | Returns the top most parent embeddable, or itself if this embeddable is not within a parent. | +| [getTitle()](./kibana-plugin-plugins-embeddable-public.iembeddable.gettitle.md) | Returns the title of this embeddable. | +| [reload()](./kibana-plugin-plugins-embeddable-public.iembeddable.reload.md) | Reload the embeddable so output and rendering is up to date. Especially relevant if the embeddable takes relative time as input (e.g. now to now-15) | +| [render(domNode)](./kibana-plugin-plugins-embeddable-public.iembeddable.render.md) | Renders the embeddable at the given node. | +| [supportedTriggers()](./kibana-plugin-plugins-embeddable-public.iembeddable.supportedtriggers.md) | List of triggers that this embeddable will execute. | +| [updateInput(changes)](./kibana-plugin-plugins-embeddable-public.iembeddable.updateinput.md) | Updates input state with the given changes. | + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.iembeddable.parent.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.iembeddable.parent.md new file mode 100644 index 0000000000000..d20102902cdb0 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.iembeddable.parent.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [IEmbeddable](./kibana-plugin-plugins-embeddable-public.iembeddable.md) > [parent](./kibana-plugin-plugins-embeddable-public.iembeddable.parent.md) + +## IEmbeddable.parent property + +If this embeddable is nested inside a container, this will contain a reference to its parent. + +Signature: + +```typescript +readonly parent?: IContainer; +``` diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.iembeddable.reload.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.iembeddable.reload.md new file mode 100644 index 0000000000000..8caea9d8dc511 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.iembeddable.reload.md @@ -0,0 +1,17 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [IEmbeddable](./kibana-plugin-plugins-embeddable-public.iembeddable.md) > [reload](./kibana-plugin-plugins-embeddable-public.iembeddable.reload.md) + +## IEmbeddable.reload() method + +Reload the embeddable so output and rendering is up to date. Especially relevant if the embeddable takes relative time as input (e.g. now to now-15) + +Signature: + +```typescript +reload(): void; +``` +Returns: + +`void` + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.iembeddable.render.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.iembeddable.render.md new file mode 100644 index 0000000000000..9079227b622dc --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.iembeddable.render.md @@ -0,0 +1,24 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [IEmbeddable](./kibana-plugin-plugins-embeddable-public.iembeddable.md) > [render](./kibana-plugin-plugins-embeddable-public.iembeddable.render.md) + +## IEmbeddable.render() method + +Renders the embeddable at the given node. + +Signature: + +```typescript +render(domNode: HTMLElement | Element): void; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| domNode | HTMLElement | Element | | + +Returns: + +`void` + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.iembeddable.runtimeid.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.iembeddable.runtimeid.md new file mode 100644 index 0000000000000..5ddd8ddd0f8dd --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.iembeddable.runtimeid.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [IEmbeddable](./kibana-plugin-plugins-embeddable-public.iembeddable.md) > [runtimeId](./kibana-plugin-plugins-embeddable-public.iembeddable.runtimeid.md) + +## IEmbeddable.runtimeId property + +Unique ID an embeddable is assigned each time it is initialized. This ID is different for different instances of the same embeddable. For example, if the same dashboard is rendered twice on the screen, all embeddable instances will have a unique `runtimeId`. + +Signature: + +```typescript +readonly runtimeId?: number; +``` diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.iembeddable.supportedtriggers.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.iembeddable.supportedtriggers.md new file mode 100644 index 0000000000000..5480f3b246648 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.iembeddable.supportedtriggers.md @@ -0,0 +1,17 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [IEmbeddable](./kibana-plugin-plugins-embeddable-public.iembeddable.md) > [supportedTriggers](./kibana-plugin-plugins-embeddable-public.iembeddable.supportedtriggers.md) + +## IEmbeddable.supportedTriggers() method + +List of triggers that this embeddable will execute. + +Signature: + +```typescript +supportedTriggers(): Array; +``` +Returns: + +`Array` + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.iembeddable.type.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.iembeddable.type.md new file mode 100644 index 0000000000000..46b9d40685dba --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.iembeddable.type.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [IEmbeddable](./kibana-plugin-plugins-embeddable-public.iembeddable.md) > [type](./kibana-plugin-plugins-embeddable-public.iembeddable.type.md) + +## IEmbeddable.type property + +The type of embeddable, this is what will be used to take a serialized embeddable and find the correct factory for which to create an instance of it. + +Signature: + +```typescript +readonly type: string; +``` diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.iembeddable.updateinput.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.iembeddable.updateinput.md new file mode 100644 index 0000000000000..523464103bd1a --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.iembeddable.updateinput.md @@ -0,0 +1,24 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [IEmbeddable](./kibana-plugin-plugins-embeddable-public.iembeddable.md) > [updateInput](./kibana-plugin-plugins-embeddable-public.iembeddable.updateinput.md) + +## IEmbeddable.updateInput() method + +Updates input state with the given changes. + +Signature: + +```typescript +updateInput(changes: Partial): void; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| changes | Partial<I> | | + +Returns: + +`void` + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.iserrorembeddable.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.iserrorembeddable.md new file mode 100644 index 0000000000000..358d085ea9bba --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.iserrorembeddable.md @@ -0,0 +1,22 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [isErrorEmbeddable](./kibana-plugin-plugins-embeddable-public.iserrorembeddable.md) + +## isErrorEmbeddable() function + +Signature: + +```typescript +export declare function isErrorEmbeddable(embeddable: TEmbeddable | ErrorEmbeddable): embeddable is ErrorEmbeddable; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| embeddable | TEmbeddable | ErrorEmbeddable | | + +Returns: + +`embeddable is ErrorEmbeddable` + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.israngeselecttriggercontext.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.israngeselecttriggercontext.md new file mode 100644 index 0000000000000..cd28494fe3a09 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.israngeselecttriggercontext.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [isRangeSelectTriggerContext](./kibana-plugin-plugins-embeddable-public.israngeselecttriggercontext.md) + +## isRangeSelectTriggerContext variable + +Signature: + +```typescript +isRangeSelectTriggerContext: (context: ChartActionContext) => context is RangeSelectContext> +``` diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.isreferenceorvalueembeddable.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.isreferenceorvalueembeddable.md new file mode 100644 index 0000000000000..26a221d929ce6 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.isreferenceorvalueembeddable.md @@ -0,0 +1,22 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [isReferenceOrValueEmbeddable](./kibana-plugin-plugins-embeddable-public.isreferenceorvalueembeddable.md) + +## isReferenceOrValueEmbeddable() function + +Signature: + +```typescript +export declare function isReferenceOrValueEmbeddable(incoming: unknown): incoming is ReferenceOrValueEmbeddable; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| incoming | unknown | | + +Returns: + +`incoming is ReferenceOrValueEmbeddable` + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.issavedobjectembeddableinput.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.issavedobjectembeddableinput.md new file mode 100644 index 0000000000000..663cc41f1bffc --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.issavedobjectembeddableinput.md @@ -0,0 +1,22 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [isSavedObjectEmbeddableInput](./kibana-plugin-plugins-embeddable-public.issavedobjectembeddableinput.md) + +## isSavedObjectEmbeddableInput() function + +Signature: + +```typescript +export declare function isSavedObjectEmbeddableInput(input: EmbeddableInput | SavedObjectEmbeddableInput): input is SavedObjectEmbeddableInput; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| input | EmbeddableInput | SavedObjectEmbeddableInput | | + +Returns: + +`input is SavedObjectEmbeddableInput` + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.isvalueclicktriggercontext.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.isvalueclicktriggercontext.md new file mode 100644 index 0000000000000..4e3c970d9b437 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.isvalueclicktriggercontext.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [isValueClickTriggerContext](./kibana-plugin-plugins-embeddable-public.isvalueclicktriggercontext.md) + +## isValueClickTriggerContext variable + +Signature: + +```typescript +isValueClickTriggerContext: (context: ChartActionContext) => context is ValueClickContext> +``` diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.md new file mode 100644 index 0000000000000..df67eda5074b9 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.md @@ -0,0 +1,97 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) + +## kibana-plugin-plugins-embeddable-public package + +## Classes + +| Class | Description | +| --- | --- | +| [AddPanelAction](./kibana-plugin-plugins-embeddable-public.addpanelaction.md) | | +| [AttributeService](./kibana-plugin-plugins-embeddable-public.attributeservice.md) | | +| [Container](./kibana-plugin-plugins-embeddable-public.container.md) | | +| [EditPanelAction](./kibana-plugin-plugins-embeddable-public.editpanelaction.md) | | +| [Embeddable](./kibana-plugin-plugins-embeddable-public.embeddable.md) | | +| [EmbeddableChildPanel](./kibana-plugin-plugins-embeddable-public.embeddablechildpanel.md) | This component can be used by embeddable containers using react to easily render children. It waits for the child to be initialized, showing a loading indicator until that is complete. | +| [EmbeddableFactoryNotFoundError](./kibana-plugin-plugins-embeddable-public.embeddablefactorynotfounderror.md) | | +| [EmbeddablePanel](./kibana-plugin-plugins-embeddable-public.embeddablepanel.md) | | +| [EmbeddableRoot](./kibana-plugin-plugins-embeddable-public.embeddableroot.md) | | +| [EmbeddableStateTransfer](./kibana-plugin-plugins-embeddable-public.embeddablestatetransfer.md) | A wrapper around the state object in which provides strongly typed helper methods for common incoming and outgoing states used by the embeddable infrastructure. | +| [ErrorEmbeddable](./kibana-plugin-plugins-embeddable-public.errorembeddable.md) | | +| [PanelNotFoundError](./kibana-plugin-plugins-embeddable-public.panelnotfounderror.md) | | + +## Enumerations + +| Enumeration | Description | +| --- | --- | +| [ViewMode](./kibana-plugin-plugins-embeddable-public.viewmode.md) | | + +## Functions + +| Function | Description | +| --- | --- | +| [isErrorEmbeddable(embeddable)](./kibana-plugin-plugins-embeddable-public.iserrorembeddable.md) | | +| [isReferenceOrValueEmbeddable(incoming)](./kibana-plugin-plugins-embeddable-public.isreferenceorvalueembeddable.md) | | +| [isSavedObjectEmbeddableInput(input)](./kibana-plugin-plugins-embeddable-public.issavedobjectembeddableinput.md) | | +| [openAddPanelFlyout(options)](./kibana-plugin-plugins-embeddable-public.openaddpanelflyout.md) | | +| [plugin(initializerContext)](./kibana-plugin-plugins-embeddable-public.plugin.md) | | + +## Interfaces + +| Interface | Description | +| --- | --- | +| [Adapters](./kibana-plugin-plugins-embeddable-public.adapters.md) | The interface that the adapters used to open an inspector have to fullfill. | +| [ContainerInput](./kibana-plugin-plugins-embeddable-public.containerinput.md) | | +| [ContainerOutput](./kibana-plugin-plugins-embeddable-public.containeroutput.md) | | +| [EmbeddableChildPanelProps](./kibana-plugin-plugins-embeddable-public.embeddablechildpanelprops.md) | | +| [EmbeddableContext](./kibana-plugin-plugins-embeddable-public.embeddablecontext.md) | | +| [EmbeddableEditorState](./kibana-plugin-plugins-embeddable-public.embeddableeditorstate.md) | A state package that contains information an editor will need to create or edit an embeddable then redirect back. | +| [EmbeddableFactory](./kibana-plugin-plugins-embeddable-public.embeddablefactory.md) | EmbeddableFactories create and initialize an embeddable instance | +| [EmbeddableInstanceConfiguration](./kibana-plugin-plugins-embeddable-public.embeddableinstanceconfiguration.md) | | +| [EmbeddableOutput](./kibana-plugin-plugins-embeddable-public.embeddableoutput.md) | | +| [EmbeddablePackageState](./kibana-plugin-plugins-embeddable-public.embeddablepackagestate.md) | A state package that contains all fields necessary to create or update an embeddable by reference or by value in a container. | +| [EmbeddableSetup](./kibana-plugin-plugins-embeddable-public.embeddablesetup.md) | | +| [EmbeddableSetupDependencies](./kibana-plugin-plugins-embeddable-public.embeddablesetupdependencies.md) | | +| [EmbeddableStart](./kibana-plugin-plugins-embeddable-public.embeddablestart.md) | | +| [EmbeddableStartDependencies](./kibana-plugin-plugins-embeddable-public.embeddablestartdependencies.md) | | +| [EnhancementRegistryDefinition](./kibana-plugin-plugins-embeddable-public.enhancementregistrydefinition.md) | | +| [IContainer](./kibana-plugin-plugins-embeddable-public.icontainer.md) | | +| [IEmbeddable](./kibana-plugin-plugins-embeddable-public.iembeddable.md) | | +| [OutputSpec](./kibana-plugin-plugins-embeddable-public.outputspec.md) | | +| [PanelState](./kibana-plugin-plugins-embeddable-public.panelstate.md) | | +| [PropertySpec](./kibana-plugin-plugins-embeddable-public.propertyspec.md) | | +| [RangeSelectContext](./kibana-plugin-plugins-embeddable-public.rangeselectcontext.md) | | +| [ReferenceOrValueEmbeddable](./kibana-plugin-plugins-embeddable-public.referenceorvalueembeddable.md) | Any embeddable that implements this interface will be able to use input that is either by reference (backed by a saved object) OR by value, (provided by the container). | +| [SavedObjectEmbeddableInput](./kibana-plugin-plugins-embeddable-public.savedobjectembeddableinput.md) | | +| [ValueClickContext](./kibana-plugin-plugins-embeddable-public.valueclickcontext.md) | | + +## Variables + +| Variable | Description | +| --- | --- | +| [ACTION\_ADD\_PANEL](./kibana-plugin-plugins-embeddable-public.action_add_panel.md) | | +| [ACTION\_EDIT\_PANEL](./kibana-plugin-plugins-embeddable-public.action_edit_panel.md) | | +| [ATTRIBUTE\_SERVICE\_KEY](./kibana-plugin-plugins-embeddable-public.attribute_service_key.md) | The attribute service is a shared, generic service that embeddables can use to provide the functionality required to fulfill the requirements of the ReferenceOrValueEmbeddable interface. The attribute\_service can also be used as a higher level wrapper to transform an embeddable input shape that references a saved object into an embeddable input shape that contains that saved object's attributes by value. | +| [CONTEXT\_MENU\_TRIGGER](./kibana-plugin-plugins-embeddable-public.context_menu_trigger.md) | | +| [contextMenuTrigger](./kibana-plugin-plugins-embeddable-public.contextmenutrigger.md) | | +| [defaultEmbeddableFactoryProvider](./kibana-plugin-plugins-embeddable-public.defaultembeddablefactoryprovider.md) | | +| [EmbeddableRenderer](./kibana-plugin-plugins-embeddable-public.embeddablerenderer.md) | Helper react component to render an embeddable Can be used if you have an embeddable object or an embeddable factory Supports updating input by passing input prop | +| [isRangeSelectTriggerContext](./kibana-plugin-plugins-embeddable-public.israngeselecttriggercontext.md) | | +| [isValueClickTriggerContext](./kibana-plugin-plugins-embeddable-public.isvalueclicktriggercontext.md) | | +| [PANEL\_BADGE\_TRIGGER](./kibana-plugin-plugins-embeddable-public.panel_badge_trigger.md) | | +| [PANEL\_NOTIFICATION\_TRIGGER](./kibana-plugin-plugins-embeddable-public.panel_notification_trigger.md) | | +| [panelBadgeTrigger](./kibana-plugin-plugins-embeddable-public.panelbadgetrigger.md) | | +| [panelNotificationTrigger](./kibana-plugin-plugins-embeddable-public.panelnotificationtrigger.md) | | +| [withEmbeddableSubscription](./kibana-plugin-plugins-embeddable-public.withembeddablesubscription.md) | | + +## Type Aliases + +| Type Alias | Description | +| --- | --- | +| [ChartActionContext](./kibana-plugin-plugins-embeddable-public.chartactioncontext.md) | | +| [EmbeddableFactoryDefinition](./kibana-plugin-plugins-embeddable-public.embeddablefactorydefinition.md) | | +| [EmbeddableInput](./kibana-plugin-plugins-embeddable-public.embeddableinput.md) | | +| [EmbeddablePanelHOC](./kibana-plugin-plugins-embeddable-public.embeddablepanelhoc.md) | | +| [EmbeddableRendererProps](./kibana-plugin-plugins-embeddable-public.embeddablerendererprops.md) | This type is a publicly exposed props of [EmbeddableRenderer](./kibana-plugin-plugins-embeddable-public.embeddablerenderer.md) Union is used to validate that or factory or embeddable is passed in, but it can't be both simultaneously In case when embeddable is passed in, input is optional, because there is already an input inside of embeddable object In case when factory is used, then input is required, because it will be used as initial input to create an embeddable object | + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.openaddpanelflyout.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.openaddpanelflyout.md new file mode 100644 index 0000000000000..ce97f79b4beb9 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.openaddpanelflyout.md @@ -0,0 +1,29 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [openAddPanelFlyout](./kibana-plugin-plugins-embeddable-public.openaddpanelflyout.md) + +## openAddPanelFlyout() function + +Signature: + +```typescript +export declare function openAddPanelFlyout(options: { + embeddable: IContainer; + getFactory: EmbeddableStart['getEmbeddableFactory']; + getAllFactories: EmbeddableStart['getEmbeddableFactories']; + overlays: OverlayStart; + notifications: NotificationsStart; + SavedObjectFinder: React.ComponentType; +}): Promise; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| options | {
embeddable: IContainer;
getFactory: EmbeddableStart['getEmbeddableFactory'];
getAllFactories: EmbeddableStart['getEmbeddableFactories'];
overlays: OverlayStart;
notifications: NotificationsStart;
SavedObjectFinder: React.ComponentType<any>;
} | | + +Returns: + +`Promise` + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.outputspec.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.outputspec.md new file mode 100644 index 0000000000000..eead69b4e487c --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.outputspec.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [OutputSpec](./kibana-plugin-plugins-embeddable-public.outputspec.md) + +## OutputSpec interface + +Signature: + +```typescript +export interface OutputSpec +``` diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.panel_badge_trigger.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.panel_badge_trigger.md new file mode 100644 index 0000000000000..d5032d98ef4aa --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.panel_badge_trigger.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [PANEL\_BADGE\_TRIGGER](./kibana-plugin-plugins-embeddable-public.panel_badge_trigger.md) + +## PANEL\_BADGE\_TRIGGER variable + +Signature: + +```typescript +PANEL_BADGE_TRIGGER = "PANEL_BADGE_TRIGGER" +``` diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.panel_notification_trigger.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.panel_notification_trigger.md new file mode 100644 index 0000000000000..cd8a4a1ca4581 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.panel_notification_trigger.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [PANEL\_NOTIFICATION\_TRIGGER](./kibana-plugin-plugins-embeddable-public.panel_notification_trigger.md) + +## PANEL\_NOTIFICATION\_TRIGGER variable + +Signature: + +```typescript +PANEL_NOTIFICATION_TRIGGER = "PANEL_NOTIFICATION_TRIGGER" +``` diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.panelbadgetrigger.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.panelbadgetrigger.md new file mode 100644 index 0000000000000..f6113c93a1c66 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.panelbadgetrigger.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [panelBadgeTrigger](./kibana-plugin-plugins-embeddable-public.panelbadgetrigger.md) + +## panelBadgeTrigger variable + +Signature: + +```typescript +panelBadgeTrigger: Trigger<'PANEL_BADGE_TRIGGER'> +``` diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.panelnotfounderror._constructor_.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.panelnotfounderror._constructor_.md new file mode 100644 index 0000000000000..d1704403b2336 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.panelnotfounderror._constructor_.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [PanelNotFoundError](./kibana-plugin-plugins-embeddable-public.panelnotfounderror.md) > [(constructor)](./kibana-plugin-plugins-embeddable-public.panelnotfounderror._constructor_.md) + +## PanelNotFoundError.(constructor) + +Constructs a new instance of the `PanelNotFoundError` class + +Signature: + +```typescript +constructor(); +``` diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.panelnotfounderror.code.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.panelnotfounderror.code.md new file mode 100644 index 0000000000000..d169fb97480cc --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.panelnotfounderror.code.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [PanelNotFoundError](./kibana-plugin-plugins-embeddable-public.panelnotfounderror.md) > [code](./kibana-plugin-plugins-embeddable-public.panelnotfounderror.code.md) + +## PanelNotFoundError.code property + +Signature: + +```typescript +code: string; +``` diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.panelnotfounderror.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.panelnotfounderror.md new file mode 100644 index 0000000000000..2191fdecf1ac5 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.panelnotfounderror.md @@ -0,0 +1,24 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [PanelNotFoundError](./kibana-plugin-plugins-embeddable-public.panelnotfounderror.md) + +## PanelNotFoundError class + +Signature: + +```typescript +export declare class PanelNotFoundError extends Error +``` + +## Constructors + +| Constructor | Modifiers | Description | +| --- | --- | --- | +| [(constructor)()](./kibana-plugin-plugins-embeddable-public.panelnotfounderror._constructor_.md) | | Constructs a new instance of the PanelNotFoundError class | + +## Properties + +| Property | Modifiers | Type | Description | +| --- | --- | --- | --- | +| [code](./kibana-plugin-plugins-embeddable-public.panelnotfounderror.code.md) | | string | | + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.panelnotificationtrigger.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.panelnotificationtrigger.md new file mode 100644 index 0000000000000..df606c11f64ce --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.panelnotificationtrigger.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [panelNotificationTrigger](./kibana-plugin-plugins-embeddable-public.panelnotificationtrigger.md) + +## panelNotificationTrigger variable + +Signature: + +```typescript +panelNotificationTrigger: Trigger<'PANEL_NOTIFICATION_TRIGGER'> +``` diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.panelstate.explicitinput.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.panelstate.explicitinput.md new file mode 100644 index 0000000000000..16123958d4db1 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.panelstate.explicitinput.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [PanelState](./kibana-plugin-plugins-embeddable-public.panelstate.md) > [explicitInput](./kibana-plugin-plugins-embeddable-public.panelstate.explicitinput.md) + +## PanelState.explicitInput property + +Signature: + +```typescript +explicitInput: Partial & { + id: string; + }; +``` diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.panelstate.id.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.panelstate.id.md new file mode 100644 index 0000000000000..e6fd4e0264f0d --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.panelstate.id.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [PanelState](./kibana-plugin-plugins-embeddable-public.panelstate.md) > [id](./kibana-plugin-plugins-embeddable-public.panelstate.id.md) + +## PanelState.id property + +Signature: + +```typescript +id: string; +``` diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.panelstate.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.panelstate.md new file mode 100644 index 0000000000000..b37f652b5021c --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.panelstate.md @@ -0,0 +1,24 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [PanelState](./kibana-plugin-plugins-embeddable-public.panelstate.md) + +## PanelState interface + +Signature: + +```typescript +export interface PanelState +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [explicitInput](./kibana-plugin-plugins-embeddable-public.panelstate.explicitinput.md) | Partial<E> & {
id: string;
} | | +| [id](./kibana-plugin-plugins-embeddable-public.panelstate.id.md) | string | | +| [type](./kibana-plugin-plugins-embeddable-public.panelstate.type.md) | string | | + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.panelstate.type.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.panelstate.type.md new file mode 100644 index 0000000000000..8be470a77f1c7 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.panelstate.type.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [PanelState](./kibana-plugin-plugins-embeddable-public.panelstate.md) > [type](./kibana-plugin-plugins-embeddable-public.panelstate.type.md) + +## PanelState.type property + +Signature: + +```typescript +type: string; +``` diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.plugin.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.plugin.md new file mode 100644 index 0000000000000..4e3ae760153cb --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.plugin.md @@ -0,0 +1,22 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [plugin](./kibana-plugin-plugins-embeddable-public.plugin.md) + +## plugin() function + +Signature: + +```typescript +export declare function plugin(initializerContext: PluginInitializerContext): EmbeddablePublicPlugin; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| initializerContext | PluginInitializerContext | | + +Returns: + +`EmbeddablePublicPlugin` + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.propertyspec.accesspath.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.propertyspec.accesspath.md new file mode 100644 index 0000000000000..2a337e4b0141a --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.propertyspec.accesspath.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [PropertySpec](./kibana-plugin-plugins-embeddable-public.propertyspec.md) > [accessPath](./kibana-plugin-plugins-embeddable-public.propertyspec.accesspath.md) + +## PropertySpec.accessPath property + +Signature: + +```typescript +accessPath: string; +``` diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.propertyspec.description.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.propertyspec.description.md new file mode 100644 index 0000000000000..f36309c657795 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.propertyspec.description.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [PropertySpec](./kibana-plugin-plugins-embeddable-public.propertyspec.md) > [description](./kibana-plugin-plugins-embeddable-public.propertyspec.description.md) + +## PropertySpec.description property + +Signature: + +```typescript +description: string; +``` diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.propertyspec.displayname.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.propertyspec.displayname.md new file mode 100644 index 0000000000000..16311493fa5dd --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.propertyspec.displayname.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [PropertySpec](./kibana-plugin-plugins-embeddable-public.propertyspec.md) > [displayName](./kibana-plugin-plugins-embeddable-public.propertyspec.displayname.md) + +## PropertySpec.displayName property + +Signature: + +```typescript +displayName: string; +``` diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.propertyspec.id.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.propertyspec.id.md new file mode 100644 index 0000000000000..a37ed9000b67a --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.propertyspec.id.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [PropertySpec](./kibana-plugin-plugins-embeddable-public.propertyspec.md) > [id](./kibana-plugin-plugins-embeddable-public.propertyspec.id.md) + +## PropertySpec.id property + +Signature: + +```typescript +id: string; +``` diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.propertyspec.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.propertyspec.md new file mode 100644 index 0000000000000..02534b5d9d4da --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.propertyspec.md @@ -0,0 +1,22 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [PropertySpec](./kibana-plugin-plugins-embeddable-public.propertyspec.md) + +## PropertySpec interface + +Signature: + +```typescript +export interface PropertySpec +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [accessPath](./kibana-plugin-plugins-embeddable-public.propertyspec.accesspath.md) | string | | +| [description](./kibana-plugin-plugins-embeddable-public.propertyspec.description.md) | string | | +| [displayName](./kibana-plugin-plugins-embeddable-public.propertyspec.displayname.md) | string | | +| [id](./kibana-plugin-plugins-embeddable-public.propertyspec.id.md) | string | | +| [value](./kibana-plugin-plugins-embeddable-public.propertyspec.value.md) | string | | + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.propertyspec.value.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.propertyspec.value.md new file mode 100644 index 0000000000000..3360a9fff783c --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.propertyspec.value.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [PropertySpec](./kibana-plugin-plugins-embeddable-public.propertyspec.md) > [value](./kibana-plugin-plugins-embeddable-public.propertyspec.value.md) + +## PropertySpec.value property + +Signature: + +```typescript +value?: string; +``` diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.rangeselectcontext.data.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.rangeselectcontext.data.md new file mode 100644 index 0000000000000..6d2774d86f109 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.rangeselectcontext.data.md @@ -0,0 +1,16 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [RangeSelectContext](./kibana-plugin-plugins-embeddable-public.rangeselectcontext.md) > [data](./kibana-plugin-plugins-embeddable-public.rangeselectcontext.data.md) + +## RangeSelectContext.data property + +Signature: + +```typescript +data: { + table: KibanaDatatable; + column: number; + range: number[]; + timeFieldName?: string; + }; +``` diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.rangeselectcontext.embeddable.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.rangeselectcontext.embeddable.md new file mode 100644 index 0000000000000..a6c9f0f7e4253 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.rangeselectcontext.embeddable.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [RangeSelectContext](./kibana-plugin-plugins-embeddable-public.rangeselectcontext.md) > [embeddable](./kibana-plugin-plugins-embeddable-public.rangeselectcontext.embeddable.md) + +## RangeSelectContext.embeddable property + +Signature: + +```typescript +embeddable?: T; +``` diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.rangeselectcontext.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.rangeselectcontext.md new file mode 100644 index 0000000000000..0f92ed86301da --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.rangeselectcontext.md @@ -0,0 +1,19 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [RangeSelectContext](./kibana-plugin-plugins-embeddable-public.rangeselectcontext.md) + +## RangeSelectContext interface + +Signature: + +```typescript +export interface RangeSelectContext +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [data](./kibana-plugin-plugins-embeddable-public.rangeselectcontext.data.md) | {
table: KibanaDatatable;
column: number;
range: number[];
timeFieldName?: string;
} | | +| [embeddable](./kibana-plugin-plugins-embeddable-public.rangeselectcontext.embeddable.md) | T | | + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.referenceorvalueembeddable.getinputasreftype.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.referenceorvalueembeddable.getinputasreftype.md new file mode 100644 index 0000000000000..559787c75ab66 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.referenceorvalueembeddable.getinputasreftype.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [ReferenceOrValueEmbeddable](./kibana-plugin-plugins-embeddable-public.referenceorvalueembeddable.md) > [getInputAsRefType](./kibana-plugin-plugins-embeddable-public.referenceorvalueembeddable.getinputasreftype.md) + +## ReferenceOrValueEmbeddable.getInputAsRefType property + +Gets the embeddable's current input as its Reference type + +Signature: + +```typescript +getInputAsRefType: () => Promise; +``` diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.referenceorvalueembeddable.getinputasvaluetype.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.referenceorvalueembeddable.getinputasvaluetype.md new file mode 100644 index 0000000000000..f9cd23b97858a --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.referenceorvalueembeddable.getinputasvaluetype.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [ReferenceOrValueEmbeddable](./kibana-plugin-plugins-embeddable-public.referenceorvalueembeddable.md) > [getInputAsValueType](./kibana-plugin-plugins-embeddable-public.referenceorvalueembeddable.getinputasvaluetype.md) + +## ReferenceOrValueEmbeddable.getInputAsValueType property + +Gets the embeddable's current input as its Value type + +Signature: + +```typescript +getInputAsValueType: () => Promise; +``` diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.referenceorvalueembeddable.inputisreftype.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.referenceorvalueembeddable.inputisreftype.md new file mode 100644 index 0000000000000..9de0447769397 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.referenceorvalueembeddable.inputisreftype.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [ReferenceOrValueEmbeddable](./kibana-plugin-plugins-embeddable-public.referenceorvalueembeddable.md) > [inputIsRefType](./kibana-plugin-plugins-embeddable-public.referenceorvalueembeddable.inputisreftype.md) + +## ReferenceOrValueEmbeddable.inputIsRefType property + +determines whether the input is by value or by reference. + +Signature: + +```typescript +inputIsRefType: (input: ValTypeInput | RefTypeInput) => input is RefTypeInput; +``` diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.referenceorvalueembeddable.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.referenceorvalueembeddable.md new file mode 100644 index 0000000000000..47d6d8a0772d8 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.referenceorvalueembeddable.md @@ -0,0 +1,22 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [ReferenceOrValueEmbeddable](./kibana-plugin-plugins-embeddable-public.referenceorvalueembeddable.md) + +## ReferenceOrValueEmbeddable interface + +Any embeddable that implements this interface will be able to use input that is either by reference (backed by a saved object) OR by value, (provided by the container). + +Signature: + +```typescript +export interface ReferenceOrValueEmbeddable +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [getInputAsRefType](./kibana-plugin-plugins-embeddable-public.referenceorvalueembeddable.getinputasreftype.md) | () => Promise<RefTypeInput> | Gets the embeddable's current input as its Reference type | +| [getInputAsValueType](./kibana-plugin-plugins-embeddable-public.referenceorvalueembeddable.getinputasvaluetype.md) | () => Promise<ValTypeInput> | Gets the embeddable's current input as its Value type | +| [inputIsRefType](./kibana-plugin-plugins-embeddable-public.referenceorvalueembeddable.inputisreftype.md) | (input: ValTypeInput | RefTypeInput) => input is RefTypeInput | determines whether the input is by value or by reference. | + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.savedobjectembeddableinput.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.savedobjectembeddableinput.md new file mode 100644 index 0000000000000..ae0df9ec01ba1 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.savedobjectembeddableinput.md @@ -0,0 +1,18 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [SavedObjectEmbeddableInput](./kibana-plugin-plugins-embeddable-public.savedobjectembeddableinput.md) + +## SavedObjectEmbeddableInput interface + +Signature: + +```typescript +export interface SavedObjectEmbeddableInput extends EmbeddableInput +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [savedObjectId](./kibana-plugin-plugins-embeddable-public.savedobjectembeddableinput.savedobjectid.md) | string | | + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.savedobjectembeddableinput.savedobjectid.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.savedobjectembeddableinput.savedobjectid.md new file mode 100644 index 0000000000000..d8cb3bbda9d01 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.savedobjectembeddableinput.savedobjectid.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [SavedObjectEmbeddableInput](./kibana-plugin-plugins-embeddable-public.savedobjectembeddableinput.md) > [savedObjectId](./kibana-plugin-plugins-embeddable-public.savedobjectembeddableinput.savedobjectid.md) + +## SavedObjectEmbeddableInput.savedObjectId property + +Signature: + +```typescript +savedObjectId: string; +``` diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.valueclickcontext.data.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.valueclickcontext.data.md new file mode 100644 index 0000000000000..92c33affc47a9 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.valueclickcontext.data.md @@ -0,0 +1,20 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [ValueClickContext](./kibana-plugin-plugins-embeddable-public.valueclickcontext.md) > [data](./kibana-plugin-plugins-embeddable-public.valueclickcontext.data.md) + +## ValueClickContext.data property + +Signature: + +```typescript +data: { + data: Array<{ + table: Pick; + column: number; + row: number; + value: any; + }>; + timeFieldName?: string; + negate?: boolean; + }; +``` diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.valueclickcontext.embeddable.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.valueclickcontext.embeddable.md new file mode 100644 index 0000000000000..38adee9346945 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.valueclickcontext.embeddable.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [ValueClickContext](./kibana-plugin-plugins-embeddable-public.valueclickcontext.md) > [embeddable](./kibana-plugin-plugins-embeddable-public.valueclickcontext.embeddable.md) + +## ValueClickContext.embeddable property + +Signature: + +```typescript +embeddable?: T; +``` diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.valueclickcontext.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.valueclickcontext.md new file mode 100644 index 0000000000000..13133095956c6 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.valueclickcontext.md @@ -0,0 +1,19 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [ValueClickContext](./kibana-plugin-plugins-embeddable-public.valueclickcontext.md) + +## ValueClickContext interface + +Signature: + +```typescript +export interface ValueClickContext +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [data](./kibana-plugin-plugins-embeddable-public.valueclickcontext.data.md) | {
data: Array<{
table: Pick<KibanaDatatable, 'rows' | 'columns'>;
column: number;
row: number;
value: any;
}>;
timeFieldName?: string;
negate?: boolean;
} | | +| [embeddable](./kibana-plugin-plugins-embeddable-public.valueclickcontext.embeddable.md) | T | | + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.viewmode.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.viewmode.md new file mode 100644 index 0000000000000..f47169951018d --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.viewmode.md @@ -0,0 +1,19 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [ViewMode](./kibana-plugin-plugins-embeddable-public.viewmode.md) + +## ViewMode enum + +Signature: + +```typescript +export declare enum ViewMode +``` + +## Enumeration Members + +| Member | Value | Description | +| --- | --- | --- | +| EDIT | "edit" | | +| VIEW | "view" | | + diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.withembeddablesubscription.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.withembeddablesubscription.md new file mode 100644 index 0000000000000..a815292f3a0c3 --- /dev/null +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.withembeddablesubscription.md @@ -0,0 +1,17 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [withEmbeddableSubscription](./kibana-plugin-plugins-embeddable-public.withembeddablesubscription.md) + +## withEmbeddableSubscription variable + +Signature: + +```typescript +withEmbeddableSubscription: = IEmbeddable, ExtraProps = {}>(WrappedComponent: React.ComponentType<{ + input: I; + output: O; + embeddable: E; +} & ExtraProps>) => React.ComponentType<{ + embeddable: E; +} & ExtraProps> +``` diff --git a/docs/development/plugins/embeddable/server/index.md b/docs/development/plugins/embeddable/server/index.md new file mode 100644 index 0000000000000..3c4d4ce3aed36 --- /dev/null +++ b/docs/development/plugins/embeddable/server/index.md @@ -0,0 +1,12 @@ + + +[Home](./index.md) + +## API Reference + +## Packages + +| Package | Description | +| --- | --- | +| [kibana-plugin-plugins-embeddable-server](./kibana-plugin-plugins-embeddable-server.md) | | + diff --git a/docs/development/plugins/embeddable/server/kibana-plugin-plugins-embeddable-server.embeddableregistrydefinition.id.md b/docs/development/plugins/embeddable/server/kibana-plugin-plugins-embeddable-server.embeddableregistrydefinition.id.md new file mode 100644 index 0000000000000..ce3e532fcaa3b --- /dev/null +++ b/docs/development/plugins/embeddable/server/kibana-plugin-plugins-embeddable-server.embeddableregistrydefinition.id.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-server](./kibana-plugin-plugins-embeddable-server.md) > [EmbeddableRegistryDefinition](./kibana-plugin-plugins-embeddable-server.embeddableregistrydefinition.md) > [id](./kibana-plugin-plugins-embeddable-server.embeddableregistrydefinition.id.md) + +## EmbeddableRegistryDefinition.id property + +Signature: + +```typescript +id: string; +``` diff --git a/docs/development/plugins/embeddable/server/kibana-plugin-plugins-embeddable-server.embeddableregistrydefinition.md b/docs/development/plugins/embeddable/server/kibana-plugin-plugins-embeddable-server.embeddableregistrydefinition.md new file mode 100644 index 0000000000000..de46d91d90c65 --- /dev/null +++ b/docs/development/plugins/embeddable/server/kibana-plugin-plugins-embeddable-server.embeddableregistrydefinition.md @@ -0,0 +1,18 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-server](./kibana-plugin-plugins-embeddable-server.md) > [EmbeddableRegistryDefinition](./kibana-plugin-plugins-embeddable-server.embeddableregistrydefinition.md) + +## EmbeddableRegistryDefinition interface + +Signature: + +```typescript +export interface EmbeddableRegistryDefinition

extends PersistableStateDefinition

+``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [id](./kibana-plugin-plugins-embeddable-server.embeddableregistrydefinition.id.md) | string | | + diff --git a/docs/development/plugins/embeddable/server/kibana-plugin-plugins-embeddable-server.embeddablesetup.getattributeservice.md b/docs/development/plugins/embeddable/server/kibana-plugin-plugins-embeddable-server.embeddablesetup.getattributeservice.md new file mode 100644 index 0000000000000..9cd77ca6e3a36 --- /dev/null +++ b/docs/development/plugins/embeddable/server/kibana-plugin-plugins-embeddable-server.embeddablesetup.getattributeservice.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-server](./kibana-plugin-plugins-embeddable-server.md) > [EmbeddableSetup](./kibana-plugin-plugins-embeddable-server.embeddablesetup.md) > [getAttributeService](./kibana-plugin-plugins-embeddable-server.embeddablesetup.getattributeservice.md) + +## EmbeddableSetup.getAttributeService property + +Signature: + +```typescript +getAttributeService: any; +``` diff --git a/docs/development/plugins/embeddable/server/kibana-plugin-plugins-embeddable-server.embeddablesetup.md b/docs/development/plugins/embeddable/server/kibana-plugin-plugins-embeddable-server.embeddablesetup.md new file mode 100644 index 0000000000000..bd024095e80be --- /dev/null +++ b/docs/development/plugins/embeddable/server/kibana-plugin-plugins-embeddable-server.embeddablesetup.md @@ -0,0 +1,20 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-server](./kibana-plugin-plugins-embeddable-server.md) > [EmbeddableSetup](./kibana-plugin-plugins-embeddable-server.embeddablesetup.md) + +## EmbeddableSetup interface + +Signature: + +```typescript +export interface EmbeddableSetup +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [getAttributeService](./kibana-plugin-plugins-embeddable-server.embeddablesetup.getattributeservice.md) | any | | +| [registerEmbeddableFactory](./kibana-plugin-plugins-embeddable-server.embeddablesetup.registerembeddablefactory.md) | (factory: EmbeddableRegistryDefinition) => void | | +| [registerEnhancement](./kibana-plugin-plugins-embeddable-server.embeddablesetup.registerenhancement.md) | (enhancement: EnhancementRegistryDefinition) => void | | + diff --git a/docs/development/plugins/embeddable/server/kibana-plugin-plugins-embeddable-server.embeddablesetup.registerembeddablefactory.md b/docs/development/plugins/embeddable/server/kibana-plugin-plugins-embeddable-server.embeddablesetup.registerembeddablefactory.md new file mode 100644 index 0000000000000..442941ce86950 --- /dev/null +++ b/docs/development/plugins/embeddable/server/kibana-plugin-plugins-embeddable-server.embeddablesetup.registerembeddablefactory.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-server](./kibana-plugin-plugins-embeddable-server.md) > [EmbeddableSetup](./kibana-plugin-plugins-embeddable-server.embeddablesetup.md) > [registerEmbeddableFactory](./kibana-plugin-plugins-embeddable-server.embeddablesetup.registerembeddablefactory.md) + +## EmbeddableSetup.registerEmbeddableFactory property + +Signature: + +```typescript +registerEmbeddableFactory: (factory: EmbeddableRegistryDefinition) => void; +``` diff --git a/docs/development/plugins/embeddable/server/kibana-plugin-plugins-embeddable-server.embeddablesetup.registerenhancement.md b/docs/development/plugins/embeddable/server/kibana-plugin-plugins-embeddable-server.embeddablesetup.registerenhancement.md new file mode 100644 index 0000000000000..9ea2846d0300b --- /dev/null +++ b/docs/development/plugins/embeddable/server/kibana-plugin-plugins-embeddable-server.embeddablesetup.registerenhancement.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-server](./kibana-plugin-plugins-embeddable-server.md) > [EmbeddableSetup](./kibana-plugin-plugins-embeddable-server.embeddablesetup.md) > [registerEnhancement](./kibana-plugin-plugins-embeddable-server.embeddablesetup.registerenhancement.md) + +## EmbeddableSetup.registerEnhancement property + +Signature: + +```typescript +registerEnhancement: (enhancement: EnhancementRegistryDefinition) => void; +``` diff --git a/docs/development/plugins/embeddable/server/kibana-plugin-plugins-embeddable-server.enhancementregistrydefinition.id.md b/docs/development/plugins/embeddable/server/kibana-plugin-plugins-embeddable-server.enhancementregistrydefinition.id.md new file mode 100644 index 0000000000000..a93c691246872 --- /dev/null +++ b/docs/development/plugins/embeddable/server/kibana-plugin-plugins-embeddable-server.enhancementregistrydefinition.id.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-server](./kibana-plugin-plugins-embeddable-server.md) > [EnhancementRegistryDefinition](./kibana-plugin-plugins-embeddable-server.enhancementregistrydefinition.md) > [id](./kibana-plugin-plugins-embeddable-server.enhancementregistrydefinition.id.md) + +## EnhancementRegistryDefinition.id property + +Signature: + +```typescript +id: string; +``` diff --git a/docs/development/plugins/embeddable/server/kibana-plugin-plugins-embeddable-server.enhancementregistrydefinition.md b/docs/development/plugins/embeddable/server/kibana-plugin-plugins-embeddable-server.enhancementregistrydefinition.md new file mode 100644 index 0000000000000..09ff48a92158d --- /dev/null +++ b/docs/development/plugins/embeddable/server/kibana-plugin-plugins-embeddable-server.enhancementregistrydefinition.md @@ -0,0 +1,18 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-server](./kibana-plugin-plugins-embeddable-server.md) > [EnhancementRegistryDefinition](./kibana-plugin-plugins-embeddable-server.enhancementregistrydefinition.md) + +## EnhancementRegistryDefinition interface + +Signature: + +```typescript +export interface EnhancementRegistryDefinition

extends PersistableStateDefinition

Welcome to the Alerting plugin example

- - - - - - - -

Documentation links

-
-
-
- - -

Plugin Structure

-

- This example solution has both `server` and a `public` plugins. The `server` handles - registration of example the AlertTypes, while the `public` handles creation of, and - navigation for, these alert types. -

-
- - -
-
- -); diff --git a/examples/alerting_example/public/components/page.tsx b/examples/alerting_example/public/components/page.tsx deleted file mode 100644 index 99076c7ddcedf..0000000000000 --- a/examples/alerting_example/public/components/page.tsx +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import React from 'react'; -import { withRouter, RouteComponentProps } from 'react-router-dom'; - -import { - EuiPageBody, - EuiPageContent, - EuiPageContentBody, - EuiPageHeader, - EuiPageHeaderSection, - EuiTitle, - EuiBreadcrumbs, - EuiSpacer, -} from '@elastic/eui'; - -type PageProps = RouteComponentProps & { - title: string; - children: React.ReactNode; - crumb?: string; - isHome?: boolean; -}; - -export const Page = withRouter(({ title, crumb, children, isHome = false, history }: PageProps) => { - const breadcrumbs: Array<{ - text: string; - onClick?: () => void; - }> = [ - { - text: crumb ?? title, - }, - ]; - if (!isHome) { - breadcrumbs.splice(0, 0, { - text: 'Home', - onClick: () => { - history.push(`/`); - }, - }); - } - return ( - - - - -

{title}

-
-
-
- - - - {children} - -
- ); -}); diff --git a/examples/alerting_example/public/index.ts b/examples/alerting_example/public/index.ts deleted file mode 100644 index 4a2bfc79903c3..0000000000000 --- a/examples/alerting_example/public/index.ts +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { AlertingExamplePlugin } from './plugin'; - -export const plugin = () => new AlertingExamplePlugin(); diff --git a/examples/alerting_example/public/plugin.tsx b/examples/alerting_example/public/plugin.tsx deleted file mode 100644 index 3f972fa9fe2ee..0000000000000 --- a/examples/alerting_example/public/plugin.tsx +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { Plugin, CoreSetup, AppMountParameters, AppNavLinkStatus } from '../../../src/core/public'; -import { PluginSetupContract as AlertingSetup } from '../../../x-pack/plugins/alerts/public'; -import { ChartsPluginStart } from '../../../src/plugins/charts/public'; -import { TriggersAndActionsUIPublicPluginSetup } from '../../../x-pack/plugins/triggers_actions_ui/public'; -import { DataPublicPluginStart } from '../../../src/plugins/data/public'; -import { getAlertType as getAlwaysFiringAlertType } from './alert_types/always_firing'; -import { getAlertType as getPeopleInSpaceAlertType } from './alert_types/astros'; -import { registerNavigation } from './alert_types'; -import { DeveloperExamplesSetup } from '../../developer_examples/public'; - -export type Setup = void; -export type Start = void; - -export interface AlertingExamplePublicSetupDeps { - alerts: AlertingSetup; - triggers_actions_ui: TriggersAndActionsUIPublicPluginSetup; - developerExamples: DeveloperExamplesSetup; -} - -export interface AlertingExamplePublicStartDeps { - alerts: AlertingSetup; - triggers_actions_ui: TriggersAndActionsUIPublicPluginSetup; - charts: ChartsPluginStart; - data: DataPublicPluginStart; -} - -export class AlertingExamplePlugin implements Plugin { - public setup( - core: CoreSetup, - // eslint-disable-next-line @typescript-eslint/naming-convention - { alerts, triggers_actions_ui, developerExamples }: AlertingExamplePublicSetupDeps - ) { - core.application.register({ - id: 'AlertingExample', - title: 'Alerting Example', - navLinkStatus: AppNavLinkStatus.hidden, - async mount(params: AppMountParameters) { - const [coreStart, depsStart] = await core.getStartServices(); - const { renderApp } = await import('./application'); - return renderApp(coreStart, depsStart, params); - }, - }); - - triggers_actions_ui.alertTypeRegistry.register(getAlwaysFiringAlertType()); - triggers_actions_ui.alertTypeRegistry.register(getPeopleInSpaceAlertType()); - - registerNavigation(alerts); - - developerExamples.register({ - appId: 'AlertingExample', - title: 'Alerting', - description: `This alerting example walks you through how to set up a new alert.`, - links: [ - { - label: 'README', - href: 'https://github.com/elastic/kibana/tree/master/x-pack/plugins/alerting', - iconType: 'logoGithub', - size: 's', - target: '_blank', - }, - ], - }); - } - - public start() {} - public stop() {} -} diff --git a/examples/alerting_example/server/alert_types/always_firing.ts b/examples/alerting_example/server/alert_types/always_firing.ts deleted file mode 100644 index b89e5da089336..0000000000000 --- a/examples/alerting_example/server/alert_types/always_firing.ts +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import uuid from 'uuid'; -import { range } from 'lodash'; -import { AlertType } from '../../../../x-pack/plugins/alerts/server'; -import { DEFAULT_INSTANCES_TO_GENERATE, ALERTING_EXAMPLE_APP_ID } from '../../common/constants'; - -export const alertType: AlertType = { - id: 'example.always-firing', - name: 'Always firing', - actionGroups: [{ id: 'default', name: 'default' }], - defaultActionGroupId: 'default', - async executor({ services, params: { instances = DEFAULT_INSTANCES_TO_GENERATE }, state }) { - const count = (state.count ?? 0) + 1; - - range(instances) - .map(() => ({ id: uuid.v4() })) - .forEach((instance: { id: string }) => { - services - .alertInstanceFactory(instance.id) - .replaceState({ triggerdOnCycle: count }) - .scheduleActions('default'); - }); - - return { - count, - }; - }, - producer: ALERTING_EXAMPLE_APP_ID, -}; diff --git a/examples/alerting_example/server/alert_types/astros.ts b/examples/alerting_example/server/alert_types/astros.ts deleted file mode 100644 index 1ccf8af4ce623..0000000000000 --- a/examples/alerting_example/server/alert_types/astros.ts +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import axios from 'axios'; -import { AlertType } from '../../../../x-pack/plugins/alerts/server'; -import { Operator, Craft, ALERTING_EXAMPLE_APP_ID } from '../../common/constants'; - -interface PeopleInSpace { - people: Array<{ - craft: string; - name: string; - }>; - number: number; -} - -function getOperator(op: string) { - switch (op) { - case Operator.AreAbove: - return (left: number, right: number) => left > right; - case Operator.AreBelow: - return (left: number, right: number) => left < right; - case Operator.AreExactly: - return (left: number, right: number) => left === right; - default: - return () => { - throw new Error( - `Invalid Operator "${op}" [${Operator.AreAbove},${Operator.AreBelow},${Operator.AreExactly}]` - ); - }; - } -} - -function getCraftFilter(craft: string) { - return (person: { craft: string; name: string }) => - craft === Craft.OuterSpace ? true : craft === person.craft; -} - -export const alertType: AlertType = { - id: 'example.people-in-space', - name: 'People In Space Right Now', - actionGroups: [{ id: 'default', name: 'default' }], - defaultActionGroupId: 'default', - async executor({ services, params }) { - const { outerSpaceCapacity, craft: craftToTriggerBy, op } = params; - - const response = await axios.get('http://api.open-notify.org/astros.json'); - const { - data: { number: peopleInSpace, people = [] }, - } = response; - - const peopleInCraft = people.filter(getCraftFilter(craftToTriggerBy)); - - if (getOperator(op)(peopleInCraft.length, outerSpaceCapacity)) { - peopleInCraft.forEach(({ craft, name }) => { - services.alertInstanceFactory(name).replaceState({ craft }).scheduleActions('default'); - }); - } - - return { - peopleInSpace, - }; - }, - producer: ALERTING_EXAMPLE_APP_ID, -}; diff --git a/examples/alerting_example/server/index.ts b/examples/alerting_example/server/index.ts deleted file mode 100644 index 32e9b181ebb54..0000000000000 --- a/examples/alerting_example/server/index.ts +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { PluginInitializer } from 'kibana/server'; -import { AlertingExamplePlugin } from './plugin'; - -export const plugin: PluginInitializer = () => new AlertingExamplePlugin(); diff --git a/examples/alerting_example/server/plugin.ts b/examples/alerting_example/server/plugin.ts deleted file mode 100644 index 4141b48ffeeaf..0000000000000 --- a/examples/alerting_example/server/plugin.ts +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { Plugin, CoreSetup } from 'kibana/server'; -import { i18n } from '@kbn/i18n'; -import { DEFAULT_APP_CATEGORIES } from '../../../src/core/server'; -import { PluginSetupContract as AlertingSetup } from '../../../x-pack/plugins/alerts/server'; -import { PluginSetupContract as FeaturesPluginSetup } from '../../../x-pack/plugins/features/server'; - -import { alertType as alwaysFiringAlert } from './alert_types/always_firing'; -import { alertType as peopleInSpaceAlert } from './alert_types/astros'; -import { INDEX_THRESHOLD_ID } from '../../../x-pack/plugins/alerting_builtins/server'; -import { ALERTING_EXAMPLE_APP_ID } from '../common/constants'; - -// this plugin's dependendencies -export interface AlertingExampleDeps { - alerts: AlertingSetup; - features: FeaturesPluginSetup; -} - -export class AlertingExamplePlugin implements Plugin { - public setup(core: CoreSetup, { alerts, features }: AlertingExampleDeps) { - alerts.registerType(alwaysFiringAlert); - alerts.registerType(peopleInSpaceAlert); - - features.registerKibanaFeature({ - id: ALERTING_EXAMPLE_APP_ID, - name: i18n.translate('alertsExample.featureRegistry.alertsExampleFeatureName', { - defaultMessage: 'Alerts Example', - }), - app: [], - management: { - insightsAndAlerting: ['triggersActions'], - }, - category: DEFAULT_APP_CATEGORIES.management, - alerting: [alwaysFiringAlert.id, peopleInSpaceAlert.id, INDEX_THRESHOLD_ID], - privileges: { - all: { - alerting: { - all: [alwaysFiringAlert.id, peopleInSpaceAlert.id, INDEX_THRESHOLD_ID], - }, - savedObject: { - all: [], - read: [], - }, - management: { - insightsAndAlerting: ['triggersActions'], - }, - ui: [], - }, - read: { - alerting: { - read: [alwaysFiringAlert.id, peopleInSpaceAlert.id, INDEX_THRESHOLD_ID], - }, - savedObject: { - all: [], - read: [], - }, - management: { - insightsAndAlerting: ['triggersActions'], - }, - ui: [], - }, - }, - }); - } - - public start() {} - public stop() {} -} diff --git a/examples/alerting_example/tsconfig.json b/examples/alerting_example/tsconfig.json deleted file mode 100644 index 214e4b78a9a70..0000000000000 --- a/examples/alerting_example/tsconfig.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "extends": "../../tsconfig.base.json", - "compilerOptions": { - "outDir": "./target" - }, - "include": [ - "index.ts", - "public/**/*.ts", - "public/**/*.tsx", - "server/**/*.ts", - "common/**/*.ts", - "../../typings/**/*", - ], - "exclude": [], - "references": [ - { "path": "../../src/core/tsconfig.json" } - ] -} diff --git a/examples/bfetch_explorer/tsconfig.json b/examples/bfetch_explorer/tsconfig.json index 86b35c5e4943f..253fdd9ee6c89 100644 --- a/examples/bfetch_explorer/tsconfig.json +++ b/examples/bfetch_explorer/tsconfig.json @@ -13,6 +13,7 @@ ], "exclude": [], "references": [ - { "path": "../../src/core/tsconfig.json" } + { "path": "../../src/core/tsconfig.json" }, + { "path": "../../src/plugins/kibana_react/tsconfig.json" }, ] } diff --git a/examples/embeddable_examples/kibana.json b/examples/embeddable_examples/kibana.json index 0ac40ae1889de..6025d24665901 100644 --- a/examples/embeddable_examples/kibana.json +++ b/examples/embeddable_examples/kibana.json @@ -4,7 +4,7 @@ "kibanaVersion": "kibana", "server": true, "ui": true, - "requiredPlugins": ["embeddable", "uiActions", "dashboard"], + "requiredPlugins": ["embeddable", "uiActions", "savedObjects", "dashboard"], "optionalPlugins": [], "extraPublicDirs": ["public/todo", "public/hello_world", "public/todo/todo_ref_embeddable"], "requiredBundles": ["kibanaReact"] diff --git a/examples/embeddable_examples/public/book/book_embeddable.tsx b/examples/embeddable_examples/public/book/book_embeddable.tsx index 48b81c27e8b8d..8d633a892ec6d 100644 --- a/examples/embeddable_examples/public/book/book_embeddable.tsx +++ b/examples/embeddable_examples/public/book/book_embeddable.tsx @@ -26,10 +26,10 @@ import { EmbeddableOutput, SavedObjectEmbeddableInput, ReferenceOrValueEmbeddable, + AttributeService, } from '../../../../src/plugins/embeddable/public'; import { BookSavedObjectAttributes } from '../../common'; import { BookEmbeddableComponent } from './book_component'; -import { AttributeService } from '../../../../src/plugins/dashboard/public'; export const BOOK_EMBEDDABLE = 'book'; export type BookEmbeddableInput = BookByValueInput | BookByReferenceInput; @@ -89,6 +89,7 @@ export class BookEmbeddable } else { this.updateOutput({ attributes: this.attributes, + defaultTitle: this.attributes.title, hasMatch: getHasMatch(this.input.search, this.attributes), }); } @@ -125,6 +126,7 @@ export class BookEmbeddable this.updateOutput({ attributes: this.attributes, + defaultTitle: this.attributes.title, hasMatch: getHasMatch(this.input.search, this.attributes), }); } diff --git a/examples/embeddable_examples/public/book/book_embeddable_factory.tsx b/examples/embeddable_examples/public/book/book_embeddable_factory.tsx index 292261ee16c59..f569e2e8d154d 100644 --- a/examples/embeddable_examples/public/book/book_embeddable_factory.tsx +++ b/examples/embeddable_examples/public/book/book_embeddable_factory.tsx @@ -25,6 +25,8 @@ import { EmbeddableFactoryDefinition, IContainer, EmbeddableFactory, + EmbeddableStart, + AttributeService, } from '../../../../src/plugins/embeddable/public'; import { BookEmbeddable, @@ -33,12 +35,18 @@ import { BookEmbeddableOutput, } from './book_embeddable'; import { CreateEditBookComponent } from './create_edit_book_component'; -import { OverlayStart } from '../../../../src/core/public'; -import { DashboardStart, AttributeService } from '../../../../src/plugins/dashboard/public'; +import { + OverlayStart, + SavedObjectsClientContract, + SimpleSavedObject, +} from '../../../../src/core/public'; +import { checkForDuplicateTitle, OnSaveProps } from '../../../../src/plugins/saved_objects/public'; interface StartServices { - getAttributeService: DashboardStart['getAttributeService']; + getAttributeService: EmbeddableStart['getAttributeService']; openModal: OverlayStart['openModal']; + savedObjectsClient: SavedObjectsClientContract; + overlays: OverlayStart; } export type BookEmbeddableFactory = EmbeddableFactory< @@ -117,11 +125,55 @@ export class BookEmbeddableFactoryDefinition }); } + private async unwrapMethod(savedObjectId: string): Promise { + const { savedObjectsClient } = await this.getStartServices(); + const savedObject: SimpleSavedObject = await savedObjectsClient.get< + BookSavedObjectAttributes + >(this.type, savedObjectId); + return { ...savedObject.attributes }; + } + + private async saveMethod( + type: string, + attributes: BookSavedObjectAttributes, + savedObjectId?: string + ) { + const { savedObjectsClient } = await this.getStartServices(); + if (savedObjectId) { + return savedObjectsClient.update(type, savedObjectId, attributes); + } + return savedObjectsClient.create(type, attributes); + } + + private async checkForDuplicateTitleMethod(props: OnSaveProps): Promise { + const start = await this.getStartServices(); + const { savedObjectsClient, overlays } = start; + return checkForDuplicateTitle( + { + title: props.newTitle, + copyOnSave: false, + lastSavedTitle: '', + getEsType: () => this.type, + getDisplayName: this.getDisplayName || (() => this.type), + }, + props.isTitleDuplicateConfirmed, + props.onTitleDuplicate, + { + savedObjectsClient, + overlays, + } + ); + } + private async getAttributeService() { if (!this.attributeService) { - this.attributeService = await (await this.getStartServices()).getAttributeService< + this.attributeService = (await this.getStartServices()).getAttributeService< BookSavedObjectAttributes - >(this.type); + >(this.type, { + saveMethod: this.saveMethod.bind(this), + unwrapMethod: this.unwrapMethod.bind(this), + checkForDuplicateTitle: this.checkForDuplicateTitleMethod.bind(this), + }); } return this.attributeService!; } diff --git a/examples/embeddable_examples/public/book/edit_book_action.tsx b/examples/embeddable_examples/public/book/edit_book_action.tsx index 3541ace1e5e7e..e2133a8d51ea2 100644 --- a/examples/embeddable_examples/public/book/edit_book_action.tsx +++ b/examples/embeddable_examples/public/book/edit_book_action.tsx @@ -22,7 +22,11 @@ import { i18n } from '@kbn/i18n'; import { BookSavedObjectAttributes, BOOK_SAVED_OBJECT } from '../../common'; import { createAction } from '../../../../src/plugins/ui_actions/public'; import { toMountPoint } from '../../../../src/plugins/kibana_react/public'; -import { ViewMode, SavedObjectEmbeddableInput } from '../../../../src/plugins/embeddable/public'; +import { + ViewMode, + SavedObjectEmbeddableInput, + EmbeddableStart, +} from '../../../../src/plugins/embeddable/public'; import { BookEmbeddable, BOOK_EMBEDDABLE, @@ -30,11 +34,13 @@ import { BookByValueInput, } from './book_embeddable'; import { CreateEditBookComponent } from './create_edit_book_component'; -import { DashboardStart } from '../../../../src/plugins/dashboard/public'; +import { OnSaveProps } from '../../../../src/plugins/saved_objects/public'; +import { SavedObjectsClientContract } from '../../../../src/core/target/types/public/saved_objects'; interface StartServices { openModal: OverlayStart['openModal']; - getAttributeService: DashboardStart['getAttributeService']; + getAttributeService: EmbeddableStart['getAttributeService']; + savedObjectsClient: SavedObjectsClientContract; } interface ActionContext { @@ -56,8 +62,24 @@ export const createEditBookAction = (getStartServices: () => Promise { - const { openModal, getAttributeService } = await getStartServices(); - const attributeService = getAttributeService(BOOK_SAVED_OBJECT); + const { openModal, getAttributeService, savedObjectsClient } = await getStartServices(); + const attributeService = getAttributeService(BOOK_SAVED_OBJECT, { + saveMethod: async ( + type: string, + attributes: BookSavedObjectAttributes, + savedObjectId?: string + ) => { + if (savedObjectId) { + return savedObjectsClient.update(type, savedObjectId, attributes); + } + return savedObjectsClient.create(type, attributes); + }, + checkForDuplicateTitle: (props: OnSaveProps) => { + return new Promise(() => { + return true; + }); + }, + }); const onSave = async (attributes: BookSavedObjectAttributes, useRefType: boolean) => { const newInput = await attributeService.wrapAttributes( attributes, diff --git a/examples/embeddable_examples/public/plugin.ts b/examples/embeddable_examples/public/plugin.ts index 0c6ed1eb3be48..9b9770e40611e 100644 --- a/examples/embeddable_examples/public/plugin.ts +++ b/examples/embeddable_examples/public/plugin.ts @@ -22,7 +22,7 @@ import { EmbeddableStart, CONTEXT_MENU_TRIGGER, } from '../../../src/plugins/embeddable/public'; -import { Plugin, CoreSetup, CoreStart } from '../../../src/core/public'; +import { Plugin, CoreSetup, CoreStart, SavedObjectsClient } from '../../../src/core/public'; import { HelloWorldEmbeddableFactory, HELLO_WORLD_EMBEDDABLE, @@ -62,7 +62,6 @@ import { ACTION_ADD_BOOK_TO_LIBRARY, createAddBookToLibraryAction, } from './book/add_book_to_library_action'; -import { DashboardStart } from '../../../src/plugins/dashboard/public'; import { ACTION_UNLINK_BOOK_FROM_LIBRARY, createUnlinkBookFromLibraryAction, @@ -75,7 +74,7 @@ export interface EmbeddableExamplesSetupDependencies { export interface EmbeddableExamplesStartDependencies { embeddable: EmbeddableStart; - dashboard: DashboardStart; + savedObjectsClient: SavedObjectsClient; } interface ExampleEmbeddableFactories { @@ -156,14 +155,17 @@ export class EmbeddableExamplesPlugin this.exampleEmbeddableFactories.getBookEmbeddableFactory = deps.embeddable.registerEmbeddableFactory( BOOK_EMBEDDABLE, new BookEmbeddableFactoryDefinition(async () => ({ - getAttributeService: (await core.getStartServices())[1].dashboard.getAttributeService, + getAttributeService: (await core.getStartServices())[1].embeddable.getAttributeService, openModal: (await core.getStartServices())[0].overlays.openModal, + savedObjectsClient: (await core.getStartServices())[0].savedObjects.client, + overlays: (await core.getStartServices())[0].overlays, })) ); const editBookAction = createEditBookAction(async () => ({ - getAttributeService: (await core.getStartServices())[1].dashboard.getAttributeService, + getAttributeService: (await core.getStartServices())[1].embeddable.getAttributeService, openModal: (await core.getStartServices())[0].overlays.openModal, + savedObjectsClient: (await core.getStartServices())[0].savedObjects.client, })); deps.uiActions.registerAction(editBookAction); deps.uiActions.attachAction(CONTEXT_MENU_TRIGGER, editBookAction.id); diff --git a/examples/embeddable_examples/tsconfig.json b/examples/embeddable_examples/tsconfig.json index 78098339c16f5..a922c6defcd4c 100644 --- a/examples/embeddable_examples/tsconfig.json +++ b/examples/embeddable_examples/tsconfig.json @@ -14,6 +14,7 @@ ], "exclude": [], "references": [ - { "path": "../../src/core/tsconfig.json" } + { "path": "../../src/core/tsconfig.json" }, + { "path": "../../src/plugins/kibana_react/tsconfig.json" }, ] } diff --git a/examples/search_examples/public/components/app.tsx b/examples/search_examples/public/components/app.tsx index 704d31d42e640..2425f3bbad8a9 100644 --- a/examples/search_examples/public/components/app.tsx +++ b/examples/search_examples/public/components/app.tsx @@ -53,9 +53,10 @@ import { import { DataPublicPluginStart, - IndexPatternSelect, IndexPattern, IndexPatternField, + isCompleteResponse, + isErrorResponse, } from '../../../../src/plugins/data/public'; interface SearchExamplesAppDeps { @@ -90,6 +91,7 @@ export const SearchExamplesApp = ({ navigation, data, }: SearchExamplesAppDeps) => { + const { IndexPatternSelect } = data.ui; const [getCool, setGetCool] = useState(false); const [timeTook, setTimeTook] = useState(); const [indexPattern, setIndexPattern] = useState(); @@ -144,7 +146,7 @@ export const SearchExamplesApp = ({ }) .subscribe({ next: (response) => { - if (!response.isPartial && !response.isRunning) { + if (isCompleteResponse(response)) { setTimeTook(response.rawResponse.took); const avgResult: number | undefined = response.rawResponse.aggregations ? response.rawResponse.aggregations[1].value @@ -162,7 +164,7 @@ export const SearchExamplesApp = ({ text: mountReactNode(message), }); searchSubscription$.unsubscribe(); - } else if (response.isPartial && !response.isRunning) { + } else if (isErrorResponse(response)) { // TODO: Make response error status clearer notifications.toasts.addWarning('An error has occurred'); searchSubscription$.unsubscribe(); @@ -230,7 +232,6 @@ export const SearchExamplesApp = ({ Index Pattern { +export const mySearchStrategyProvider = ( + data: PluginStart +): ISearchStrategy => { const es = data.search.getSearchStrategy('es'); return { search: async (context, request, options): Promise => { - request.debug = true; const esSearchRes = await es.search(context, request, options); return { ...esSearchRes, - cool: (request as IMyStrategyRequest).get_cool ? 'YES' : 'NOPE', + cool: request.get_cool ? 'YES' : 'NOPE', }; }, cancel: async (context, id) => { diff --git a/examples/state_containers_examples/tsconfig.json b/examples/state_containers_examples/tsconfig.json index 6cfb9f9dc2321..442fa08022dc4 100644 --- a/examples/state_containers_examples/tsconfig.json +++ b/examples/state_containers_examples/tsconfig.json @@ -14,6 +14,8 @@ ], "exclude": [], "references": [ - { "path": "../../src/core/tsconfig.json" } + { "path": "../../src/core/tsconfig.json" }, + { "path": "../../src/plugins/kibana_utils/tsconfig.json" }, + { "path": "../../src/plugins/kibana_react/tsconfig.json" }, ] } diff --git a/examples/ui_action_examples/tsconfig.json b/examples/ui_action_examples/tsconfig.json index 86b35c5e4943f..253fdd9ee6c89 100644 --- a/examples/ui_action_examples/tsconfig.json +++ b/examples/ui_action_examples/tsconfig.json @@ -13,6 +13,7 @@ ], "exclude": [], "references": [ - { "path": "../../src/core/tsconfig.json" } + { "path": "../../src/core/tsconfig.json" }, + { "path": "../../src/plugins/kibana_react/tsconfig.json" }, ] } diff --git a/examples/ui_actions_explorer/public/app.tsx b/examples/ui_actions_explorer/public/app.tsx index d59309f006838..bc8bdee75047d 100644 --- a/examples/ui_actions_explorer/public/app.tsx +++ b/examples/ui_actions_explorer/public/app.tsx @@ -37,6 +37,7 @@ import { UiActionsStart, createAction } from '../../../src/plugins/ui_actions/pu import { AppMountParameters, OverlayStart } from '../../../src/core/public'; import { HELLO_WORLD_TRIGGER_ID, ACTION_HELLO_WORLD } from '../../ui_action_examples/public'; import { TriggerContextExample } from './trigger_context_example'; +import { ContextMenuExamples } from './context_menu_examples'; interface Props { uiActionsApi: UiActionsStart; @@ -109,7 +110,12 @@ const ActionsExplorer = ({ uiActionsApi, openModal }: Props) => { + + + + + diff --git a/examples/ui_actions_explorer/public/context_menu_examples/context_menu_examples.tsx b/examples/ui_actions_explorer/public/context_menu_examples/context_menu_examples.tsx new file mode 100644 index 0000000000000..ea00b22fa3cdc --- /dev/null +++ b/examples/ui_actions_explorer/public/context_menu_examples/context_menu_examples.tsx @@ -0,0 +1,63 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React from 'react'; +import { EuiCode, EuiFlexGroup, EuiFlexItem, EuiText } from '@elastic/eui'; +import { PanelView } from './panel_view'; +import { PanelViewWithSharing } from './panel_view_with_sharing'; +import { PanelViewWithSharingLong } from './panel_view_with_sharing_long'; +import { PanelEdit } from './panel_edit'; +import { PanelEditWithDrilldowns } from './panel_edit_with_drilldowns'; +import { PanelEditWithDrilldownsAndContextActions } from './panel_edit_with_drilldowns_and_context_actions'; + +export const ContextMenuExamples: React.FC = () => { + return ( + +

Context menu examples

+

+ Below examples show how context menu panels look with varying number of actions and how the + actions can be grouped into different panels using grouping field. +

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ ); +}; diff --git a/examples/ui_actions_explorer/public/context_menu_examples/index.tsx b/examples/ui_actions_explorer/public/context_menu_examples/index.tsx new file mode 100644 index 0000000000000..4a8c2fd00cd4d --- /dev/null +++ b/examples/ui_actions_explorer/public/context_menu_examples/index.tsx @@ -0,0 +1,20 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export * from './context_menu_examples'; diff --git a/examples/ui_actions_explorer/public/context_menu_examples/panel_edit.tsx b/examples/ui_actions_explorer/public/context_menu_examples/panel_edit.tsx new file mode 100644 index 0000000000000..794a8d0348baf --- /dev/null +++ b/examples/ui_actions_explorer/public/context_menu_examples/panel_edit.tsx @@ -0,0 +1,59 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import * as React from 'react'; +import { EuiButton, EuiContextMenu, EuiPopover } from '@elastic/eui'; +import useAsync from 'react-use/lib/useAsync'; +import { buildContextMenuForActions } from '../../../../src/plugins/ui_actions/public'; +import { sampleAction } from './util'; + +export const PanelEdit: React.FC = () => { + const [open, setOpen] = React.useState(false); + + const context = {}; + const trigger: any = 'TEST_TRIGGER'; + const actions = [ + sampleAction('test-1', 100, 'Edit visualization', 'pencil'), + sampleAction('test-2', 99, 'Clone panel', 'partial'), + sampleAction('test-3', 98, 'Edit panel title', 'pencil'), + sampleAction('test-4', 97, 'Customize time range', 'calendar'), + sampleAction('test-5', 96, 'Inspect', 'inspect'), + sampleAction('test-6', 95, 'Full screen', 'fullScreen'), + sampleAction('test-7', 94, 'Replace panel', 'submodule'), + sampleAction('test-8', 93, 'Delete from dashboard', 'trash'), + ]; + + const panels = useAsync(() => + buildContextMenuForActions({ + actions: actions.map((action) => ({ action, context, trigger })), + }) + ); + + return ( + setOpen((x) => !x)}>Edit mode} + isOpen={open} + panelPaddingSize="none" + anchorPosition="downLeft" + closePopover={() => setOpen(false)} + > + + + ); +}; diff --git a/examples/ui_actions_explorer/public/context_menu_examples/panel_edit_with_drilldowns.tsx b/examples/ui_actions_explorer/public/context_menu_examples/panel_edit_with_drilldowns.tsx new file mode 100644 index 0000000000000..185011066e8e4 --- /dev/null +++ b/examples/ui_actions_explorer/public/context_menu_examples/panel_edit_with_drilldowns.tsx @@ -0,0 +1,70 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import * as React from 'react'; +import { EuiButton, EuiContextMenu, EuiPopover } from '@elastic/eui'; +import useAsync from 'react-use/lib/useAsync'; +import { buildContextMenuForActions, Action } from '../../../../src/plugins/ui_actions/public'; +import { sampleAction } from './util'; + +export const PanelEditWithDrilldowns: React.FC = () => { + const [open, setOpen] = React.useState(false); + + const context = {}; + const trigger: any = 'TEST_TRIGGER'; + const grouping: Action['grouping'] = [ + { + id: 'drilldowns', + getDisplayName: () => 'Drilldowns', + getIconType: () => 'popout', + order: 20, + }, + ]; + const actions = [ + sampleAction('test-1', 100, 'Edit visualization', 'pencil'), + sampleAction('test-2', 99, 'Clone panel', 'partial'), + sampleAction('test-3', 98, 'Edit panel title', 'pencil'), + sampleAction('test-4', 97, 'Customize time range', 'calendar'), + sampleAction('test-5', 96, 'Inspect', 'inspect'), + sampleAction('test-6', 95, 'Full screen', 'fullScreen'), + sampleAction('test-7', 94, 'Replace panel', 'submodule'), + sampleAction('test-8', 93, 'Delete from dashboard', 'trash'), + + sampleAction('test-9', 10, 'Create drilldown', 'plusInCircle', grouping), + sampleAction('test-10', 9, 'Manage drilldowns', 'list', grouping), + ]; + + const panels = useAsync(() => + buildContextMenuForActions({ + actions: actions.map((action) => ({ action, context, trigger })), + }) + ); + + return ( + setOpen((x) => !x)}>Edit mode with drilldowns} + isOpen={open} + panelPaddingSize="none" + anchorPosition="downLeft" + closePopover={() => setOpen(false)} + > + + + ); +}; diff --git a/examples/ui_actions_explorer/public/context_menu_examples/panel_edit_with_drilldowns_and_context_actions.tsx b/examples/ui_actions_explorer/public/context_menu_examples/panel_edit_with_drilldowns_and_context_actions.tsx new file mode 100644 index 0000000000000..e9543814ff015 --- /dev/null +++ b/examples/ui_actions_explorer/public/context_menu_examples/panel_edit_with_drilldowns_and_context_actions.tsx @@ -0,0 +1,87 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import * as React from 'react'; +import { EuiButton, EuiContextMenu, EuiPopover } from '@elastic/eui'; +import useAsync from 'react-use/lib/useAsync'; +import { buildContextMenuForActions, Action } from '../../../../src/plugins/ui_actions/public'; +import { sampleAction } from './util'; + +export const PanelEditWithDrilldownsAndContextActions: React.FC = () => { + const [open, setOpen] = React.useState(false); + + const context = {}; + const trigger: any = 'TEST_TRIGGER'; + const drilldownGrouping: Action['grouping'] = [ + { + id: 'drilldowns', + getDisplayName: () => 'Drilldowns', + getIconType: () => 'popout', + order: 20, + }, + ]; + const customActionGrouping: Action['grouping'] = [ + { + id: 'actions', + getDisplayName: () => 'Custom actions', + getIconType: () => 'cloudStormy', + order: 20, + }, + ]; + const actions = [ + sampleAction('test-1', 100, 'Edit visualization', 'pencil'), + sampleAction('test-2', 99, 'Clone panel', 'partial'), + sampleAction('test-3', 98, 'Edit panel title', 'pencil'), + sampleAction('test-4', 97, 'Customize time range', 'calendar'), + sampleAction('test-5', 96, 'Inspect', 'inspect'), + sampleAction('test-6', 95, 'Full screen', 'fullScreen'), + sampleAction('test-7', 94, 'Replace panel', 'submodule'), + sampleAction('test-8', 93, 'Delete from dashboard', 'trash'), + + sampleAction('test-9', 10, 'Create drilldown', 'plusInCircle', drilldownGrouping), + sampleAction('test-10', 9, 'Manage drilldowns', 'list', drilldownGrouping), + + sampleAction('test-11', 10, 'Go to Sales dashboard', 'dashboardApp', customActionGrouping), + sampleAction('test-12', 9, 'Go to Traffic dashboard', 'dashboardApp', customActionGrouping), + sampleAction('test-13', 8, 'Custom actions', 'cloudStormy', customActionGrouping), + sampleAction('test-14', 7, 'View in Salesforce', 'link', customActionGrouping), + ]; + + const panels = useAsync(() => + buildContextMenuForActions({ + actions: actions.map((action) => ({ action, context, trigger })), + }) + ); + + return ( + setOpen((x) => !x)}> + Edit mode with drilldowns and custom actions + + } + isOpen={open} + panelPaddingSize="none" + anchorPosition="downLeft" + closePopover={() => setOpen(false)} + > + + + ); +}; diff --git a/examples/ui_actions_explorer/public/context_menu_examples/panel_view.tsx b/examples/ui_actions_explorer/public/context_menu_examples/panel_view.tsx new file mode 100644 index 0000000000000..db8763fdf17f8 --- /dev/null +++ b/examples/ui_actions_explorer/public/context_menu_examples/panel_view.tsx @@ -0,0 +1,55 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import * as React from 'react'; +import { EuiButton, EuiContextMenu, EuiPopover } from '@elastic/eui'; +import useAsync from 'react-use/lib/useAsync'; +import { buildContextMenuForActions } from '../../../../src/plugins/ui_actions/public'; +import { sampleAction } from './util'; + +export const PanelView: React.FC = () => { + const [open, setOpen] = React.useState(false); + + const context = {}; + const trigger: any = 'TEST_TRIGGER'; + const actions = [ + sampleAction('test-1', 100, 'Explore underlying data', 'discoverApp'), + sampleAction('test-2', 99, 'Customize time range', 'calendar'), + sampleAction('test-3', 98, 'Inspect', 'inspect'), + sampleAction('test-4', 97, 'Full screen', 'fullScreen'), + ]; + + const panels = useAsync(() => + buildContextMenuForActions({ + actions: actions.map((action) => ({ action, context, trigger })), + }) + ); + + return ( + setOpen((x) => !x)}>View mode} + isOpen={open} + panelPaddingSize="none" + anchorPosition="downLeft" + closePopover={() => setOpen(false)} + > + + + ); +}; diff --git a/examples/ui_actions_explorer/public/context_menu_examples/panel_view_with_sharing.tsx b/examples/ui_actions_explorer/public/context_menu_examples/panel_view_with_sharing.tsx new file mode 100644 index 0000000000000..2c99d04e7d19a --- /dev/null +++ b/examples/ui_actions_explorer/public/context_menu_examples/panel_view_with_sharing.tsx @@ -0,0 +1,67 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import * as React from 'react'; +import { EuiButton, EuiContextMenu, EuiPopover } from '@elastic/eui'; +import useAsync from 'react-use/lib/useAsync'; +import { buildContextMenuForActions, Action } from '../../../../src/plugins/ui_actions/public'; +import { sampleAction } from './util'; + +export const PanelViewWithSharing: React.FC = () => { + const [open, setOpen] = React.useState(false); + + const context = {}; + const trigger: any = 'TEST_TRIGGER'; + const grouping: Action['grouping'] = [ + { + id: 'sharing', + getDisplayName: () => 'Sharing', + getIconType: () => 'share', + order: 50, + }, + ]; + const actions = [ + sampleAction('test-1', 100, 'Explore underlying data', 'discoverApp'), + sampleAction('test-2', 99, 'Customize time range', 'calendar'), + sampleAction('test-3', 98, 'Inspect', 'inspect'), + sampleAction('test-4', 97, 'Full screen', 'fullScreen'), + sampleAction('test-5', 10, 'Copy link', 'link', grouping), + sampleAction('test-6', 9, 'Copy .png', 'image', grouping), + ]; + + const panels = useAsync(() => + buildContextMenuForActions({ + actions: actions.map((action) => ({ action, context, trigger })), + }) + ); + + return ( + setOpen((x) => !x)}>View mode with few sharing options + } + isOpen={open} + panelPaddingSize="none" + anchorPosition="downLeft" + closePopover={() => setOpen(false)} + > + + + ); +}; diff --git a/examples/ui_actions_explorer/public/context_menu_examples/panel_view_with_sharing_long.tsx b/examples/ui_actions_explorer/public/context_menu_examples/panel_view_with_sharing_long.tsx new file mode 100644 index 0000000000000..99b8cbec57677 --- /dev/null +++ b/examples/ui_actions_explorer/public/context_menu_examples/panel_view_with_sharing_long.tsx @@ -0,0 +1,72 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import * as React from 'react'; +import { EuiButton, EuiContextMenu, EuiPopover } from '@elastic/eui'; +import useAsync from 'react-use/lib/useAsync'; +import { buildContextMenuForActions, Action } from '../../../../src/plugins/ui_actions/public'; +import { sampleAction } from './util'; + +export const PanelViewWithSharingLong: React.FC = () => { + const [open, setOpen] = React.useState(false); + + const context = {}; + const trigger: any = 'TEST_TRIGGER'; + const grouping: Action['grouping'] = [ + { + id: 'sharing', + getDisplayName: () => 'Sharing', + getIconType: () => 'share', + order: 50, + }, + ]; + const actions = [ + sampleAction('test-1', 100, 'Explore underlying data', 'discoverApp'), + sampleAction('test-2', 99, 'Customize time range', 'calendar'), + sampleAction('test-3', 98, 'Inspect', 'inspect'), + sampleAction('test-4', 97, 'Full screen', 'fullScreen'), + sampleAction('test-5', 10, 'Copy link', 'link', grouping), + sampleAction('test-6', 9, 'Copy .png', 'image', grouping), + sampleAction('test-7', 8, 'Copy .pdf', 'link', grouping), + sampleAction('test-8', 7, 'Send to slack', 'link', grouping), + sampleAction('test-9', 6, 'Send by e-mail', 'email', grouping), + ]; + + const panels = useAsync(() => + buildContextMenuForActions({ + actions: actions.map((action) => ({ action, context, trigger })), + }) + ); + + return ( + setOpen((x) => !x)}> + View mode with many sharing options + + } + isOpen={open} + panelPaddingSize="none" + anchorPosition="downLeft" + closePopover={() => setOpen(false)} + > + + + ); +}; diff --git a/examples/ui_actions_explorer/public/context_menu_examples/util.ts b/examples/ui_actions_explorer/public/context_menu_examples/util.ts new file mode 100644 index 0000000000000..ea14ceec7b0a3 --- /dev/null +++ b/examples/ui_actions_explorer/public/context_menu_examples/util.ts @@ -0,0 +1,39 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { Action } from '../../../../src/plugins/ui_actions/public'; + +export const sampleAction = ( + id: string, + order: number, + name: string, + icon: string, + grouping?: Action['grouping'] +): Action => { + return { + id, + type: 'SAMPLE' as any, + order, + getDisplayName: () => name, + getIconType: () => icon, + isCompatible: async () => true, + execute: async () => {}, + grouping, + }; +}; diff --git a/examples/ui_actions_explorer/tsconfig.json b/examples/ui_actions_explorer/tsconfig.json index 782b9cd57fa7b..b4449819b25a6 100644 --- a/examples/ui_actions_explorer/tsconfig.json +++ b/examples/ui_actions_explorer/tsconfig.json @@ -12,6 +12,7 @@ ], "exclude": [], "references": [ - { "path": "../../src/core/tsconfig.json" } + { "path": "../../src/core/tsconfig.json" }, + { "path": "../../src/plugins/kibana_react/tsconfig.json" }, ] } diff --git a/kibana.d.ts b/kibana.d.ts index b707405ffbeaf..50f8b8690d944 100644 --- a/kibana.d.ts +++ b/kibana.d.ts @@ -28,7 +28,6 @@ export { Public, Server }; /** * All exports from TS ambient definitions (where types are added for JS source in a .d.ts file). */ -import * as LegacyKibanaPluginSpec from './src/legacy/plugin_discovery/plugin_spec/plugin_spec_options'; import * as LegacyKibanaServer from './src/legacy/server/kbn_server'; /** @@ -39,8 +38,4 @@ export namespace Legacy { export type Request = LegacyKibanaServer.Request; export type ResponseToolkit = LegacyKibanaServer.ResponseToolkit; export type Server = LegacyKibanaServer.Server; - - export type InitPluginFunction = LegacyKibanaPluginSpec.InitPluginFunction; - export type UiExports = LegacyKibanaPluginSpec.UiExports; - export type PluginSpecOptions = LegacyKibanaPluginSpec.PluginSpecOptions; } diff --git a/package.json b/package.json index fb1d7e50d7d22..1e334f75d41b0 100644 --- a/package.json +++ b/package.json @@ -115,11 +115,9 @@ ] }, "dependencies": { - "@babel/core": "^7.11.1", - "@babel/register": "^7.10.5", "@elastic/datemath": "5.0.3", - "@elastic/elasticsearch": "7.9.0-rc.2", - "@elastic/eui": "28.4.0", + "@elastic/elasticsearch": "7.9.1", + "@elastic/eui": "29.3.0", "@elastic/good": "8.1.1-kibana2", "@elastic/numeral": "^2.5.0", "@elastic/request-crypto": "1.1.4", @@ -127,7 +125,7 @@ "@hapi/good-squeeze": "5.2.1", "@hapi/wreck": "^15.0.2", "@kbn/analytics": "1.0.0", - "@kbn/babel-preset": "1.0.0", + "@kbn/apm-config-loader": "1.0.0", "@kbn/config": "1.0.0", "@kbn/config-schema": "1.0.0", "@kbn/i18n": "1.0.0", @@ -138,6 +136,8 @@ "@kbn/telemetry-tools": "1.0.0", "@kbn/test-subj-selector": "0.2.1", "@kbn/ui-framework": "1.0.0", + "@kbn/ace": "1.0.0", + "@kbn/monaco": "1.0.0", "@kbn/ui-shared-deps": "1.0.0", "@types/yauzl": "^2.9.1", "JSONStream": "1.3.5", @@ -148,12 +148,12 @@ "angular-sanitize": "^1.8.0", "bluebird": "3.5.5", "boom": "^7.2.0", - "chalk": "^2.4.2", + "chalk": "^4.1.0", "check-disk-space": "^2.1.0", - "chokidar": "3.2.1", + "chokidar": "^3.4.2", "color": "1.0.3", - "commander": "3.0.2", - "core-js": "^3.6.4", + "commander": "^3.0.2", + "core-js": "^3.6.5", "cypress-promise": "^1.1.0", "deep-freeze-strict": "^1.1.1", "del": "^5.1.0", @@ -171,29 +171,30 @@ "handlebars": "4.7.6", "hapi": "^17.5.3", "hapi-auth-cookie": "^9.0.0", + "hjson": "3.2.1", "hoek": "^5.0.4", "http-proxy-agent": "^2.1.0", "https-proxy-agent": "^5.0.0", "inert": "^5.1.0", "inline-style": "^2.0.0", "joi": "^13.5.2", - "js-yaml": "3.13.1", + "js-yaml": "^3.14.0", "json-stable-stringify": "^1.0.1", "json-stringify-safe": "5.0.1", "lodash": "^4.17.20", - "lru-cache": "4.1.5", + "lru-cache": "^4.1.5", "minimatch": "^3.0.4", "moment": "^2.24.0", "moment-timezone": "^0.5.27", - "mustache": "2.3.2", - "node-fetch": "2.6.1", + "mustache": "^2.3.2", + "node-fetch": "^2.6.1", "node-forge": "^0.10.0", "opn": "^5.5.0", "oppsy": "^2.0.0", "p-map": "^4.0.0", "pegjs": "0.10.0", "proxy-from-env": "1.0.0", - "query-string": "5.1.1", + "query-string": "^6.13.2", "re2": "^1.15.4", "react": "^16.12.0", "react-color": "^2.13.8", @@ -209,7 +210,8 @@ "rison-node": "1.0.2", "rxjs": "^6.5.5", "seedrandom": "^3.0.5", - "semver": "^5.5.0", + "semver": "^5.7.0", + "source-map-support": "^0.5.19", "style-it": "^2.1.3", "symbol-observable": "^1.2.0", "tar": "4.4.13", @@ -220,20 +222,23 @@ "uuid": "3.3.2", "vision": "^5.3.3", "whatwg-fetch": "^3.0.0", - "yauzl": "2.10.0" + "yauzl": "^2.10.0" }, "devDependencies": { + "@babel/core": "^7.11.6", "@babel/parser": "^7.11.2", + "@babel/register": "^7.10.5", "@babel/types": "^7.11.0", - "@elastic/apm-rum": "^5.5.0", - "@elastic/charts": "21.1.2", - "@elastic/ems-client": "7.9.3", + "@elastic/apm-rum": "^5.6.1", + "@elastic/charts": "23.2.1", + "@elastic/ems-client": "7.10.0", "@elastic/eslint-config-kibana": "0.15.0", "@elastic/eslint-plugin-eui": "0.0.2", "@elastic/filesaver": "1.1.2", "@elastic/github-checks-reporter": "0.0.20b3", "@elastic/makelogs": "^6.0.0", "@elastic/ui-ace": "0.2.3", + "@kbn/babel-preset": "1.0.0", "@kbn/dev-utils": "1.0.0", "@kbn/es": "1.0.0", "@kbn/es-archiver": "1.0.0", @@ -248,13 +253,16 @@ "@microsoft/api-documenter": "7.7.2", "@microsoft/api-extractor": "7.7.0", "@percy/agent": "^0.26.0", - "@testing-library/react": "^9.3.2", - "@testing-library/react-hooks": "^3.2.1", + "@testing-library/dom": "^7.24.2", + "@testing-library/jest-dom": "^5.11.4", + "@testing-library/react": "^11.0.4", + "@testing-library/react-hooks": "^3.4.1", + "@testing-library/user-event": "^12.1.6", "@types/accept": "3.1.1", "@types/angular": "^1.6.56", "@types/angular-mocks": "^1.7.0", "@types/archiver": "^3.1.0", - "@types/babel__core": "^7.1.2", + "@types/babel__core": "^7.1.10", "@types/bluebird": "^3.1.1", "@types/boom": "^7.2.0", "@types/chance": "^1.0.0", @@ -273,7 +281,7 @@ "@types/flot": "^0.0.31", "@types/getopts": "^2.0.1", "@types/getos": "^3.0.0", - "@types/glob": "^7.1.1", + "@types/glob": "^7.1.2", "@types/globby": "^8.0.0", "@types/graphql": "^0.13.2", "@types/h2o2": "^8.1.1", @@ -284,7 +292,7 @@ "@types/hjson": "^2.4.2", "@types/hoek": "^4.1.3", "@types/inert": "^5.1.2", - "@types/jest": "^25.2.3", + "@types/jest": "^26.0.14", "@types/jest-when": "^2.7.1", "@types/joi": "^13.4.2", "@types/jquery": "^3.3.31", @@ -306,7 +314,7 @@ "@types/normalize-path": "^3.0.0", "@types/opn": "^5.1.0", "@types/pegjs": "^0.10.1", - "@types/pngjs": "^3.3.2", + "@types/pngjs": "^3.4.0", "@types/podium": "^1.0.0", "@types/prop-types": "^15.7.3", "@types/reach__router": "^1.2.6", @@ -324,19 +332,20 @@ "@types/selenium-webdriver": "^4.0.9", "@types/semver": "^5.5.0", "@types/sinon": "^7.0.13", - "@types/strip-ansi": "^3.0.0", + "@types/strip-ansi": "^5.2.1", "@types/styled-components": "^5.1.0", "@types/supertest": "^2.0.5", "@types/supertest-as-promised": "^2.0.38", + "@types/tapable": "^1.0.6", "@types/tar": "^4.0.3", - "@types/testing-library__dom": "^6.10.0", - "@types/testing-library__jest-dom": "^5.7.0", - "@types/testing-library__react": "^9.1.2", - "@types/testing-library__react-hooks": "^3.1.0", + "@types/testing-library__jest-dom": "^5.9.3", + "@types/testing-library__react-hooks": "^3.4.0", "@types/type-detect": "^4.0.1", "@types/uuid": "^3.4.4", "@types/vinyl": "^2.0.4", "@types/vinyl-fs": "^2.4.11", + "@types/webpack": "^4.41.3", + "@types/webpack-env": "^1.15.2", "@types/zen-observable": "^0.8.0", "@typescript-eslint/eslint-plugin": "^3.10.0", "@typescript-eslint/parser": "^3.10.0", @@ -346,16 +355,16 @@ "angular-route": "^1.8.0", "angular-sortable-view": "^0.0.17", "archiver": "^3.1.1", - "axe-core": "^3.4.1", + "axe-core": "^4.0.2", "babel-eslint": "^10.0.3", - "babel-jest": "^25.5.1", + "babel-jest": "^26.3.0", "babel-plugin-istanbul": "^6.0.0", - "backport": "5.5.1", + "backport": "5.6.0", "brace": "0.11.1", "chai": "3.5.0", "chance": "1.0.18", "cheerio": "0.22.0", - "chromedriver": "^84.0.0", + "chromedriver": "^86.0.0", "classnames": "2.2.6", "compare-versions": "3.5.1", "d3": "3.5.17", @@ -374,7 +383,7 @@ "eslint-plugin-cypress": "^2.8.1", "eslint-plugin-eslint-comments": "^3.2.0", "eslint-plugin-import": "^2.19.1", - "eslint-plugin-jest": "^23.10.0", + "eslint-plugin-jest": "^24.0.2", "eslint-plugin-jsx-a11y": "^6.2.3", "eslint-plugin-mocha": "^6.2.2", "eslint-plugin-no-unsanitized": "^3.0.2", @@ -389,7 +398,7 @@ "fetch-mock": "^7.3.9", "fp-ts": "^2.3.1", "geckodriver": "^1.20.0", - "getopts": "^2.2.4", + "getopts": "^2.2.5", "grunt": "1.0.4", "grunt-available-tasks": "^0.6.3", "grunt-cli": "^1.2.0", @@ -400,14 +409,13 @@ "gulp-sourcemaps": "2.6.5", "has-ansi": "^3.0.0", "history": "^4.9.0", - "hjson": "3.2.1", "iedriver": "^3.14.2", "immer": "^1.5.0", "intl-messageformat-parser": "^1.4.0", - "jest": "^25.5.4", + "jest": "^26.4.2", "jest-canvas-mock": "^2.2.0", - "jest-circus": "^25.5.4", - "jest-cli": "^25.5.4", + "jest-circus": "^26.4.2", + "jest-cli": "^26.4.2", "jest-environment-jsdom-thirteen": "^1.0.1", "jest-raw-loader": "^1.0.1", "jest-when": "^2.7.2", @@ -435,7 +443,7 @@ "multistream": "^2.1.1", "murmurhash3js": "3.0.1", "mutation-observer": "^1.0.3", - "ngreact": "0.5.1", + "ngreact": "^0.5.1", "nock": "12.0.3", "normalize-path": "^3.0.0", "nyc": "^15.0.1", @@ -463,18 +471,18 @@ "selenium-webdriver": "^4.0.0-alpha.7", "simple-git": "1.116.0", "sinon": "^7.4.2", - "strip-ansi": "^3.0.1", + "strip-ansi": "^6.0.0", "supertest": "^3.1.0", "supertest-as-promised": "^4.0.2", - "tape": "^4.13.0", + "tape": "^5.0.1", "topojson-client": "3.0.0", "tree-kill": "^1.2.2", "typescript": "4.0.2", "ui-select": "0.19.8", - "vega": "^5.13.0", - "vega-lite": "^4.13.1", - "vega-schema-url-parser": "^1.1.0", - "vega-tooltip": "^0.12.0", + "vega": "^5.17.0", + "vega-lite": "^4.16.8", + "vega-schema-url-parser": "^2.1.0", + "vega-tooltip": "^0.24.2", "vinyl-fs": "^3.0.3", "xml2js": "^0.4.22", "xmlbuilder": "13.0.2", diff --git a/packages/elastic-eslint-config-kibana/package.json b/packages/elastic-eslint-config-kibana/package.json index a4bb8d5449ee8..3f2c6e9edb261 100644 --- a/packages/elastic-eslint-config-kibana/package.json +++ b/packages/elastic-eslint-config-kibana/package.json @@ -24,7 +24,7 @@ "eslint-plugin-jsx-a11y": "^6.2.3", "eslint-plugin-eslint-comments": "^3.2.0", "eslint-plugin-import": "^2.19.1", - "eslint-plugin-jest": "^23.10.0", + "eslint-plugin-jest": "^24.0.2", "eslint-plugin-mocha": "^6.2.2", "eslint-plugin-no-unsanitized": "^3.0.2", "eslint-plugin-prefer-object-spread": "^1.2.1", diff --git a/packages/kbn-ace/README.md b/packages/kbn-ace/README.md new file mode 100644 index 0000000000000..c11d5cc2f24b8 --- /dev/null +++ b/packages/kbn-ace/README.md @@ -0,0 +1,20 @@ +# @kbn/ace + +This package contains the XJSON mode for brace. This is an extension of the `brace/mode/json` mode. + +This package also contains an import of the entire brace editor which is used for creating the custom XJSON worker. + +## Note to plugins +_This code should not be eagerly loaded_. + +Make sure imports of this package are behind a lazy-load `import()` statement. + +Your plugin should already be loading application code this way in the `mount` function. + +## Deprecated + +This package is considered deprecated and will be removed in future. + +New and existing editor functionality should use Monaco. + +_Do not add new functionality to this package_. Build new functionality for Monaco and use it instead. diff --git a/packages/kbn-ace/package.json b/packages/kbn-ace/package.json new file mode 100644 index 0000000000000..6f1cee764adf1 --- /dev/null +++ b/packages/kbn-ace/package.json @@ -0,0 +1,20 @@ +{ + "name": "@kbn/ace", + "version": "1.0.0", + "private": true, + "main": "./target/index.js", + "license": "Apache-2.0", + "scripts": { + "build": "node ./scripts/build.js", + "kbn:bootstrap": "yarn build --dev" + }, + "dependencies": { + "brace": "0.11.1" + }, + "devDependencies": { + "@kbn/dev-utils": "1.0.0", + "@kbn/babel-preset": "1.0.0", + "raw-loader": "^3.1.0", + "typescript": "4.0.2" + } +} diff --git a/packages/kbn-ace/scripts/build.js b/packages/kbn-ace/scripts/build.js new file mode 100644 index 0000000000000..2f570ffba1fc6 --- /dev/null +++ b/packages/kbn-ace/scripts/build.js @@ -0,0 +1,65 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +const path = require('path'); +const del = require('del'); +const fs = require('fs'); +const supportsColor = require('supports-color'); +const { run } = require('@kbn/dev-utils'); + +const TARGET_BUILD_DIR = path.resolve(__dirname, '../target'); +const ROOT_DIR = path.resolve(__dirname, '../'); +const WORKER_PATH_SECTION = 'ace/modes/x_json/worker/x_json.ace.worker.js'; + +run( + async ({ procRunner, log }) => { + log.info('Deleting old output'); + + await del(TARGET_BUILD_DIR); + + const cwd = ROOT_DIR; + const env = { ...process.env }; + + if (supportsColor.stdout) { + env.FORCE_COLOR = 'true'; + } + + await procRunner.run('tsc ', { + cmd: 'tsc', + args: [], + wait: true, + env, + cwd, + }); + + log.success('Copying worker file to target.'); + + fs.copyFileSync( + path.resolve(__dirname, '..', 'src', WORKER_PATH_SECTION), + path.resolve(__dirname, '..', 'target', WORKER_PATH_SECTION) + ); + + log.success('Complete'); + }, + { + flags: { + boolean: ['dev'], + }, + } +); diff --git a/src/plugins/es_ui_shared/public/console_lang/ace/modes/index.ts b/packages/kbn-ace/src/ace/modes/index.ts similarity index 100% rename from src/plugins/es_ui_shared/public/console_lang/ace/modes/index.ts rename to packages/kbn-ace/src/ace/modes/index.ts diff --git a/src/plugins/es_ui_shared/public/console_lang/ace/modes/lexer_rules/elasticsearch_sql_highlight_rules.ts b/packages/kbn-ace/src/ace/modes/lexer_rules/elasticsearch_sql_highlight_rules.ts similarity index 100% rename from src/plugins/es_ui_shared/public/console_lang/ace/modes/lexer_rules/elasticsearch_sql_highlight_rules.ts rename to packages/kbn-ace/src/ace/modes/lexer_rules/elasticsearch_sql_highlight_rules.ts diff --git a/src/plugins/es_ui_shared/public/console_lang/ace/modes/lexer_rules/index.ts b/packages/kbn-ace/src/ace/modes/lexer_rules/index.ts similarity index 100% rename from src/plugins/es_ui_shared/public/console_lang/ace/modes/lexer_rules/index.ts rename to packages/kbn-ace/src/ace/modes/lexer_rules/index.ts diff --git a/src/plugins/es_ui_shared/public/console_lang/ace/modes/lexer_rules/script_highlight_rules.ts b/packages/kbn-ace/src/ace/modes/lexer_rules/script_highlight_rules.ts similarity index 100% rename from src/plugins/es_ui_shared/public/console_lang/ace/modes/lexer_rules/script_highlight_rules.ts rename to packages/kbn-ace/src/ace/modes/lexer_rules/script_highlight_rules.ts diff --git a/src/plugins/es_ui_shared/public/console_lang/ace/modes/lexer_rules/x_json_highlight_rules.ts b/packages/kbn-ace/src/ace/modes/lexer_rules/x_json_highlight_rules.ts similarity index 100% rename from src/plugins/es_ui_shared/public/console_lang/ace/modes/lexer_rules/x_json_highlight_rules.ts rename to packages/kbn-ace/src/ace/modes/lexer_rules/x_json_highlight_rules.ts diff --git a/src/plugins/es_ui_shared/public/console_lang/ace/modes/x_json/index.ts b/packages/kbn-ace/src/ace/modes/x_json/index.ts similarity index 100% rename from src/plugins/es_ui_shared/public/console_lang/ace/modes/x_json/index.ts rename to packages/kbn-ace/src/ace/modes/x_json/index.ts diff --git a/src/plugins/es_ui_shared/public/console_lang/ace/modes/x_json/worker/index.ts b/packages/kbn-ace/src/ace/modes/x_json/worker/index.ts similarity index 100% rename from src/plugins/es_ui_shared/public/console_lang/ace/modes/x_json/worker/index.ts rename to packages/kbn-ace/src/ace/modes/x_json/worker/index.ts diff --git a/src/plugins/es_ui_shared/public/console_lang/ace/modes/x_json/worker/worker.d.ts b/packages/kbn-ace/src/ace/modes/x_json/worker/worker.d.ts similarity index 100% rename from src/plugins/es_ui_shared/public/console_lang/ace/modes/x_json/worker/worker.d.ts rename to packages/kbn-ace/src/ace/modes/x_json/worker/worker.d.ts diff --git a/src/plugins/es_ui_shared/public/console_lang/ace/modes/x_json/worker/x_json.ace.worker.js b/packages/kbn-ace/src/ace/modes/x_json/worker/x_json.ace.worker.js similarity index 100% rename from src/plugins/es_ui_shared/public/console_lang/ace/modes/x_json/worker/x_json.ace.worker.js rename to packages/kbn-ace/src/ace/modes/x_json/worker/x_json.ace.worker.js diff --git a/src/plugins/es_ui_shared/public/console_lang/ace/modes/x_json/x_json.ts b/packages/kbn-ace/src/ace/modes/x_json/x_json.ts similarity index 100% rename from src/plugins/es_ui_shared/public/console_lang/ace/modes/x_json/x_json.ts rename to packages/kbn-ace/src/ace/modes/x_json/x_json.ts diff --git a/packages/kbn-ace/src/index.ts b/packages/kbn-ace/src/index.ts new file mode 100644 index 0000000000000..62a6dbb948997 --- /dev/null +++ b/packages/kbn-ace/src/index.ts @@ -0,0 +1,27 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export { + ElasticsearchSqlHighlightRules, + ScriptHighlightRules, + XJsonHighlightRules, + addXJsonToRules, + XJsonMode, + installXJsonMode, +} from './ace/modes'; diff --git a/packages/kbn-ace/tsconfig.json b/packages/kbn-ace/tsconfig.json new file mode 100644 index 0000000000000..6d3f433c6a6d1 --- /dev/null +++ b/packages/kbn-ace/tsconfig.json @@ -0,0 +1,15 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "outDir": "./target", + "declaration": true, + "sourceMap": true, + "types": [ + "jest", + "node" + ] + }, + "include": [ + "src/**/*" + ] +} diff --git a/packages/kbn-ace/yarn.lock b/packages/kbn-ace/yarn.lock new file mode 120000 index 0000000000000..3f82ebc9cdbae --- /dev/null +++ b/packages/kbn-ace/yarn.lock @@ -0,0 +1 @@ +../../yarn.lock \ No newline at end of file diff --git a/packages/kbn-apm-config-loader/README.md b/packages/kbn-apm-config-loader/README.md new file mode 100644 index 0000000000000..51623dc745f2c --- /dev/null +++ b/packages/kbn-apm-config-loader/README.md @@ -0,0 +1,13 @@ +# @kbn/apm-config-loader + +Configuration loader for the APM instrumentation script. + +This module is only meant to be used by the APM instrumentation script (`src/apm.js`) +to load the required configuration options from the `kibana.yaml` configuration file with +default values. + +### Why not just use @kbn-config? + +`@kbn/config` is the recommended way to load and read the kibana configuration file, +however in the specific case of APM, we want to only need the minimal dependencies +before loading `elastic-apm-node` to avoid losing instrumentation on the already loaded modules. \ No newline at end of file diff --git a/packages/kbn-apm-config-loader/__fixtures__/config.yml b/packages/kbn-apm-config-loader/__fixtures__/config.yml new file mode 100644 index 0000000000000..b0706d8ff8ea0 --- /dev/null +++ b/packages/kbn-apm-config-loader/__fixtures__/config.yml @@ -0,0 +1,11 @@ +pid: + enabled: true + file: '/var/run/kibana.pid' + obj: { val: 3 } + arr: [1] + empty_obj: {} + empty_arr: [] +obj: { val: 3 } +arr: [1, 2] +empty_obj: {} +empty_arr: [] diff --git a/packages/kbn-apm-config-loader/__fixtures__/config_flat.yml b/packages/kbn-apm-config-loader/__fixtures__/config_flat.yml new file mode 100644 index 0000000000000..a687a9a9088bf --- /dev/null +++ b/packages/kbn-apm-config-loader/__fixtures__/config_flat.yml @@ -0,0 +1,6 @@ +pid.enabled: true +pid.file: '/var/run/kibana.pid' +pid.obj: { val: 3 } +pid.arr: [1, 2] +pid.empty_obj: {} +pid.empty_arr: [] diff --git a/packages/kbn-apm-config-loader/__fixtures__/en_var_ref_config.yml b/packages/kbn-apm-config-loader/__fixtures__/en_var_ref_config.yml new file mode 100644 index 0000000000000..761f6a43ba452 --- /dev/null +++ b/packages/kbn-apm-config-loader/__fixtures__/en_var_ref_config.yml @@ -0,0 +1,5 @@ +foo: 1 +bar: "pre-${KBN_ENV_VAR1}-mid-${KBN_ENV_VAR2}-post" + +elasticsearch: + requestHeadersWhitelist: ["${KBN_ENV_VAR1}", "${KBN_ENV_VAR2}"] diff --git a/packages/kbn-apm-config-loader/__fixtures__/one.yml b/packages/kbn-apm-config-loader/__fixtures__/one.yml new file mode 100644 index 0000000000000..ccef51b546194 --- /dev/null +++ b/packages/kbn-apm-config-loader/__fixtures__/one.yml @@ -0,0 +1,9 @@ +foo: 1 +bar: true +xyz: ['1', '2'] +empty_arr: [] +abc: + def: test + qwe: 1 + zyx: { val: 1 } +pom.bom: 3 diff --git a/packages/kbn-apm-config-loader/__fixtures__/two.yml b/packages/kbn-apm-config-loader/__fixtures__/two.yml new file mode 100644 index 0000000000000..a2ec41265d50f --- /dev/null +++ b/packages/kbn-apm-config-loader/__fixtures__/two.yml @@ -0,0 +1,10 @@ +foo: 2 +baz: bonkers +xyz: ['3', '4'] +arr: [1] +empty_arr: [] +abc: + ghi: test2 + qwe: 2 + zyx: {} +pom.mob: 4 diff --git a/packages/kbn-apm-config-loader/package.json b/packages/kbn-apm-config-loader/package.json new file mode 100644 index 0000000000000..6865e9ec9bf66 --- /dev/null +++ b/packages/kbn-apm-config-loader/package.json @@ -0,0 +1,23 @@ +{ + "name": "@kbn/apm-config-loader", + "main": "./target/index.js", + "types": "./target/index.d.ts", + "version": "1.0.0", + "license": "Apache-2.0", + "private": true, + "scripts": { + "build": "tsc", + "kbn:bootstrap": "yarn build", + "kbn:watch": "yarn build --watch" + }, + "dependencies": { + "@elastic/safer-lodash-set": "0.0.0", + "@kbn/utils": "1.0.0", + "js-yaml": "^3.14.0", + "lodash": "^4.17.20" + }, + "devDependencies": { + "typescript": "4.0.2", + "tsd": "^0.13.1" + } +} diff --git a/packages/kbn-apm-config-loader/src/config.test.mocks.ts b/packages/kbn-apm-config-loader/src/config.test.mocks.ts new file mode 100644 index 0000000000000..a0422665a55d2 --- /dev/null +++ b/packages/kbn-apm-config-loader/src/config.test.mocks.ts @@ -0,0 +1,66 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { join } from 'path'; +const childProcessModule = jest.requireActual('child_process'); +const fsModule = jest.requireActual('fs'); + +export const mockedRootDir = '/root'; + +export const packageMock = { + raw: {} as any, +}; +jest.doMock(join(mockedRootDir, 'package.json'), () => packageMock.raw, { virtual: true }); + +export const devConfigMock = { + raw: {} as any, +}; +jest.doMock(join(mockedRootDir, 'config', 'apm.dev.js'), () => devConfigMock.raw, { + virtual: true, +}); + +export const gitRevExecMock = jest.fn(); +jest.doMock('child_process', () => ({ + ...childProcessModule, + execSync: (command: string, options: any) => { + if (command.startsWith('git rev-parse')) { + return gitRevExecMock(command, options); + } + return childProcessModule.execSync(command, options); + }, +})); + +export const readUuidFileMock = jest.fn(); +jest.doMock('fs', () => ({ + ...fsModule, + readFileSync: (path: string, options: any) => { + if (path.endsWith('uuid')) { + return readUuidFileMock(path, options); + } + return fsModule.readFileSync(path, options); + }, +})); + +export const resetAllMocks = () => { + packageMock.raw = {}; + devConfigMock.raw = {}; + gitRevExecMock.mockReset(); + readUuidFileMock.mockReset(); + jest.resetModules(); +}; diff --git a/packages/kbn-apm-config-loader/src/config.test.ts b/packages/kbn-apm-config-loader/src/config.test.ts new file mode 100644 index 0000000000000..83438215716ac --- /dev/null +++ b/packages/kbn-apm-config-loader/src/config.test.ts @@ -0,0 +1,159 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { + packageMock, + mockedRootDir, + gitRevExecMock, + devConfigMock, + readUuidFileMock, + resetAllMocks, +} from './config.test.mocks'; + +import { ApmConfiguration } from './config'; + +describe('ApmConfiguration', () => { + beforeEach(() => { + packageMock.raw = { + version: '8.0.0', + build: { + sha: 'sha', + }, + }; + }); + + afterEach(() => { + resetAllMocks(); + }); + + it('sets the correct service name and version', () => { + packageMock.raw = { + version: '9.2.1', + }; + const config = new ApmConfiguration(mockedRootDir, {}, false); + expect(config.getConfig('myservice').serviceName).toBe('myservice'); + expect(config.getConfig('myservice').serviceVersion).toBe('9.2.1'); + }); + + it('sets the git revision from `git rev-parse` command in non distribution mode', () => { + gitRevExecMock.mockReturnValue('some-git-rev'); + const config = new ApmConfiguration(mockedRootDir, {}, false); + expect(config.getConfig('serviceName').globalLabels.git_rev).toBe('some-git-rev'); + }); + + it('sets the git revision from `pkg.build.sha` in distribution mode', () => { + gitRevExecMock.mockReturnValue('dev-sha'); + packageMock.raw = { + version: '9.2.1', + build: { + sha: 'distribution-sha', + }, + }; + const config = new ApmConfiguration(mockedRootDir, {}, true); + expect(config.getConfig('serviceName').globalLabels.git_rev).toBe('distribution-sha'); + }); + + it('reads the kibana uuid from the uuid file', () => { + readUuidFileMock.mockReturnValue('instance-uuid'); + const config = new ApmConfiguration(mockedRootDir, {}, false); + expect(config.getConfig('serviceName').globalLabels.kibana_uuid).toBe('instance-uuid'); + }); + + it('uses the uuid from the kibana config if present', () => { + readUuidFileMock.mockReturnValue('uuid-from-file'); + const kibanaConfig = { + server: { + uuid: 'uuid-from-config', + }, + }; + const config = new ApmConfiguration(mockedRootDir, kibanaConfig, false); + expect(config.getConfig('serviceName').globalLabels.kibana_uuid).toBe('uuid-from-config'); + }); + + it('uses the correct default config depending on the `isDistributable` parameter', () => { + let config = new ApmConfiguration(mockedRootDir, {}, false); + expect(config.getConfig('serviceName')).toEqual( + expect.objectContaining({ + serverUrl: expect.any(String), + secretToken: expect.any(String), + }) + ); + + config = new ApmConfiguration(mockedRootDir, {}, true); + expect(Object.keys(config.getConfig('serviceName'))).not.toContain('serverUrl'); + }); + + it('loads the configuration from the kibana config file', () => { + const kibanaConfig = { + elastic: { + apm: { + active: true, + serverUrl: 'https://url', + secretToken: 'secret', + }, + }, + }; + const config = new ApmConfiguration(mockedRootDir, kibanaConfig, true); + expect(config.getConfig('serviceName')).toEqual( + expect.objectContaining({ + active: true, + serverUrl: 'https://url', + secretToken: 'secret', + }) + ); + }); + + it('loads the configuration from the dev config is present', () => { + devConfigMock.raw = { + active: true, + serverUrl: 'https://dev-url.co', + }; + const config = new ApmConfiguration(mockedRootDir, {}, true); + expect(config.getConfig('serviceName')).toEqual( + expect.objectContaining({ + active: true, + serverUrl: 'https://dev-url.co', + }) + ); + }); + + it('respect the precedence of the dev config', () => { + const kibanaConfig = { + elastic: { + apm: { + active: true, + serverUrl: 'https://url', + secretToken: 'secret', + }, + }, + }; + devConfigMock.raw = { + active: true, + serverUrl: 'https://dev-url.co', + }; + const config = new ApmConfiguration(mockedRootDir, kibanaConfig, true); + expect(config.getConfig('serviceName')).toEqual( + expect.objectContaining({ + active: true, + serverUrl: 'https://dev-url.co', + secretToken: 'secret', + }) + ); + }); +}); diff --git a/packages/kbn-apm-config-loader/src/config.ts b/packages/kbn-apm-config-loader/src/config.ts new file mode 100644 index 0000000000000..897e7fd7ca610 --- /dev/null +++ b/packages/kbn-apm-config-loader/src/config.ts @@ -0,0 +1,162 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { join } from 'path'; +import { merge, get } from 'lodash'; +import { execSync } from 'child_process'; +// deep import to avoid loading the whole package +import { getDataPath } from '@kbn/utils/target/path'; +import { readFileSync } from 'fs'; +import { ApmAgentConfig } from './types'; + +const getDefaultConfig = (isDistributable: boolean): ApmAgentConfig => { + if (isDistributable) { + return { + active: false, + globalLabels: {}, + // Do not use a centralized controlled config + centralConfig: false, + // Capture all exceptions that are not caught + logUncaughtExceptions: true, + // Can be performance intensive, disabling by default + breakdownMetrics: false, + }; + } + + return { + active: false, + serverUrl: 'https://f1542b814f674090afd914960583265f.apm.us-central1.gcp.cloud.es.io:443', + // The secretToken below is intended to be hardcoded in this file even though + // it makes it public. This is not a security/privacy issue. Normally we'd + // instead disable the need for a secretToken in the APM Server config where + // the data is transmitted to, but due to how it's being hosted, it's easier, + // for now, to simply leave it in. + secretToken: 'R0Gjg46pE9K9wGestd', + globalLabels: {}, + breakdownMetrics: true, + centralConfig: false, + logUncaughtExceptions: true, + }; +}; + +export class ApmConfiguration { + private baseConfig?: any; + private kibanaVersion: string; + private pkgBuild: Record; + + constructor( + private readonly rootDir: string, + private readonly rawKibanaConfig: Record, + private readonly isDistributable: boolean + ) { + // eslint-disable-next-line @typescript-eslint/no-var-requires + const { version, build } = require(join(this.rootDir, 'package.json')); + this.kibanaVersion = version; + this.pkgBuild = build; + } + + public getConfig(serviceName: string): ApmAgentConfig { + return { + ...this.getBaseConfig(), + serviceName, + }; + } + + private getBaseConfig() { + if (!this.baseConfig) { + const apmConfig = merge( + getDefaultConfig(this.isDistributable), + this.getConfigFromKibanaConfig(), + this.getDevConfig(), + this.getDistConfig() + ); + + const rev = this.getGitRev(); + if (rev !== null) { + apmConfig.globalLabels.git_rev = rev; + } + + const uuid = this.getKibanaUuid(); + if (uuid) { + apmConfig.globalLabels.kibana_uuid = uuid; + } + + apmConfig.serviceVersion = this.kibanaVersion; + this.baseConfig = apmConfig; + } + + return this.baseConfig; + } + + private getConfigFromKibanaConfig(): ApmAgentConfig { + return get(this.rawKibanaConfig, 'elastic.apm', {}); + } + + private getKibanaUuid() { + // try to access the `server.uuid` value from the config file first. + // if not manually defined, we will then read the value from the `{DATA_FOLDER}/uuid` file. + // note that as the file is created by the platform AFTER apm init, the file + // will not be present at first startup, but there is nothing we can really do about that. + if (get(this.rawKibanaConfig, 'server.uuid')) { + return this.rawKibanaConfig.server.uuid; + } + + const dataPath: string = get(this.rawKibanaConfig, 'path.data') || getDataPath(); + try { + const filename = join(dataPath, 'uuid'); + return readFileSync(filename, 'utf-8'); + } catch (e) {} // eslint-disable-line no-empty + } + + private getDevConfig(): ApmAgentConfig { + try { + const apmDevConfigPath = join(this.rootDir, 'config', 'apm.dev.js'); + return require(apmDevConfigPath); + } catch (e) { + return {}; + } + } + + /** Config keys that cannot be overridden in production builds */ + private getDistConfig(): ApmAgentConfig { + if (!this.isDistributable) { + return {}; + } + + return { + // Headers & body may contain sensitive info + captureHeaders: false, + captureBody: 'off', + }; + } + + private getGitRev() { + if (this.isDistributable) { + return this.pkgBuild.sha; + } + try { + return execSync('git rev-parse --short HEAD', { + encoding: 'utf-8' as BufferEncoding, + stdio: ['ignore', 'pipe', 'ignore'], + }).trim(); + } catch (e) { + return null; + } + } +} diff --git a/packages/kbn-apm-config-loader/src/config_loader.test.mocks.ts b/packages/kbn-apm-config-loader/src/config_loader.test.mocks.ts new file mode 100644 index 0000000000000..74b50d9daf632 --- /dev/null +++ b/packages/kbn-apm-config-loader/src/config_loader.test.mocks.ts @@ -0,0 +1,45 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export const getConfigurationFilePathsMock = jest.fn(); +jest.doMock('./utils/get_config_file_paths', () => ({ + getConfigurationFilePaths: getConfigurationFilePathsMock, +})); + +export const getConfigFromFilesMock = jest.fn(); +jest.doMock('./utils/read_config', () => ({ + getConfigFromFiles: getConfigFromFilesMock, +})); + +export const applyConfigOverridesMock = jest.fn(); +jest.doMock('./utils/apply_config_overrides', () => ({ + applyConfigOverrides: applyConfigOverridesMock, +})); + +export const ApmConfigurationMock = jest.fn(); +jest.doMock('./config', () => ({ + ApmConfiguration: ApmConfigurationMock, +})); + +export const resetAllMocks = () => { + getConfigurationFilePathsMock.mockReset(); + getConfigFromFilesMock.mockReset(); + applyConfigOverridesMock.mockReset(); + ApmConfigurationMock.mockReset(); +}; diff --git a/packages/kbn-apm-config-loader/src/config_loader.test.ts b/packages/kbn-apm-config-loader/src/config_loader.test.ts new file mode 100644 index 0000000000000..da59237de231e --- /dev/null +++ b/packages/kbn-apm-config-loader/src/config_loader.test.ts @@ -0,0 +1,75 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { + ApmConfigurationMock, + applyConfigOverridesMock, + getConfigFromFilesMock, + getConfigurationFilePathsMock, + resetAllMocks, +} from './config_loader.test.mocks'; + +import { loadConfiguration } from './config_loader'; + +describe('loadConfiguration', () => { + const argv = ['some', 'arbitrary', 'args']; + const rootDir = '/root/dir'; + const isDistributable = false; + + afterEach(() => { + resetAllMocks(); + }); + + it('calls `getConfigurationFilePaths` with the correct arguments', () => { + loadConfiguration(argv, rootDir, isDistributable); + expect(getConfigurationFilePathsMock).toHaveBeenCalledTimes(1); + expect(getConfigurationFilePathsMock).toHaveBeenCalledWith(argv); + }); + + it('calls `getConfigFromFiles` with the correct arguments', () => { + const configPaths = ['/path/to/config', '/path/to/other/config']; + getConfigurationFilePathsMock.mockReturnValue(configPaths); + + loadConfiguration(argv, rootDir, isDistributable); + expect(getConfigFromFilesMock).toHaveBeenCalledTimes(1); + expect(getConfigFromFilesMock).toHaveBeenCalledWith(configPaths); + }); + + it('calls `applyConfigOverrides` with the correct arguments', () => { + const config = { server: { uuid: 'uuid' } }; + getConfigFromFilesMock.mockReturnValue(config); + + loadConfiguration(argv, rootDir, isDistributable); + expect(applyConfigOverridesMock).toHaveBeenCalledTimes(1); + expect(applyConfigOverridesMock).toHaveBeenCalledWith(config, argv); + }); + + it('creates and return an `ApmConfiguration` instance', () => { + const apmInstance = { apmInstance: true }; + ApmConfigurationMock.mockImplementation(() => apmInstance); + + const config = { server: { uuid: 'uuid' } }; + getConfigFromFilesMock.mockReturnValue(config); + + const instance = loadConfiguration(argv, rootDir, isDistributable); + expect(ApmConfigurationMock).toHaveBeenCalledTimes(1); + expect(ApmConfigurationMock).toHaveBeenCalledWith(rootDir, config, isDistributable); + expect(instance).toBe(apmInstance); + }); +}); diff --git a/packages/kbn-apm-config-loader/src/config_loader.ts b/packages/kbn-apm-config-loader/src/config_loader.ts new file mode 100644 index 0000000000000..edddd445b9b7a --- /dev/null +++ b/packages/kbn-apm-config-loader/src/config_loader.ts @@ -0,0 +1,39 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { getConfigurationFilePaths, getConfigFromFiles, applyConfigOverrides } from './utils'; +import { ApmConfiguration } from './config'; + +/** + * Load the APM configuration. + * + * @param argv the `process.argv` arguments + * @param rootDir The root directory of kibana (where the sources and the `package.json` file are) + * @param production true for production builds, false otherwise + */ +export const loadConfiguration = ( + argv: string[], + rootDir: string, + isDistributable: boolean +): ApmConfiguration => { + const configPaths = getConfigurationFilePaths(argv); + const rawConfiguration = getConfigFromFiles(configPaths); + applyConfigOverrides(rawConfiguration, argv); + return new ApmConfiguration(rootDir, rawConfiguration, isDistributable); +}; diff --git a/packages/kbn-apm-config-loader/src/index.ts b/packages/kbn-apm-config-loader/src/index.ts new file mode 100644 index 0000000000000..0d9c057c7cf89 --- /dev/null +++ b/packages/kbn-apm-config-loader/src/index.ts @@ -0,0 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export { loadConfiguration } from './config_loader'; +export type { ApmConfiguration } from './config'; +export type { ApmAgentConfig } from './types'; diff --git a/packages/kbn-apm-config-loader/src/types.ts b/packages/kbn-apm-config-loader/src/types.ts new file mode 100644 index 0000000000000..172edfe0af009 --- /dev/null +++ b/packages/kbn-apm-config-loader/src/types.ts @@ -0,0 +1,24 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +// There is an (incomplete) `AgentConfigOptions` type declared in node_modules/elastic-apm-node/index.d.ts +// but it's not exported, and using ts tricks to retrieve the type via Parameters[0] +// causes errors in the generated .d.ts file because of esModuleInterop and the fact that the apm module +// is just exporting an instance of the `ApmAgent` type. +export type ApmAgentConfig = Record; diff --git a/packages/kbn-apm-config-loader/src/utils/__snapshots__/read_config.test.ts.snap b/packages/kbn-apm-config-loader/src/utils/__snapshots__/read_config.test.ts.snap new file mode 100644 index 0000000000000..afdce4e76d3f5 --- /dev/null +++ b/packages/kbn-apm-config-loader/src/utils/__snapshots__/read_config.test.ts.snap @@ -0,0 +1,108 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`different cwd() resolves relative files based on the cwd 1`] = ` +Object { + "abc": Object { + "def": "test", + "qwe": 1, + "zyx": Object { + "val": 1, + }, + }, + "bar": true, + "empty_arr": Array [], + "foo": 1, + "pom": Object { + "bom": 3, + }, + "xyz": Array [ + "1", + "2", + ], +} +`; + +exports[`reads and merges multiple yaml files from file system and parses to json 1`] = ` +Object { + "abc": Object { + "def": "test", + "ghi": "test2", + "qwe": 2, + "zyx": Object {}, + }, + "arr": Array [ + 1, + ], + "bar": true, + "baz": "bonkers", + "empty_arr": Array [], + "foo": 2, + "pom": Object { + "bom": 3, + "mob": 4, + }, + "xyz": Array [ + "3", + "4", + ], +} +`; + +exports[`reads single yaml from file system and parses to json 1`] = ` +Object { + "arr": Array [ + 1, + 2, + ], + "empty_arr": Array [], + "empty_obj": Object {}, + "obj": Object { + "val": 3, + }, + "pid": Object { + "arr": Array [ + 1, + ], + "empty_arr": Array [], + "empty_obj": Object {}, + "enabled": true, + "file": "/var/run/kibana.pid", + "obj": Object { + "val": 3, + }, + }, +} +`; + +exports[`returns a deep object 1`] = ` +Object { + "pid": Object { + "arr": Array [ + 1, + 2, + ], + "empty_arr": Array [], + "empty_obj": Object {}, + "enabled": true, + "file": "/var/run/kibana.pid", + "obj": Object { + "val": 3, + }, + }, +} +`; + +exports[`should inject an environment variable value when setting a value with \${ENV_VAR} 1`] = ` +Object { + "bar": "pre-val1-mid-val2-post", + "elasticsearch": Object { + "requestHeadersWhitelist": Array [ + "val1", + "val2", + ], + }, + "foo": 1, +} +`; + +exports[`should throw an exception when referenced environment variable in a config value does not exist 1`] = `"Unknown environment variable referenced in config : KBN_ENV_VAR1"`; diff --git a/packages/kbn-apm-config-loader/src/utils/apply_config_overrides.test.ts b/packages/kbn-apm-config-loader/src/utils/apply_config_overrides.test.ts new file mode 100644 index 0000000000000..1d86f7e1f6e8a --- /dev/null +++ b/packages/kbn-apm-config-loader/src/utils/apply_config_overrides.test.ts @@ -0,0 +1,58 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { applyConfigOverrides } from './apply_config_overrides'; + +describe('applyConfigOverrides', () => { + it('overrides `server.uuid` when provided as a command line argument', () => { + const config: Record = { + server: { + uuid: 'from-config', + }, + }; + const argv = ['--server.uuid', 'from-argv']; + + applyConfigOverrides(config, argv); + + expect(config.server.uuid).toEqual('from-argv'); + }); + + it('overrides `path.data` when provided as a command line argument', () => { + const config: Record = { + path: { + data: '/from/config', + }, + }; + const argv = ['--path.data', '/from/argv']; + + applyConfigOverrides(config, argv); + + expect(config.path.data).toEqual('/from/argv'); + }); + + it('properly set the overridden properties even if the parent object is not present in the config', () => { + const config: Record = {}; + const argv = ['--server.uuid', 'from-argv', '--path.data', '/data-path']; + + applyConfigOverrides(config, argv); + + expect(config.server.uuid).toEqual('from-argv'); + expect(config.path.data).toEqual('/data-path'); + }); +}); diff --git a/packages/kbn-apm-config-loader/src/utils/apply_config_overrides.ts b/packages/kbn-apm-config-loader/src/utils/apply_config_overrides.ts new file mode 100644 index 0000000000000..6a3bf95f9954d --- /dev/null +++ b/packages/kbn-apm-config-loader/src/utils/apply_config_overrides.ts @@ -0,0 +1,38 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { set } from '@elastic/safer-lodash-set'; +import { getArgValue } from './read_argv'; + +/** + * Manually applies the specific configuration overrides we need to load the APM config. + * Currently, only these are needed: + * - server.uuid + * - path.data + */ +export const applyConfigOverrides = (config: Record, argv: string[]) => { + const serverUuid = getArgValue(argv, '--server.uuid'); + if (serverUuid) { + set(config, 'server.uuid', serverUuid); + } + const dataPath = getArgValue(argv, '--path.data'); + if (dataPath) { + set(config, 'path.data', dataPath); + } +}; diff --git a/packages/kbn-apm-config-loader/src/utils/ensure_deep_object.test.ts b/packages/kbn-apm-config-loader/src/utils/ensure_deep_object.test.ts new file mode 100644 index 0000000000000..5a520fbeef316 --- /dev/null +++ b/packages/kbn-apm-config-loader/src/utils/ensure_deep_object.test.ts @@ -0,0 +1,156 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { ensureDeepObject } from './ensure_deep_object'; + +test('flat object', () => { + const obj = { + 'foo.a': 1, + 'foo.b': 2, + }; + + expect(ensureDeepObject(obj)).toEqual({ + foo: { + a: 1, + b: 2, + }, + }); +}); + +test('deep object', () => { + const obj = { + foo: { + a: 1, + b: 2, + }, + }; + + expect(ensureDeepObject(obj)).toEqual({ + foo: { + a: 1, + b: 2, + }, + }); +}); + +test('flat within deep object', () => { + const obj = { + foo: { + b: 2, + 'bar.a': 1, + }, + }; + + expect(ensureDeepObject(obj)).toEqual({ + foo: { + b: 2, + bar: { + a: 1, + }, + }, + }); +}); + +test('flat then flat object', () => { + const obj = { + 'foo.bar': { + b: 2, + 'quux.a': 1, + }, + }; + + expect(ensureDeepObject(obj)).toEqual({ + foo: { + bar: { + b: 2, + quux: { + a: 1, + }, + }, + }, + }); +}); + +test('full with empty array', () => { + const obj = { + a: 1, + b: [], + }; + + expect(ensureDeepObject(obj)).toEqual({ + a: 1, + b: [], + }); +}); + +test('full with array of primitive values', () => { + const obj = { + a: 1, + b: [1, 2, 3], + }; + + expect(ensureDeepObject(obj)).toEqual({ + a: 1, + b: [1, 2, 3], + }); +}); + +test('full with array of full objects', () => { + const obj = { + a: 1, + b: [{ c: 2 }, { d: 3 }], + }; + + expect(ensureDeepObject(obj)).toEqual({ + a: 1, + b: [{ c: 2 }, { d: 3 }], + }); +}); + +test('full with array of flat objects', () => { + const obj = { + a: 1, + b: [{ 'c.d': 2 }, { 'e.f': 3 }], + }; + + expect(ensureDeepObject(obj)).toEqual({ + a: 1, + b: [{ c: { d: 2 } }, { e: { f: 3 } }], + }); +}); + +test('flat with flat and array of flat objects', () => { + const obj = { + a: 1, + 'b.c': 2, + d: [3, { 'e.f': 4 }, { 'g.h': 5 }], + }; + + expect(ensureDeepObject(obj)).toEqual({ + a: 1, + b: { c: 2 }, + d: [3, { e: { f: 4 } }, { g: { h: 5 } }], + }); +}); + +test('array composed of flat objects', () => { + const arr = [{ 'c.d': 2 }, { 'e.f': 3 }]; + + expect(ensureDeepObject(arr)).toEqual([{ c: { d: 2 } }, { e: { f: 3 } }]); +}); diff --git a/packages/kbn-apm-config-loader/src/utils/ensure_deep_object.ts b/packages/kbn-apm-config-loader/src/utils/ensure_deep_object.ts new file mode 100644 index 0000000000000..6eaaef983355c --- /dev/null +++ b/packages/kbn-apm-config-loader/src/utils/ensure_deep_object.ts @@ -0,0 +1,61 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +const separator = '.'; + +/** + * Recursively traverses through the object's properties and expands ones with + * dot-separated names into nested objects (eg. { a.b: 'c'} -> { a: { b: 'c' }). + * @param obj Object to traverse through. + * @returns Same object instance with expanded properties. + */ +export function ensureDeepObject(obj: any): any { + if (obj == null || typeof obj !== 'object') { + return obj; + } + + if (Array.isArray(obj)) { + return obj.map((item) => ensureDeepObject(item)); + } + + return Object.keys(obj).reduce((fullObject, propertyKey) => { + const propertyValue = obj[propertyKey]; + if (!propertyKey.includes(separator)) { + fullObject[propertyKey] = ensureDeepObject(propertyValue); + } else { + walk(fullObject, propertyKey.split(separator), propertyValue); + } + + return fullObject; + }, {} as any); +} + +function walk(obj: any, keys: string[], value: any) { + const key = keys.shift()!; + if (keys.length === 0) { + obj[key] = value; + return; + } + + if (obj[key] === undefined) { + obj[key] = {}; + } + + walk(obj[key], keys, ensureDeepObject(value)); +} diff --git a/packages/kbn-apm-config-loader/src/utils/get_config_file_paths.test.ts b/packages/kbn-apm-config-loader/src/utils/get_config_file_paths.test.ts new file mode 100644 index 0000000000000..c18069f21180b --- /dev/null +++ b/packages/kbn-apm-config-loader/src/utils/get_config_file_paths.test.ts @@ -0,0 +1,39 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { resolve, join } from 'path'; +import { getConfigPath } from '@kbn/utils'; +import { getConfigurationFilePaths } from './get_config_file_paths'; + +describe('getConfigurationFilePaths', () => { + const cwd = process.cwd(); + + it('retrieve the config file paths from the command line arguments', () => { + const argv = ['--config', './relative-path', '-c', '/absolute-path']; + + expect(getConfigurationFilePaths(argv)).toEqual([ + resolve(cwd, join('.', 'relative-path')), + '/absolute-path', + ]); + }); + + it('fallbacks to `getConfigPath` value', () => { + expect(getConfigurationFilePaths([])).toEqual([getConfigPath()]); + }); +}); diff --git a/packages/kbn-apm-config-loader/src/utils/get_config_file_paths.ts b/packages/kbn-apm-config-loader/src/utils/get_config_file_paths.ts new file mode 100644 index 0000000000000..262f0d1c8b3f5 --- /dev/null +++ b/packages/kbn-apm-config-loader/src/utils/get_config_file_paths.ts @@ -0,0 +1,37 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { resolve } from 'path'; +// deep import to avoid loading the whole package +import { getConfigPath } from '@kbn/utils/target/path'; +import { getArgValues } from './read_argv'; + +/** + * Return the configuration files that needs to be loaded. + * + * This mimics the behavior of the `src/cli/serve/serve.js` cli script by reading + * `-c` and `--config` options from process.argv, and fallbacks to `@kbn/utils`'s `getConfigPath()` + */ +export const getConfigurationFilePaths = (argv: string[]): string[] => { + const rawPaths = getArgValues(argv, ['-c', '--config']); + if (rawPaths.length) { + return rawPaths.map((path) => resolve(process.cwd(), path)); + } + return [getConfigPath()]; +}; diff --git a/packages/kbn-apm-config-loader/src/utils/index.ts b/packages/kbn-apm-config-loader/src/utils/index.ts new file mode 100644 index 0000000000000..03a44e31a44d5 --- /dev/null +++ b/packages/kbn-apm-config-loader/src/utils/index.ts @@ -0,0 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export { getConfigFromFiles } from './read_config'; +export { getConfigurationFilePaths } from './get_config_file_paths'; +export { applyConfigOverrides } from './apply_config_overrides'; diff --git a/packages/kbn-apm-config-loader/src/utils/read_argv.test.ts b/packages/kbn-apm-config-loader/src/utils/read_argv.test.ts new file mode 100644 index 0000000000000..282810e71681e --- /dev/null +++ b/packages/kbn-apm-config-loader/src/utils/read_argv.test.ts @@ -0,0 +1,80 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { getArgValue, getArgValues } from './read_argv'; + +describe('getArgValues', () => { + it('retrieve the arg value from the provided argv arguments', () => { + const argValues = getArgValues( + ['--config', 'my-config', '--foo', '-b', 'bar', '--config', 'other-config', '--baz'], + '--config' + ); + expect(argValues).toEqual(['my-config', 'other-config']); + }); + + it('accept aliases', () => { + const argValues = getArgValues( + ['--config', 'my-config', '--foo', '-b', 'bar', '-c', 'other-config', '--baz'], + ['--config', '-c'] + ); + expect(argValues).toEqual(['my-config', 'other-config']); + }); + + it('returns an empty array when the arg is not found', () => { + const argValues = getArgValues( + ['--config', 'my-config', '--foo', '-b', 'bar', '-c', 'other-config', '--baz'], + '--unicorn' + ); + expect(argValues).toEqual([]); + }); + + it('ignores the flag when no value is provided', () => { + const argValues = getArgValues( + ['-c', 'my-config', '--foo', '-b', 'bar', '--config'], + ['--config', '-c'] + ); + expect(argValues).toEqual(['my-config']); + }); +}); + +describe('getArgValue', () => { + it('retrieve the first arg value from the provided argv arguments', () => { + const argValues = getArgValue( + ['--config', 'my-config', '--foo', '-b', 'bar', '--config', 'other-config', '--baz'], + '--config' + ); + expect(argValues).toEqual('my-config'); + }); + + it('accept aliases', () => { + const argValues = getArgValue( + ['-c', 'my-config', '--foo', '-b', 'bar', '--config', 'other-config', '--baz'], + ['--config', '-c'] + ); + expect(argValues).toEqual('my-config'); + }); + + it('returns undefined the arg is not found', () => { + const argValues = getArgValue( + ['--config', 'my-config', '--foo', '-b', 'bar', '-c', 'other-config', '--baz'], + '--unicorn' + ); + expect(argValues).toBeUndefined(); + }); +}); diff --git a/packages/kbn-apm-config-loader/src/utils/read_argv.ts b/packages/kbn-apm-config-loader/src/utils/read_argv.ts new file mode 100644 index 0000000000000..9a74d5344a0fc --- /dev/null +++ b/packages/kbn-apm-config-loader/src/utils/read_argv.ts @@ -0,0 +1,36 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export const getArgValues = (argv: string[], flag: string | string[]): string[] => { + const flags = typeof flag === 'string' ? [flag] : flag; + const values: string[] = []; + for (let i = 0; i < argv.length; i++) { + if (flags.includes(argv[i]) && argv[i + 1]) { + values.push(argv[++i]); + } + } + return values; +}; + +export const getArgValue = (argv: string[], flag: string | string[]): string | undefined => { + const values = getArgValues(argv, flag); + if (values.length) { + return values[0]; + } +}; diff --git a/packages/kbn-apm-config-loader/src/utils/read_config.test.ts b/packages/kbn-apm-config-loader/src/utils/read_config.test.ts new file mode 100644 index 0000000000000..7320e5dcbd6ce --- /dev/null +++ b/packages/kbn-apm-config-loader/src/utils/read_config.test.ts @@ -0,0 +1,79 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { relative, resolve } from 'path'; +import { getConfigFromFiles } from './read_config'; + +const fixtureFile = (name: string) => resolve(__dirname, '..', '..', '__fixtures__', name); + +test('reads single yaml from file system and parses to json', () => { + const config = getConfigFromFiles([fixtureFile('config.yml')]); + + expect(config).toMatchSnapshot(); +}); + +test('returns a deep object', () => { + const config = getConfigFromFiles([fixtureFile('config_flat.yml')]); + + expect(config).toMatchSnapshot(); +}); + +test('reads and merges multiple yaml files from file system and parses to json', () => { + const config = getConfigFromFiles([fixtureFile('one.yml'), fixtureFile('two.yml')]); + + expect(config).toMatchSnapshot(); +}); + +test('should inject an environment variable value when setting a value with ${ENV_VAR}', () => { + process.env.KBN_ENV_VAR1 = 'val1'; + process.env.KBN_ENV_VAR2 = 'val2'; + + const config = getConfigFromFiles([fixtureFile('en_var_ref_config.yml')]); + + delete process.env.KBN_ENV_VAR1; + delete process.env.KBN_ENV_VAR2; + + expect(config).toMatchSnapshot(); +}); + +test('should throw an exception when referenced environment variable in a config value does not exist', () => { + expect(() => + getConfigFromFiles([fixtureFile('en_var_ref_config.yml')]) + ).toThrowErrorMatchingSnapshot(); +}); + +describe('different cwd()', () => { + const originalCwd = process.cwd(); + const tempCwd = resolve(__dirname); + + beforeAll(() => process.chdir(tempCwd)); + afterAll(() => process.chdir(originalCwd)); + + test('resolves relative files based on the cwd', () => { + const relativePath = relative(tempCwd, fixtureFile('one.yml')); + const config = getConfigFromFiles([relativePath]); + + expect(config).toMatchSnapshot(); + }); + + test('fails to load relative paths, not found because of the cwd', () => { + const relativePath = relative(resolve(__dirname, '..', '..'), fixtureFile('one.yml')); + expect(() => getConfigFromFiles([relativePath])).toThrowError(/ENOENT/); + }); +}); diff --git a/packages/kbn-apm-config-loader/src/utils/read_config.ts b/packages/kbn-apm-config-loader/src/utils/read_config.ts new file mode 100644 index 0000000000000..825bfd60181bf --- /dev/null +++ b/packages/kbn-apm-config-loader/src/utils/read_config.ts @@ -0,0 +1,64 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { readFileSync } from 'fs'; +import { safeLoad } from 'js-yaml'; + +import { set } from '@elastic/safer-lodash-set'; +import { isPlainObject } from 'lodash'; +import { ensureDeepObject } from './ensure_deep_object'; + +const readYaml = (path: string) => safeLoad(readFileSync(path, 'utf8')); + +function replaceEnvVarRefs(val: string) { + return val.replace(/\$\{(\w+)\}/g, (match, envVarName) => { + const envVarValue = process.env[envVarName]; + if (envVarValue !== undefined) { + return envVarValue; + } + + throw new Error(`Unknown environment variable referenced in config : ${envVarName}`); + }); +} + +function merge(target: Record, value: any, key?: string) { + if ((isPlainObject(value) || Array.isArray(value)) && Object.keys(value).length > 0) { + for (const [subKey, subVal] of Object.entries(value)) { + merge(target, subVal, key ? `${key}.${subKey}` : subKey); + } + } else if (key !== undefined) { + set(target, key, typeof value === 'string' ? replaceEnvVarRefs(value) : value); + } + + return target; +} + +/** @internal */ +export const getConfigFromFiles = (configFiles: readonly string[]): Record => { + let mergedYaml: Record = {}; + + for (const configFile of configFiles) { + const yaml = readYaml(configFile); + if (yaml !== null) { + mergedYaml = merge(mergedYaml, yaml); + } + } + + return ensureDeepObject(mergedYaml); +}; diff --git a/packages/kbn-apm-config-loader/tsconfig.json b/packages/kbn-apm-config-loader/tsconfig.json new file mode 100644 index 0000000000000..ba00ddfa6adb6 --- /dev/null +++ b/packages/kbn-apm-config-loader/tsconfig.json @@ -0,0 +1,12 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "declaration": true, + "outDir": "./target", + "stripInternal": false, + "declarationMap": true, + "types": ["jest", "node"] + }, + "include": ["./src/**/*.ts"], + "exclude": ["target"] +} diff --git a/packages/kbn-apm-config-loader/yarn.lock b/packages/kbn-apm-config-loader/yarn.lock new file mode 120000 index 0000000000000..3f82ebc9cdbae --- /dev/null +++ b/packages/kbn-apm-config-loader/yarn.lock @@ -0,0 +1 @@ +../../yarn.lock \ No newline at end of file diff --git a/packages/kbn-babel-preset/node_preset.js b/packages/kbn-babel-preset/node_preset.js index ee06e2588b022..86817ed253e7c 100644 --- a/packages/kbn-babel-preset/node_preset.js +++ b/packages/kbn-babel-preset/node_preset.js @@ -18,23 +18,6 @@ */ module.exports = (_, options = {}) => { - const overrides = []; - if (!process.env.ALLOW_PERFORMANCE_HOOKS_IN_TASK_MANAGER) { - overrides.push({ - test: [/x-pack[\/\\]legacy[\/\\]plugins[\/\\]task_manager/], - plugins: [ - [ - require.resolve('babel-plugin-filter-imports'), - { - imports: { - perf_hooks: ['performance'], - }, - }, - ], - ], - }); - } - return { presets: [ [ @@ -66,14 +49,5 @@ module.exports = (_, options = {}) => { ], require('./common_preset'), ], - plugins: [ - [ - require.resolve('babel-plugin-transform-define'), - { - 'global.__BUILT_WITH_BABEL__': 'true', - }, - ], - ], - overrides, }; }; diff --git a/packages/kbn-babel-preset/package.json b/packages/kbn-babel-preset/package.json index d73294b4cf873..79d2fd8687dae 100644 --- a/packages/kbn-babel-preset/package.json +++ b/packages/kbn-babel-preset/package.json @@ -1,7 +1,7 @@ { "name": "@kbn/babel-preset", - "private": true, "version": "1.0.0", + "private": true, "license": "Apache-2.0", "dependencies": { "@babel/plugin-proposal-class-properties": "^7.10.4", @@ -13,10 +13,8 @@ "@babel/preset-react": "^7.10.4", "@babel/preset-typescript": "^7.10.4", "babel-plugin-add-module-exports": "^1.0.2", - "babel-plugin-filter-imports": "^3.0.0", "babel-plugin-styled-components": "^1.10.7", - "babel-plugin-transform-define": "^1.3.1", - "babel-plugin-transform-imports": "^2.0.0", + "babel-plugin-transform-react-remove-prop-types": "^0.4.24", "react-is": "^16.8.0", "styled-components": "^5.1.0" } diff --git a/packages/kbn-babel-preset/webpack_preset.js b/packages/kbn-babel-preset/webpack_preset.js index 97462a579e3c4..503b99d3c3e8a 100644 --- a/packages/kbn-babel-preset/webpack_preset.js +++ b/packages/kbn-babel-preset/webpack_preset.js @@ -40,24 +40,18 @@ module.exports = () => { }, ], ], - // NOTE: we can enable this by default for everything as soon as we only have one instance - // of lodash across the entire project. For now we are just enabling it for siem - // as they are extensively using the lodash v4 - overrides: [ - { - test: [/x-pack[\/\\]legacy[\/\\]plugins[\/\\]siem[\/\\]public/], + env: { + production: { plugins: [ [ - require.resolve('babel-plugin-transform-imports'), + require.resolve('babel-plugin-transform-react-remove-prop-types'), { - 'lodash/?(((\\w*)?/?)*)': { - transform: 'lodash/${1}/${member}', - preventFullImport: false, - }, + mode: 'remove', + removeImport: true, }, ], ], }, - ], + }, }; }; diff --git a/packages/kbn-config/package.json b/packages/kbn-config/package.json index 2d9dbc3b7ab8f..6d2d56b929ead 100644 --- a/packages/kbn-config/package.json +++ b/packages/kbn-config/package.json @@ -16,7 +16,7 @@ "@kbn/logging": "1.0.0", "@kbn/std": "1.0.0", "@kbn/utility-types": "1.0.0", - "js-yaml": "3.13.1", + "js-yaml": "^3.14.0", "load-json-file": "^6.2.0", "lodash": "^4.17.20", "moment": "^2.24.0", @@ -25,6 +25,6 @@ }, "devDependencies": { "typescript": "4.0.2", - "tsd": "^0.7.4" + "tsd": "^0.13.1" } } diff --git a/packages/kbn-config/src/env.test.ts b/packages/kbn-config/src/env.test.ts index f3d51a021246e..1613a90951d40 100644 --- a/packages/kbn-config/src/env.test.ts +++ b/packages/kbn-config/src/env.test.ts @@ -198,6 +198,18 @@ test('pluginSearchPaths contains x-pack/examples plugins path if --run-examples expect(env.pluginSearchPaths).toContain('/some/home/dir/x-pack/examples'); }); +test('pluginSearchPaths does not contain x-pack/examples plugins path if --oss flag is true', () => { + const env = new Env( + '/some/home/dir', + packageInfos, + getEnvOptions({ + cliArgs: { runExamples: true, oss: true }, + }) + ); + + expect(env.pluginSearchPaths).not.toContain('/some/home/dir/x-pack/examples'); +}); + test('pluginSearchPaths does not contains examples plugins path if --run-examples flag is false', () => { const env = new Env( '/some/home/dir', diff --git a/packages/kbn-config/src/env.ts b/packages/kbn-config/src/env.ts index 250c7b72d47a9..e4585056696f9 100644 --- a/packages/kbn-config/src/env.ts +++ b/packages/kbn-config/src/env.ts @@ -123,8 +123,9 @@ export class Env { resolve(this.homeDir, 'src', 'plugins'), ...(options.cliArgs.oss ? [] : [resolve(this.homeDir, 'x-pack', 'plugins')]), resolve(this.homeDir, 'plugins'), - ...(options.cliArgs.runExamples - ? [resolve(this.homeDir, 'examples'), resolve(this.homeDir, 'x-pack', 'examples')] + ...(options.cliArgs.runExamples ? [resolve(this.homeDir, 'examples')] : []), + ...(options.cliArgs.runExamples && !options.cliArgs.oss + ? [resolve(this.homeDir, 'x-pack', 'examples')] : []), resolve(this.homeDir, '..', 'kibana-extra'), ]; diff --git a/packages/kbn-dev-utils/package.json b/packages/kbn-dev-utils/package.json index a3fe8178822aa..a51734168cf76 100644 --- a/packages/kbn-dev-utils/package.json +++ b/packages/kbn-dev-utils/package.json @@ -10,9 +10,9 @@ "kbn:watch": "yarn build --watch" }, "dependencies": { - "@babel/core": "^7.11.1", + "@babel/core": "^7.11.6", "@kbn/utils": "1.0.0", - "axios": "^0.19.0", + "axios": "^0.19.2", "chalk": "^4.1.0", "cheerio": "0.22.0", "dedent": "^0.7.0", diff --git a/packages/kbn-dev-utils/src/ci_stats_reporter/README.md b/packages/kbn-dev-utils/src/ci_stats_reporter/README.md index c7b98224c4e57..12fc33dfaffb0 100644 --- a/packages/kbn-dev-utils/src/ci_stats_reporter/README.md +++ b/packages/kbn-dev-utils/src/ci_stats_reporter/README.md @@ -8,10 +8,23 @@ This class integrates with the `ciStats.trackBuild {}` Jenkins Pipeline function To create an instance of the reporter, import the class and call `CiStatsReporter.fromEnv(log)` (passing it a tooling log). -#### `CiStatsReporter#metrics(metrics: Array<{ group: string, id: string, value: number }>)` +#### `CiStatsReporter#metrics(metrics: Metric[])` Use this method to record metrics in the Kibana CI Stats service. +```ts +interface Metric { + group: string, + id: string, + value: number, + // optional limit, values which exceed the limit will fail PRs + limit?: number + // optional path, relative to the root of the repo, where config values + // are defined. Will be linked to in PRs which have overages. + limitConfigPath?: string +} +``` + Example: ```ts diff --git a/packages/kbn-dev-utils/src/ci_stats_reporter/ci_stats_reporter.ts b/packages/kbn-dev-utils/src/ci_stats_reporter/ci_stats_reporter.ts index b0378ab6c5cd5..a2f3b63daec50 100644 --- a/packages/kbn-dev-utils/src/ci_stats_reporter/ci_stats_reporter.ts +++ b/packages/kbn-dev-utils/src/ci_stats_reporter/ci_stats_reporter.ts @@ -29,7 +29,13 @@ interface Config { buildId: string; } -export type CiStatsMetrics = Array<{ group: string; id: string; value: number }>; +export type CiStatsMetrics = Array<{ + group: string; + id: string; + value: number; + limit?: number; + limitConfigPath?: string; +}>; function parseConfig(log: ToolingLog) { const configJson = process.env.KIBANA_CI_STATS_CONFIG; diff --git a/packages/kbn-dev-utils/src/index.ts b/packages/kbn-dev-utils/src/index.ts index 8217999b01128..6a845825f0fd4 100644 --- a/packages/kbn-dev-utils/src/index.ts +++ b/packages/kbn-dev-utils/src/index.ts @@ -17,7 +17,7 @@ * under the License. */ -export { REPO_ROOT } from '@kbn/utils'; +export * from '@kbn/utils'; export { withProcRunner, ProcRunner } from './proc_runner'; export * from './tooling_log'; export * from './serializers'; diff --git a/packages/kbn-dev-utils/src/kbn_client/kbn_client.ts b/packages/kbn-dev-utils/src/kbn_client/kbn_client.ts index 861ea0988692c..7184727fc53de 100644 --- a/packages/kbn-dev-utils/src/kbn_client/kbn_client.ts +++ b/packages/kbn-dev-utils/src/kbn_client/kbn_client.ts @@ -54,8 +54,8 @@ export class KbnClient { /** * Make a direct request to the Kibana server */ - async request(options: ReqOptions) { - return await this.requester.request(options); + async request(options: ReqOptions) { + return await this.requester.request(options); } resolveUrl(relativeUrl: string) { diff --git a/packages/kbn-dev-utils/src/plugin_list/discover_plugins.ts b/packages/kbn-dev-utils/src/plugin_list/discover_plugins.ts index 5d92ddb600aa9..e8f6735205b19 100644 --- a/packages/kbn-dev-utils/src/plugin_list/discover_plugins.ts +++ b/packages/kbn-dev-utils/src/plugin_list/discover_plugins.ts @@ -29,7 +29,7 @@ import { extractAsciidocInfo } from './extract_asciidoc_info'; export interface Plugin { id: string; - relativeDir?: string; + relativeDir: string; relativeReadmePath?: string; readmeSnippet?: string; readmeAsciidocAnchor?: string; diff --git a/packages/kbn-dev-utils/src/plugin_list/generate_plugin_list.ts b/packages/kbn-dev-utils/src/plugin_list/generate_plugin_list.ts index e1a1323553113..680c220adb18c 100644 --- a/packages/kbn-dev-utils/src/plugin_list/generate_plugin_list.ts +++ b/packages/kbn-dev-utils/src/plugin_list/generate_plugin_list.ts @@ -24,9 +24,11 @@ import { REPO_ROOT } from '@kbn/utils'; import { Plugins } from './discover_plugins'; +const sortPlugins = (plugins: Plugins) => plugins.sort((a, b) => a.id.localeCompare(b.id)); + function* printPlugins(plugins: Plugins, includes: string[]) { - for (const plugin of plugins) { - const path = plugin.relativeReadmePath || plugin.relativeDir; + for (const plugin of sortPlugins(plugins)) { + const path = normalizePath(plugin.relativeReadmePath || plugin.relativeDir); yield ''; if (plugin.readmeAsciidocAnchor) { @@ -67,7 +69,7 @@ NOTE: [discrete] === src/plugins -[%header,cols=2*] +[%header,cols=2*] |=== |Name |Description @@ -79,7 +81,7 @@ ${Array.from(printPlugins(ossPlugins, includes)).join('\n')} [discrete] === x-pack/plugins -[%header,cols=2*] +[%header,cols=2*] |=== |Name |Description diff --git a/packages/kbn-es-archiver/package.json b/packages/kbn-es-archiver/package.json index 13b5662519b19..81c1747bb2727 100644 --- a/packages/kbn-es-archiver/package.json +++ b/packages/kbn-es-archiver/package.json @@ -4,8 +4,8 @@ "license": "Apache-2.0", "main": "target/index.js", "scripts": { - "kbn:bootstrap": "tsc", - "kbn:watch": "tsc --watch" + "kbn:bootstrap": "rm -rf target && tsc", + "kbn:watch": "rm -rf target && tsc --watch" }, "dependencies": { "@kbn/dev-utils": "1.0.0", diff --git a/packages/kbn-es-archiver/src/cli.ts b/packages/kbn-es-archiver/src/cli.ts index 41abe83c148cd..87df07fe865bd 100644 --- a/packages/kbn-es-archiver/src/cli.ts +++ b/packages/kbn-es-archiver/src/cli.ts @@ -144,7 +144,7 @@ export function runCli() { const query = flags.query; let parsedQuery; - if (typeof query === 'string') { + if (typeof query === 'string' && query.length > 0) { try { parsedQuery = JSON.parse(query); } catch (err) { diff --git a/packages/kbn-es/package.json b/packages/kbn-es/package.json index 52ef3fe05e751..c3733094350be 100644 --- a/packages/kbn-es/package.json +++ b/packages/kbn-es/package.json @@ -1,23 +1,32 @@ { "name": "@kbn/es", - "main": "./src/index.js", + "main": "./target/index.js", "version": "1.0.0", "license": "Apache-2.0", "private": true, + "scripts": { + "kbn:bootstrap": "node scripts/build", + "kbn:watch": "node scripts/build --watch" + }, "dependencies": { - "@elastic/elasticsearch": "7.9.0-rc.1", + "@elastic/elasticsearch": "7.9.1", "@kbn/dev-utils": "1.0.0", - "abort-controller": "^2.0.3", + "abort-controller": "^3.0.0", "chalk": "^4.1.0", "dedent": "^0.7.0", "del": "^5.1.0", "execa": "^4.0.2", - "getopts": "^2.2.4", + "getopts": "^2.2.5", "glob": "^7.1.2", "node-fetch": "^2.6.1", - "simple-git": "^1.91.0", + "simple-git": "1.116.0", "tar-fs": "^2.1.0", "tree-kill": "^1.2.2", "yauzl": "^2.10.0" + }, + "devDependencies": { + "@kbn/babel-preset": "1.0.0", + "@babel/cli": "^7.10.5", + "del": "^5.1.0" } } diff --git a/packages/kbn-es/scripts/build.js b/packages/kbn-es/scripts/build.js new file mode 100644 index 0000000000000..50aad665c920b --- /dev/null +++ b/packages/kbn-es/scripts/build.js @@ -0,0 +1,71 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +const { resolve } = require('path'); + +const del = require('del'); +const { run, withProcRunner } = require('@kbn/dev-utils'); + +const ROOT_DIR = resolve(__dirname, '..'); +const BUILD_DIR = resolve(ROOT_DIR, 'target'); + +run( + async ({ log, flags }) => { + await withProcRunner(log, async (proc) => { + log.info('Deleting old output'); + await del(BUILD_DIR); + + const cwd = ROOT_DIR; + + log.info(`Starting babel${flags.watch ? ' in watch mode' : ''}`); + await proc.run(`babel`, { + cmd: 'babel', + args: [ + 'src', + '--no-babelrc', + '--presets', + require.resolve('@kbn/babel-preset/node_preset'), + '--extensions', + '.ts,.js', + '--copy-files', + '--out-dir', + BUILD_DIR, + ...(flags.watch ? ['--watch'] : ['--quiet']), + ...(!flags['source-maps'] || !!process.env.CODE_COVERAGE + ? [] + : ['--source-maps', 'inline']), + ], + wait: true, + cwd, + }); + + log.success('Complete'); + }); + }, + { + description: 'Simple build tool for @kbn/es package', + flags: { + boolean: ['watch', 'source-maps'], + help: ` + --watch Run in watch mode + --source-maps Include sourcemaps + `, + }, + } +); diff --git a/packages/kbn-es/src/integration_tests/__fixtures__/es_bin.js b/packages/kbn-es/src/integration_tests/__fixtures__/es_bin.js index b860664443d1a..27e73e6c204e8 100644 --- a/packages/kbn-es/src/integration_tests/__fixtures__/es_bin.js +++ b/packages/kbn-es/src/integration_tests/__fixtures__/es_bin.js @@ -25,65 +25,67 @@ const { exitCode, start, ssl } = JSON.parse(process.argv[2]); const { createServer } = ssl ? require('https') : require('http'); const { ES_KEY_PATH, ES_CERT_PATH } = require('@kbn/dev-utils'); -process.exitCode = exitCode; +(function main() { + process.exitCode = exitCode; -if (!start) { - return; -} + if (!start) { + return; + } + + let serverUrl; + const server = createServer( + { + // Note: the integration uses the ES_P12_PATH, but that keystore contains + // the same key/cert as ES_KEY_PATH and ES_CERT_PATH + key: ssl ? fs.readFileSync(ES_KEY_PATH) : undefined, + cert: ssl ? fs.readFileSync(ES_CERT_PATH) : undefined, + }, + (req, res) => { + const url = new URL(req.url, serverUrl); + const send = (code, body) => { + res.writeHead(code, { 'content-type': 'application/json' }); + res.end(JSON.stringify(body)); + }; -let serverUrl; -const server = createServer( - { - // Note: the integration uses the ES_P12_PATH, but that keystore contains - // the same key/cert as ES_KEY_PATH and ES_CERT_PATH - key: ssl ? fs.readFileSync(ES_KEY_PATH) : undefined, - cert: ssl ? fs.readFileSync(ES_CERT_PATH) : undefined, - }, - (req, res) => { - const url = new URL(req.url, serverUrl); - const send = (code, body) => { - res.writeHead(code, { 'content-type': 'application/json' }); - res.end(JSON.stringify(body)); - }; + if (url.pathname === '/_xpack') { + return send(400, { + error: { + reason: 'foo bar', + }, + }); + } - if (url.pathname === '/_xpack') { - return send(400, { + return send(404, { error: { - reason: 'foo bar', + reason: 'not found', }, }); } + ); - return send(404, { - error: { - reason: 'not found', - }, - }); - } -); - -// setup server auto close after 1 second of silence -let serverCloseTimer; -const delayServerClose = () => { - clearTimeout(serverCloseTimer); - serverCloseTimer = setTimeout(() => server.close(), 1000); -}; -server.on('request', delayServerClose); -server.on('listening', delayServerClose); + // setup server auto close after 1 second of silence + let serverCloseTimer; + const delayServerClose = () => { + clearTimeout(serverCloseTimer); + serverCloseTimer = setTimeout(() => server.close(), 1000); + }; + server.on('request', delayServerClose); + server.on('listening', delayServerClose); -server.listen(0, '127.0.0.1', function () { - const { port, address: hostname } = server.address(); - serverUrl = new URL( - formatUrl({ - protocol: 'http:', - port, - hostname, - }) - ); + server.listen(0, '127.0.0.1', function () { + const { port, address: hostname } = server.address(); + serverUrl = new URL( + formatUrl({ + protocol: 'http:', + port, + hostname, + }) + ); - console.log( - `[o.e.h.AbstractHttpServerTransport] [computer] publish_address {127.0.0.1:${port}}, bound_addresses {[::1]:${port}}, {127.0.0.1:${port}}` - ); + console.log( + `[o.e.h.AbstractHttpServerTransport] [computer] publish_address {127.0.0.1:${port}}, bound_addresses {[::1]:${port}}, {127.0.0.1:${port}}` + ); - console.log('started'); -}); + console.log('started'); + }); +})(); diff --git a/packages/kbn-es/src/integration_tests/cluster.test.js b/packages/kbn-es/src/integration_tests/cluster.test.js index 0ae0ac0aac27a..6229a8add0d24 100644 --- a/packages/kbn-es/src/integration_tests/cluster.test.js +++ b/packages/kbn-es/src/integration_tests/cluster.test.js @@ -60,7 +60,7 @@ async function ensureResolve(promise) { function mockEsBin({ exitCode, start }) { execa.mockImplementationOnce((cmd, args, options) => - require.requireActual('execa')( + jest.requireActual('execa')( process.execPath, [ require.resolve('./__fixtures__/es_bin.js'), diff --git a/packages/kbn-eslint-import-resolver-kibana/package.json b/packages/kbn-eslint-import-resolver-kibana/package.json index 332f7e8a20cc2..223c73e97908e 100755 --- a/packages/kbn-eslint-import-resolver-kibana/package.json +++ b/packages/kbn-eslint-import-resolver-kibana/package.json @@ -13,7 +13,7 @@ "debug": "^2.6.9", "eslint-import-resolver-node": "0.3.2", "eslint-import-resolver-webpack": "0.11.1", - "glob-all": "^3.1.0", + "glob-all": "^3.2.1", "lru-cache": "^4.1.5", "resolve": "^1.7.1", "webpack": "^4.41.5" diff --git a/packages/kbn-i18n/package.json b/packages/kbn-i18n/package.json index eccdff9060cbe..f23faecbeaa67 100644 --- a/packages/kbn-i18n/package.json +++ b/packages/kbn-i18n/package.json @@ -13,13 +13,13 @@ }, "devDependencies": { "@babel/cli": "^7.10.5", - "@babel/core": "^7.11.1", + "@babel/core": "^7.11.6", "@kbn/babel-preset": "1.0.0", "@kbn/dev-utils": "1.0.0", "@types/intl-relativeformat": "^2.1.0", "@types/react-intl": "^2.3.15", "del": "^5.1.0", - "getopts": "^2.2.4", + "getopts": "^2.2.5", "supports-color": "^7.0.0", "typescript": "4.0.2" }, diff --git a/packages/kbn-i18n/src/core/i18n.test.ts b/packages/kbn-i18n/src/core/i18n.test.ts index ec08c82b502db..3364f20879c2a 100644 --- a/packages/kbn-i18n/src/core/i18n.test.ts +++ b/packages/kbn-i18n/src/core/i18n.test.ts @@ -25,7 +25,7 @@ describe('I18n engine', () => { let i18n: typeof i18nModule; beforeEach(() => { - i18n = require.requireActual('./i18n'); + i18n = jest.requireActual('./i18n'); }); afterEach(() => { diff --git a/packages/kbn-i18n/src/react/index.tsx b/packages/kbn-i18n/src/react/index.tsx index ff30934aad6d1..b438c44598b75 100644 --- a/packages/kbn-i18n/src/react/index.tsx +++ b/packages/kbn-i18n/src/react/index.tsx @@ -17,8 +17,10 @@ * under the License. */ -import { InjectedIntl as _InjectedIntl } from 'react-intl'; +import { InjectedIntl as _InjectedIntl, InjectedIntlProps as _InjectedIntlProps } from 'react-intl'; + export type InjectedIntl = _InjectedIntl; +export type InjectedIntlProps = _InjectedIntlProps; export { intlShape, @@ -29,6 +31,8 @@ export { FormattedPlural, FormattedMessage, FormattedHTMLMessage, + // Only used for testing. Use I18nProvider otherwise. + IntlProvider as __IntlProvider, } from 'react-intl'; export { I18nProvider } from './provider'; diff --git a/packages/kbn-interpreter/package.json b/packages/kbn-interpreter/package.json index aef63229ebe96..4d415e96389df 100644 --- a/packages/kbn-interpreter/package.json +++ b/packages/kbn-interpreter/package.json @@ -11,12 +11,12 @@ "dependencies": { "@babel/runtime": "^7.11.2", "@kbn/i18n": "1.0.0", - "lodash": "^4.17.15", + "lodash": "^4.17.20", "uuid": "3.3.2" }, "devDependencies": { "@babel/cli": "^7.10.5", - "@babel/core": "^7.11.1", + "@babel/core": "^7.11.6", "@babel/plugin-transform-modules-commonjs": "^7.10.4", "@babel/plugin-transform-runtime": "^7.11.0", "@kbn/babel-preset": "1.0.0", @@ -25,12 +25,12 @@ "copy-webpack-plugin": "^6.0.2", "css-loader": "^3.4.2", "del": "^5.1.0", - "getopts": "^2.2.4", + "getopts": "^2.2.5", "pegjs": "0.10.0", "sass-loader": "^8.0.2", "style-loader": "^1.1.3", "supports-color": "^7.0.0", - "url-loader": "2.2.0", + "url-loader": "^2.2.0", "webpack": "^4.41.5", "webpack-cli": "^3.3.10" } diff --git a/packages/kbn-monaco/package.json b/packages/kbn-monaco/package.json index ca133010fe230..fcea80c9b7110 100644 --- a/packages/kbn-monaco/package.json +++ b/packages/kbn-monaco/package.json @@ -18,7 +18,7 @@ "babel-loader": "^8.0.6", "css-loader": "^3.4.2", "del": "^5.1.0", - "raw-loader": "3.1.0", + "raw-loader": "^3.1.0", "supports-color": "^7.0.0", "typescript": "4.0.2", "webpack": "^4.41.5", diff --git a/packages/kbn-optimizer/README.md b/packages/kbn-optimizer/README.md index a666907f02678..3fdf915e84c21 100644 --- a/packages/kbn-optimizer/README.md +++ b/packages/kbn-optimizer/README.md @@ -84,9 +84,9 @@ const config = OptimizerConfig.create({ dist: true }); -await runOptimizer(config) - .pipe(logOptimizerState(log, config)) - .toPromise(); +await lastValueFrom( + runOptimizer(config).pipe(logOptimizerState(log, config)) +); ``` This is essentially what we're doing in [`script/build_kibana_platform_plugins`][Cli] and the new [build system task][BuildTask]. diff --git a/packages/kbn-optimizer/limits.yml b/packages/kbn-optimizer/limits.yml new file mode 100644 index 0000000000000..b075a678bff38 --- /dev/null +++ b/packages/kbn-optimizer/limits.yml @@ -0,0 +1,100 @@ +pageLoadAssetSize: + advancedSettings: 27596 + alerts: 106936 + apm: 64385 + apmOss: 18996 + beatsManagement: 188135 + bfetch: 41874 + canvas: 1066647 + charts: 159211 + cloud: 21076 + console: 46091 + core: 692106 + crossClusterReplication: 65408 + dashboard: 374194 + dashboardEnhanced: 65646 + dashboardMode: 22716 + data: 1170713 + dataEnhanced: 50420 + devTools: 38637 + discover: 105145 + discoverEnhanced: 42730 + embeddable: 312874 + embeddableEnhanced: 41145 + enterpriseSearch: 35741 + esUiShared: 326654 + expressions: 224136 + features: 31211 + fileUpload: 24717 + globalSearch: 43548 + globalSearchBar: 62888 + globalSearchProviders: 25554 + graph: 31504 + grokdebugger: 26779 + home: 41661 + indexLifecycleManagement: 107090 + indexManagement: 140608 + indexPatternManagement: 154222 + infra: 197873 + ingestManager: 415829 + ingestPipelines: 58003 + inputControlVis: 172675 + inspector: 148711 + kibanaLegacy: 107711 + kibanaOverview: 56279 + kibanaReact: 161921 + kibanaUtils: 198829 + lens: 96624 + licenseManagement: 41817 + licensing: 39008 + lists: 183665 + logstash: 53548 + management: 46112 + maps: 183610 + mapsLegacy: 116817 + mapsLegacyLicensing: 20214 + ml: 82187 + monitoring: 268612 + navigation: 37269 + newsfeed: 42228 + observability: 89709 + painlessLab: 179748 + regionMap: 66098 + remoteClusters: 51327 + reporting: 183418 + rollup: 97204 + savedObjects: 108518 + savedObjectsManagement: 100503 + searchprofiler: 67080 + security: 189428 + securityOss: 30806 + securitySolution: 622387 + share: 99061 + snapshotRestore: 79032 + spaces: 387915 + telemetry: 91832 + telemetryManagementSection: 52443 + tileMap: 65337 + timelion: 29920 + transform: 41007 + triggersActionsUi: 170001 + uiActions: 97717 + uiActionsEnhanced: 349511 + upgradeAssistant: 81241 + uptime: 40825 + urlDrilldown: 34174 + urlForwarding: 32579 + usageCollection: 39762 + visDefaultEditor: 50178 + visTypeMarkdown: 30896 + visTypeMetric: 42790 + visTypeTable: 94934 + visTypeTagcloud: 37575 + visTypeTimelion: 51933 + visTypeTimeseries: 155203 + visTypeVega: 153573 + visTypeVislib: 242838 + visTypeXy: 20255 + visualizations: 295025 + visualize: 57431 + watcher: 43598 diff --git a/packages/kbn-optimizer/package.json b/packages/kbn-optimizer/package.json index b80d1365659dd..c9e414dbc5177 100644 --- a/packages/kbn-optimizer/package.json +++ b/packages/kbn-optimizer/package.json @@ -11,29 +11,38 @@ }, "dependencies": { "@babel/cli": "^7.10.5", + "@babel/core": "^7.11.6", "@kbn/babel-preset": "1.0.0", "@kbn/dev-utils": "1.0.0", + "@kbn/std": "1.0.0", "@kbn/ui-shared-deps": "1.0.0", "autoprefixer": "^9.7.4", "babel-loader": "^8.0.6", "clean-webpack-plugin": "^3.0.0", "compression-webpack-plugin": "^4.0.0", "cpy": "^8.0.0", + "core-js": "^3.6.5", "css-loader": "^3.4.2", + "dedent": "^0.7.0", "del": "^5.1.0", "execa": "^4.0.2", "file-loader": "^4.2.0", "istanbul-instrumenter-loader": "^3.0.1", - "jest-diff": "^25.5.0", + "jest-diff": "^26.4.2", + "js-yaml": "^3.14.0", "json-stable-stringify": "^1.0.1", + "lmdb-store": "^0.6.10", "loader-utils": "^1.2.3", - "node-sass": "^4.13.0", + "node-sass": "^4.13.1", "normalize-path": "^3.0.0", + "pirates": "^4.0.1", "postcss": "^7.0.32", "postcss-loader": "^3.0.0", "raw-loader": "^3.1.0", "rxjs": "^6.5.5", + "js-yaml": "^3.14.0", "sass-loader": "^8.0.2", + "source-map-support": "^0.5.19", "style-loader": "^1.1.3", "terser-webpack-plugin": "^2.1.2", "tinymath": "1.2.1", @@ -44,8 +53,10 @@ "webpack-merge": "^4.2.2" }, "devDependencies": { + "@types/babel__core": "^7.1.10", "@types/compression-webpack-plugin": "^2.0.2", "@types/loader-utils": "^1.1.3", + "@types/source-map-support": "^0.5.3", "@types/watchpack": "^1.1.5", "@types/webpack": "^4.41.3" } diff --git a/packages/kbn-optimizer/src/cli.ts b/packages/kbn-optimizer/src/cli.ts index dcfb56be66efd..a822773052cae 100644 --- a/packages/kbn-optimizer/src/cli.ts +++ b/packages/kbn-optimizer/src/cli.ts @@ -22,12 +22,14 @@ import 'source-map-support/register'; import Path from 'path'; import { REPO_ROOT } from '@kbn/utils'; +import { lastValueFrom } from '@kbn/std'; import { run, createFlagError, CiStatsReporter } from '@kbn/dev-utils'; import { logOptimizerState } from './log_optimizer_state'; import { OptimizerConfig } from './optimizer'; import { reportOptimizerStats } from './report_optimizer_stats'; import { runOptimizer } from './run_optimizer'; +import { validateLimitsForAllBundles, updateBundleLimits } from './limits'; run( async ({ log, flags }) => { @@ -93,14 +95,24 @@ run( throw createFlagError('expected --filter to be one or more strings'); } + const validateLimits = flags['validate-limits'] ?? false; + if (typeof validateLimits !== 'boolean') { + throw createFlagError('expected --validate-limits to have no value'); + } + + const updateLimits = flags['update-limits'] ?? false; + if (typeof updateLimits !== 'boolean') { + throw createFlagError('expected --update-limits to have no value'); + } + const config = OptimizerConfig.create({ repoRoot: REPO_ROOT, watch, maxWorkerCount, - oss, - dist, + oss: oss && !(validateLimits || updateLimits), + dist: dist || updateLimits, cache, - examples, + examples: examples && !(validateLimits || updateLimits), profileWebpack, extraPluginScanDirs, inspectWorkers, @@ -108,6 +120,11 @@ run( filter, }); + if (validateLimits) { + validateLimitsForAllBundles(log, config); + return; + } + let update$ = runOptimizer(config); if (reportStats) { @@ -120,7 +137,11 @@ run( update$ = update$.pipe(reportOptimizerStats(reporter, config, log)); } - await update$.pipe(logOptimizerState(log, config)).toPromise(); + await lastValueFrom(update$.pipe(logOptimizerState(log, config))); + + if (updateLimits) { + updateBundleLimits(log, config); + } }, { flags: { @@ -134,6 +155,8 @@ run( 'profile', 'inspect-workers', 'report-stats', + 'validate-limits', + 'update-limits', ], string: ['workers', 'scan-dir', 'filter'], default: { @@ -152,10 +175,12 @@ run( --no-cache disable the cache --filter comma-separated list of bundle id filters, results from multiple flags are merged, * and ! are supported --no-examples don't build the example plugins - --dist create bundles that are suitable for inclusion in the Kibana distributable + --dist create bundles that are suitable for inclusion in the Kibana distributable, enabled when running with --update-limits --scan-dir add a directory to the list of directories scanned for plugins (specify as many times as necessary) --no-inspect-workers when inspecting the parent process, don't inspect the workers --report-stats attempt to report stats about this execution of the build to the kibana-ci-stats service using this name + --validate-limits validate the limits.yml config to ensure that there are limits defined for every bundle + --update-limits run a build and rewrite the limits file to include the current bundle sizes +5kb `, }, } diff --git a/packages/kbn-optimizer/src/common/event_stream_helpers.test.ts b/packages/kbn-optimizer/src/common/event_stream_helpers.test.ts index 7458fa13eccb3..8f5a01a4e4a5d 100644 --- a/packages/kbn-optimizer/src/common/event_stream_helpers.test.ts +++ b/packages/kbn-optimizer/src/common/event_stream_helpers.test.ts @@ -18,20 +18,21 @@ */ import * as Rx from 'rxjs'; -import { toArray, take } from 'rxjs/operators'; +import { take } from 'rxjs/operators'; +import { allValuesFrom } from './rxjs_helpers'; import { summarizeEventStream } from './event_stream_helpers'; it('emits each state with each event, ignoring events when summarizer returns undefined', async () => { const event$ = Rx.of(1, 2, 3, 4, 5); const initial = 0; - const values = await summarizeEventStream(event$, initial, (state, event) => { - if (event % 2) { - return state + event; - } - }) - .pipe(toArray()) - .toPromise(); + const values = await allValuesFrom( + summarizeEventStream(event$, initial, (state, event) => { + if (event % 2) { + return state + event; + } + }) + ); expect(values).toMatchInlineSnapshot(` Array [ @@ -57,15 +58,15 @@ it('emits each state with each event, ignoring events when summarizer returns un it('interleaves injected events when source is synchronous', async () => { const event$ = Rx.of(1, 7); const initial = 0; - const values = await summarizeEventStream(event$, initial, (state, event, injectEvent) => { - if (event < 5) { - injectEvent(event + 2); - } + const values = await allValuesFrom( + summarizeEventStream(event$, initial, (state, event, injectEvent) => { + if (event < 5) { + injectEvent(event + 2); + } - return state + event; - }) - .pipe(toArray()) - .toPromise(); + return state + event; + }) + ); expect(values).toMatchInlineSnapshot(` Array [ @@ -95,15 +96,15 @@ it('interleaves injected events when source is synchronous', async () => { it('interleaves injected events when source is asynchronous', async () => { const event$ = Rx.of(1, 7, Rx.asyncScheduler); const initial = 0; - const values = await summarizeEventStream(event$, initial, (state, event, injectEvent) => { - if (event < 5) { - injectEvent(event + 2); - } + const values = await allValuesFrom( + summarizeEventStream(event$, initial, (state, event, injectEvent) => { + if (event < 5) { + injectEvent(event + 2); + } - return state + event; - }) - .pipe(toArray()) - .toPromise(); + return state + event; + }) + ); expect(values).toMatchInlineSnapshot(` Array [ @@ -133,17 +134,17 @@ it('interleaves injected events when source is asynchronous', async () => { it('interleaves mulitple injected events in order', async () => { const event$ = Rx.of(1); const initial = 0; - const values = await summarizeEventStream(event$, initial, (state, event, injectEvent) => { - if (event < 10) { - injectEvent(10); - injectEvent(20); - injectEvent(30); - } - - return state + event; - }) - .pipe(toArray()) - .toPromise(); + const values = await allValuesFrom( + summarizeEventStream(event$, initial, (state, event, injectEvent) => { + if (event < 10) { + injectEvent(10); + injectEvent(20); + injectEvent(30); + } + + return state + event; + }) + ); expect(values).toMatchInlineSnapshot(` Array [ @@ -179,9 +180,9 @@ it('stops an infinite stream when unsubscribed', async () => { return prev + event; }); - const values = await summarizeEventStream(event$, initial, summarize) - .pipe(take(11), toArray()) - .toPromise(); + const values = await allValuesFrom( + summarizeEventStream(event$, initial, summarize).pipe(take(11)) + ); expect(values).toMatchInlineSnapshot(` Array [ diff --git a/packages/kbn-optimizer/src/common/rxjs_helpers.test.ts b/packages/kbn-optimizer/src/common/rxjs_helpers.test.ts index dda66c999b8f1..457da9290bbd0 100644 --- a/packages/kbn-optimizer/src/common/rxjs_helpers.test.ts +++ b/packages/kbn-optimizer/src/common/rxjs_helpers.test.ts @@ -19,6 +19,7 @@ import * as Rx from 'rxjs'; import { toArray, map } from 'rxjs/operators'; +import { lastValueFrom } from '@kbn/std'; import { pipeClosure, debounceTimeBuffer, maybeMap, maybe } from './rxjs_helpers'; @@ -36,21 +37,21 @@ describe('pipeClosure()', () => { toArray() ); - await expect(foo$.toPromise()).resolves.toMatchInlineSnapshot(` + await expect(lastValueFrom(foo$)).resolves.toMatchInlineSnapshot(` Array [ 1, 2, 3, ] `); - await expect(foo$.toPromise()).resolves.toMatchInlineSnapshot(` + await expect(lastValueFrom(foo$)).resolves.toMatchInlineSnapshot(` Array [ 2, 4, 6, ] `); - await expect(foo$.toPromise()).resolves.toMatchInlineSnapshot(` + await expect(lastValueFrom(foo$)).resolves.toMatchInlineSnapshot(` Array [ 3, 6, @@ -64,7 +65,7 @@ describe('maybe()', () => { it('filters out undefined values from the stream', async () => { const foo$ = Rx.of(1, undefined, 2, undefined, 3).pipe(maybe(), toArray()); - await expect(foo$.toPromise()).resolves.toEqual([1, 2, 3]); + await expect(lastValueFrom(foo$)).resolves.toEqual([1, 2, 3]); }); }); @@ -75,7 +76,7 @@ describe('maybeMap()', () => { toArray() ); - await expect(foo$.toPromise()).resolves.toEqual([1, 3, 5]); + await expect(lastValueFrom(foo$)).resolves.toEqual([1, 3, 5]); }); }); diff --git a/packages/kbn-optimizer/src/common/rxjs_helpers.ts b/packages/kbn-optimizer/src/common/rxjs_helpers.ts index c6385c22518aa..49bf2d8f145dd 100644 --- a/packages/kbn-optimizer/src/common/rxjs_helpers.ts +++ b/packages/kbn-optimizer/src/common/rxjs_helpers.ts @@ -18,7 +18,8 @@ */ import * as Rx from 'rxjs'; -import { mergeMap, tap, debounceTime, map } from 'rxjs/operators'; +import { mergeMap, tap, debounceTime, map, toArray } from 'rxjs/operators'; +import { firstValueFrom } from '@kbn/std'; type Operator = (source: Rx.Observable) => Rx.Observable; type MapFn = (item: T1, index: number) => T2; @@ -73,3 +74,6 @@ export const debounceTimeBuffer = (ms: number) => }) ); }); + +export const allValuesFrom = (observable: Rx.Observable) => + firstValueFrom(observable.pipe(toArray())); diff --git a/packages/kbn-optimizer/src/index.ts b/packages/kbn-optimizer/src/index.ts index 39cf2120baf0a..c522ff770d369 100644 --- a/packages/kbn-optimizer/src/index.ts +++ b/packages/kbn-optimizer/src/index.ts @@ -21,3 +21,5 @@ export { OptimizerConfig } from './optimizer'; export * from './run_optimizer'; export * from './log_optimizer_state'; export * from './report_optimizer_stats'; +export * from './node'; +export * from './limits'; diff --git a/packages/kbn-optimizer/src/integration_tests/__snapshots__/basic_optimization.test.ts.snap b/packages/kbn-optimizer/src/integration_tests/__snapshots__/basic_optimization.test.ts.snap index 79442c35df265..cb5bb1e8fc529 100644 --- a/packages/kbn-optimizer/src/integration_tests/__snapshots__/basic_optimization.test.ts.snap +++ b/packages/kbn-optimizer/src/integration_tests/__snapshots__/basic_optimization.test.ts.snap @@ -57,6 +57,7 @@ OptimizerConfig { "cache": true, "dist": false, "inspectWorkers": false, + "limits": "", "maxWorkerCount": 1, "plugins": Array [ Object { @@ -98,7 +99,7 @@ OptimizerConfig { } `; -exports[`prepares assets for distribution: bar bundle 1`] = `"(function(modules){var installedModules={};function __webpack_require__(moduleId){if(installedModules[moduleId]){return installedModules[moduleId].exports}var module=installedModules[moduleId]={i:moduleId,l:false,exports:{}};modules[moduleId].call(module.exports,module,module.exports,__webpack_require__);module.l=true;return module.exports}__webpack_require__.m=modules;__webpack_require__.c=installedModules;__webpack_require__.d=function(exports,name,getter){if(!__webpack_require__.o(exports,name)){Object.defineProperty(exports,name,{enumerable:true,get:getter})}};__webpack_require__.r=function(exports){if(typeof Symbol!==\\"undefined\\"&&Symbol.toStringTag){Object.defineProperty(exports,Symbol.toStringTag,{value:\\"Module\\"})}Object.defineProperty(exports,\\"__esModule\\",{value:true})};__webpack_require__.t=function(value,mode){if(mode&1)value=__webpack_require__(value);if(mode&8)return value;if(mode&4&&typeof value===\\"object\\"&&value&&value.__esModule)return value;var ns=Object.create(null);__webpack_require__.r(ns);Object.defineProperty(ns,\\"default\\",{enumerable:true,value:value});if(mode&2&&typeof value!=\\"string\\")for(var key in value)__webpack_require__.d(ns,key,function(key){return value[key]}.bind(null,key));return ns};__webpack_require__.n=function(module){var getter=module&&module.__esModule?function getDefault(){return module[\\"default\\"]}:function getModuleExports(){return module};__webpack_require__.d(getter,\\"a\\",getter);return getter};__webpack_require__.o=function(object,property){return Object.prototype.hasOwnProperty.call(object,property)};__webpack_require__.p=\\"\\";return __webpack_require__(__webpack_require__.s=3)})([function(module,exports,__webpack_require__){\\"use strict\\";var isOldIE=function isOldIE(){var memo;return function memorize(){if(typeof memo===\\"undefined\\"){memo=Boolean(window&&document&&document.all&&!window.atob)}return memo}}();var getTarget=function getTarget(){var memo={};return function memorize(target){if(typeof memo[target]===\\"undefined\\"){var styleTarget=document.querySelector(target);if(window.HTMLIFrameElement&&styleTarget instanceof window.HTMLIFrameElement){try{styleTarget=styleTarget.contentDocument.head}catch(e){styleTarget=null}}memo[target]=styleTarget}return memo[target]}}();var stylesInDom=[];function getIndexByIdentifier(identifier){var result=-1;for(var i=0;i { dist: false, }); + expect(config.limits).toEqual(readLimits()); + (config as any).limits = ''; + expect(config).toMatchSnapshot('OptimizerConfig'); - const msgs = await runOptimizer(config) - .pipe( + const msgs = await allValuesFrom( + runOptimizer(config).pipe( logOptimizerState(log, config), - filter((x) => x.event?.type !== 'worker stdio'), - toArray() + filter((x) => x.event?.type !== 'worker stdio') ) - .toPromise(); + ); const assert = (statement: string, truth: boolean, altStates?: OptimizerUpdate[]) => { if (!truth) { @@ -199,17 +209,16 @@ it('uses cache on second run and exist cleanly', async () => { dist: false, }); - const msgs = await runOptimizer(config) - .pipe( + const msgs = await allValuesFrom( + runOptimizer(config).pipe( tap((state) => { if (state.event?.type === 'worker stdio') { // eslint-disable-next-line no-console console.log('worker', state.event.stream, state.event.line); } - }), - toArray() + }) ) - .toPromise(); + ); expect(msgs.map((m) => m.state.phase)).toMatchInlineSnapshot(` Array [ @@ -231,7 +240,7 @@ it('prepares assets for distribution', async () => { dist: true, }); - await runOptimizer(config).pipe(logOptimizerState(log, config), toArray()).toPromise(); + await allValuesFrom(runOptimizer(config).pipe(logOptimizerState(log, config))); expectFileMatchesSnapshotWithCompression('plugins/foo/target/public/foo.plugin.js', 'foo bundle'); expectFileMatchesSnapshotWithCompression( diff --git a/packages/kbn-optimizer/src/integration_tests/bundle_cache.test.ts b/packages/kbn-optimizer/src/integration_tests/bundle_cache.test.ts index 48cab508954a0..00e6782128dd9 100644 --- a/packages/kbn-optimizer/src/integration_tests/bundle_cache.test.ts +++ b/packages/kbn-optimizer/src/integration_tests/bundle_cache.test.ts @@ -21,12 +21,11 @@ import Path from 'path'; import cpy from 'cpy'; import del from 'del'; -import { toArray } from 'rxjs/operators'; import { createAbsolutePathSerializer } from '@kbn/dev-utils'; import { getMtimes } from '../optimizer/get_mtimes'; import { OptimizerConfig } from '../optimizer/optimizer_config'; -import { Bundle } from '../common/bundle'; +import { allValuesFrom, Bundle } from '../common'; import { getBundleCacheEvent$ } from '../optimizer/bundle_cache'; const TMP_DIR = Path.resolve(__dirname, '../__fixtures__/__tmp__'); @@ -78,9 +77,7 @@ it('emits "bundle cached" event when everything is updated', async () => { bundleRefExportIds: [], }); - const cacheEvents = await getBundleCacheEvent$(config, optimizerCacheKey) - .pipe(toArray()) - .toPromise(); + const cacheEvents = await allValuesFrom(getBundleCacheEvent$(config, optimizerCacheKey)); expect(cacheEvents).toMatchInlineSnapshot(` Array [ @@ -119,9 +116,7 @@ it('emits "bundle not cached" event when cacheKey is up to date but caching is d bundleRefExportIds: [], }); - const cacheEvents = await getBundleCacheEvent$(config, optimizerCacheKey) - .pipe(toArray()) - .toPromise(); + const cacheEvents = await allValuesFrom(getBundleCacheEvent$(config, optimizerCacheKey)); expect(cacheEvents).toMatchInlineSnapshot(` Array [ @@ -160,9 +155,7 @@ it('emits "bundle not cached" event when optimizerCacheKey is missing', async () bundleRefExportIds: [], }); - const cacheEvents = await getBundleCacheEvent$(config, optimizerCacheKey) - .pipe(toArray()) - .toPromise(); + const cacheEvents = await allValuesFrom(getBundleCacheEvent$(config, optimizerCacheKey)); expect(cacheEvents).toMatchInlineSnapshot(` Array [ @@ -201,9 +194,7 @@ it('emits "bundle not cached" event when optimizerCacheKey is outdated, includes bundleRefExportIds: [], }); - const cacheEvents = await getBundleCacheEvent$(config, optimizerCacheKey) - .pipe(toArray()) - .toPromise(); + const cacheEvents = await allValuesFrom(getBundleCacheEvent$(config, optimizerCacheKey)); expect(cacheEvents).toMatchInlineSnapshot(` Array [ @@ -247,9 +238,7 @@ it('emits "bundle not cached" event when bundleRefExportIds is outdated, include bundleRefExportIds: ['plugin/bar/public'], }); - const cacheEvents = await getBundleCacheEvent$(config, optimizerCacheKey) - .pipe(toArray()) - .toPromise(); + const cacheEvents = await allValuesFrom(getBundleCacheEvent$(config, optimizerCacheKey)); expect(cacheEvents).toMatchInlineSnapshot(` Array [ @@ -292,9 +281,7 @@ it('emits "bundle not cached" event when cacheKey is missing', async () => { bundleRefExportIds: [], }); - const cacheEvents = await getBundleCacheEvent$(config, optimizerCacheKey) - .pipe(toArray()) - .toPromise(); + const cacheEvents = await allValuesFrom(getBundleCacheEvent$(config, optimizerCacheKey)); expect(cacheEvents).toMatchInlineSnapshot(` Array [ @@ -333,9 +320,7 @@ it('emits "bundle not cached" event when cacheKey is outdated', async () => { jest.spyOn(bundle, 'createCacheKey').mockImplementation(() => 'new'); - const cacheEvents = await getBundleCacheEvent$(config, optimizerCacheKey) - .pipe(toArray()) - .toPromise(); + const cacheEvents = await allValuesFrom(getBundleCacheEvent$(config, optimizerCacheKey)); expect(cacheEvents).toMatchInlineSnapshot(` Array [ diff --git a/packages/kbn-optimizer/src/integration_tests/watch_bundles_for_changes.test.ts b/packages/kbn-optimizer/src/integration_tests/watch_bundles_for_changes.test.ts index 176b17c979da9..00f3c780adc0a 100644 --- a/packages/kbn-optimizer/src/integration_tests/watch_bundles_for_changes.test.ts +++ b/packages/kbn-optimizer/src/integration_tests/watch_bundles_for_changes.test.ts @@ -20,6 +20,7 @@ import * as Rx from 'rxjs'; import { map } from 'rxjs/operators'; import ActualWatchpack from 'watchpack'; +import { lastValueFrom } from '@kbn/std'; import { Bundle, ascending } from '../common'; import { watchBundlesForChanges$ } from '../optimizer/watch_bundles_for_changes'; @@ -78,8 +79,8 @@ afterEach(async () => { it('notifies of changes and completes once all bundles have changed', async () => { expect.assertions(18); - const promise = watchBundlesForChanges$(bundleCacheEvent$, Date.now()) - .pipe( + const promise = lastValueFrom( + watchBundlesForChanges$(bundleCacheEvent$, Date.now()).pipe( map((event, i) => { // each time we trigger a change event we get a 'changed detected' event if (i === 0 || i === 2 || i === 4 || i === 6) { @@ -116,7 +117,7 @@ it('notifies of changes and completes once all bundles have changed', async () = } }) ) - .toPromise(); + ); expect(MockWatchPack.mock.instances).toHaveLength(1); const [watcher] = (MockWatchPack.mock.instances as any) as Array>; diff --git a/packages/kbn-optimizer/src/limits.ts b/packages/kbn-optimizer/src/limits.ts new file mode 100644 index 0000000000000..b0fae0901251d --- /dev/null +++ b/packages/kbn-optimizer/src/limits.ts @@ -0,0 +1,103 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import Fs from 'fs'; + +import dedent from 'dedent'; +import Yaml from 'js-yaml'; +import { createFailError, ToolingLog } from '@kbn/dev-utils'; + +import { OptimizerConfig, getMetrics, Limits } from './optimizer'; + +const LIMITS_PATH = require.resolve('../limits.yml'); +const DEFAULT_BUDGET = 15000; + +const diff = (a: T[], b: T[]): T[] => a.filter((item) => !b.includes(item)); + +export function readLimits(): Limits { + let yaml; + try { + yaml = Fs.readFileSync(LIMITS_PATH, 'utf8'); + } catch (error) { + if (error.code !== 'ENOENT') { + throw error; + } + } + + return yaml ? Yaml.safeLoad(yaml) : {}; +} + +export function validateLimitsForAllBundles(log: ToolingLog, config: OptimizerConfig) { + const limitBundleIds = Object.keys(config.limits.pageLoadAssetSize || {}); + const configBundleIds = config.bundles.map((b) => b.id); + + const missingBundleIds = diff(configBundleIds, limitBundleIds); + const extraBundleIds = diff(limitBundleIds, configBundleIds); + + const issues = []; + if (missingBundleIds.length) { + issues.push(`missing: ${missingBundleIds.join(', ')}`); + } + if (extraBundleIds.length) { + issues.push(`extra: ${extraBundleIds.join(', ')}`); + } + if (issues.length) { + throw createFailError( + dedent` + The limits defined in packages/kbn-optimizer/limits.yml are outdated. Please update + this file with a limit (in bytes) for every production bundle. + + ${issues.join('\n ')} + + To automatically update the limits file locally run: + + node scripts/build_kibana_platform_plugins.js --update-limits + + To validate your changes locally run: + + node scripts/build_kibana_platform_plugins.js --validate-limits + ` + '\n' + ); + } + + log.success('limits.yml file valid'); +} + +export function updateBundleLimits(log: ToolingLog, config: OptimizerConfig) { + const metrics = getMetrics(log, config); + + const pageLoadAssetSize: NonNullable = {}; + + for (const metric of metrics.sort((a, b) => a.id.localeCompare(b.id))) { + if (metric.group === 'page load bundle size') { + const existingLimit = config.limits.pageLoadAssetSize?.[metric.id]; + pageLoadAssetSize[metric.id] = + existingLimit != null && existingLimit >= metric.value + ? existingLimit + : metric.value + DEFAULT_BUDGET; + } + } + + const newLimits: Limits = { + pageLoadAssetSize, + }; + + Fs.writeFileSync(LIMITS_PATH, Yaml.safeDump(newLimits)); + log.success(`wrote updated limits to ${LIMITS_PATH}`); +} diff --git a/packages/kbn-optimizer/src/node/cache.ts b/packages/kbn-optimizer/src/node/cache.ts new file mode 100644 index 0000000000000..7fbf009e38a7d --- /dev/null +++ b/packages/kbn-optimizer/src/node/cache.ts @@ -0,0 +1,171 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import Path from 'path'; + +// @ts-expect-error no types available +import * as LmdbStore from 'lmdb-store'; +import { REPO_ROOT, UPSTREAM_BRANCH } from '@kbn/dev-utils'; + +const CACHE_DIR = Path.resolve(REPO_ROOT, 'data/node_auto_transpilation_cache', UPSTREAM_BRANCH); +const reportError = () => { + // right now I'm not sure we need to worry about errors, the cache isn't actually + // necessary, and if the cache is broken it should just rebuild on the next restart + // of the process. We don't know how often errors occur though and what types of + // things might fail on different machines so we probably want some way to signal + // to users that something is wrong +}; + +const GLOBAL_ATIME = `${Date.now()}`; +const MINUTE = 1000 * 60; +const HOUR = MINUTE * 60; +const DAY = HOUR * 24; + +interface Lmdb { + get(key: string): T | undefined; + put(key: string, value: T, version?: number, ifVersion?: number): Promise; + remove(key: string, ifVersion?: number): Promise; + openDB(options: { name: string; encoding: 'msgpack' | 'string' | 'json' | 'binary' }): Lmdb; + getRange(options?: { + start?: T; + end?: T; + reverse?: boolean; + limit?: number; + versions?: boolean; + }): Iterable<{ key: string; value: T }>; +} + +export class Cache { + private readonly codes: Lmdb; + private readonly atimes: Lmdb; + private readonly mtimes: Lmdb; + private readonly sourceMaps: Lmdb; + private readonly prefix: string; + + constructor(config: { prefix: string }) { + this.prefix = config.prefix; + + this.codes = LmdbStore.open({ + name: 'codes', + path: CACHE_DIR, + }); + + this.atimes = this.codes.openDB({ + name: 'atimes', + encoding: 'string', + }); + + this.mtimes = this.codes.openDB({ + name: 'mtimes', + encoding: 'string', + }); + + this.sourceMaps = this.codes.openDB({ + name: 'sourceMaps', + encoding: 'msgpack', + }); + + // after the process has been running for 30 minutes prune the + // keys which haven't been used in 30 days. We use `unref()` to + // make sure this timer doesn't hold other processes open + // unexpectedly + setTimeout(() => { + this.pruneOldKeys(); + }, 30 * MINUTE).unref(); + } + + getMtime(path: string) { + return this.mtimes.get(this.getKey(path)); + } + + getCode(path: string) { + const key = this.getKey(path); + + // when we use a file from the cache set the "atime" of that cache entry + // so that we know which cache items we use and which haven't been + // touched in a long time (currently 30 days) + this.atimes.put(key, GLOBAL_ATIME).catch(reportError); + + return this.codes.get(key); + } + + getSourceMap(path: string) { + return this.sourceMaps.get(this.getKey(path)); + } + + update(path: string, file: { mtime: string; code: string; map: any }) { + const key = this.getKey(path); + + Promise.all([ + this.atimes.put(key, GLOBAL_ATIME), + this.mtimes.put(key, file.mtime), + this.codes.put(key, file.code), + this.sourceMaps.put(key, file.map), + ]).catch(reportError); + } + + private getKey(path: string) { + return `${this.prefix}${path}`; + } + + private async pruneOldKeys() { + try { + const ATIME_LIMIT = Date.now() - 30 * DAY; + const BATCH_SIZE = 1000; + + const validKeys: string[] = []; + const invalidKeys: string[] = []; + + for (const { key, value } of this.atimes.getRange()) { + const atime = parseInt(value, 10); + if (atime < ATIME_LIMIT) { + invalidKeys.push(key); + } else { + validKeys.push(key); + } + + if (validKeys.length + invalidKeys.length >= BATCH_SIZE) { + const promises = new Set(); + + if (invalidKeys.length) { + for (const k of invalidKeys) { + // all these promises are the same currently, so Set() will + // optimise this to a single promise, but I wouldn't be shocked + // if a future version starts returning independent promises so + // this is just for some future-proofing + promises.add(this.atimes.remove(k)); + promises.add(this.mtimes.remove(k)); + promises.add(this.codes.remove(k)); + promises.add(this.sourceMaps.remove(k)); + } + } else { + // delay a smidge to allow other things to happen before the next batch of checks + promises.add(new Promise((resolve) => setTimeout(resolve, 1))); + } + + invalidKeys.length = 0; + validKeys.length = 0; + await Promise.all(Array.from(promises)); + } + } + } catch { + // ignore errors, the cache is totally disposable and will rebuild if there is some sort of corruption + } + } +} diff --git a/packages/kbn-optimizer/src/node/index.ts b/packages/kbn-optimizer/src/node/index.ts new file mode 100644 index 0000000000000..64dd75ce573e6 --- /dev/null +++ b/packages/kbn-optimizer/src/node/index.ts @@ -0,0 +1,20 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export * from './node_auto_tranpilation'; diff --git a/packages/kbn-optimizer/src/node/node_auto_tranpilation.ts b/packages/kbn-optimizer/src/node/node_auto_tranpilation.ts new file mode 100644 index 0000000000000..ff6ab1c68da53 --- /dev/null +++ b/packages/kbn-optimizer/src/node/node_auto_tranpilation.ts @@ -0,0 +1,187 @@ +/* eslint-disable @kbn/eslint/require-license-header */ + +/** + * This module is based on @babel/register @ 9808d25, modified to use + * a more efficient caching implementation which writes to disk as + * the cache is built rather than keeping the whole cache in memory + * and then dumping it to disk when the process exits. + */ + +/** + * @notice + * MIT License + * + * Copyright (c) 2014-present Sebastian McKenzie and other contributors + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +import Fs from 'fs'; +import Path from 'path'; +import Crypto from 'crypto'; + +import * as babel from '@babel/core'; +import { addHook } from 'pirates'; +import { REPO_ROOT } from '@kbn/dev-utils'; +import sourceMapSupport from 'source-map-support'; + +import { Cache } from './cache'; + +const cwd = process.cwd(); + +const IGNORE_PATTERNS = [ + /[\/\\]kbn-pm[\/\\]dist[\/\\]/, + + // ignore paths matching `/node_modules/{a}/{b}`, unless `a` + // is `x-pack` and `b` is not `node_modules` + /[\/\\]node_modules[\/\\](?!x-pack[\/\\](?!node_modules)([^\/\\]+))([^\/\\]+[\/\\][^\/\\]+)/, + + // ignore paths matching `/canvas/canvas_plugin/` + /[\/\\]canvas[\/\\]canvas_plugin[\/\\]/, + + // ignore any path in the packages, unless it is in the package's + // root `src` directory, in any test or __tests__ directory, or it + // ends with .test.js, .test.ts, or .test.tsx + /[\/\\]packages[\/\\](eslint-|kbn-)[^\/\\]+[\/\\](?!src[\/\\].*|(.+[\/\\])?(test|__tests__)[\/\\].+|.+\.test\.(js|ts|tsx)$)(.+$)/, +]; + +function getBabelOptions(path: string) { + return babel.loadOptions({ + cwd, + sourceRoot: Path.dirname(path) + Path.sep, + filename: path, + babelrc: false, + presets: [require.resolve('@kbn/babel-preset/node_preset')], + sourceMaps: 'both', + ast: false, + })!; +} + +/** + * @babel/register uses a JSON encoded copy of the config + babel.version + * as the cache key for files, so we do something similar but we don't need + * a unique cache key for every file as our config isn't different for + * different files (by design). Instead we determine a unique prefix and + * automatically prepend all paths with the prefix to create cache keys + */ +function determineCachePrefix() { + const json = JSON.stringify({ + babelVersion: babel.version, + // get a config for a fake js, ts, and tsx file to make sure we + // capture conditional config portions based on the file extension + js: getBabelOptions(Path.resolve(REPO_ROOT, 'foo.js')), + ts: getBabelOptions(Path.resolve(REPO_ROOT, 'foo.ts')), + tsx: getBabelOptions(Path.resolve(REPO_ROOT, 'foo.tsx')), + }); + + const checksum = Crypto.createHash('sha256').update(json).digest('hex'); + return `${checksum}:`; +} + +function compile(cache: Cache, source: string, path: string) { + try { + const mtime = `${Fs.statSync(path).mtimeMs}`; + if (cache.getMtime(path) === mtime) { + const code = cache.getCode(path); + if (code) { + // code *should* always be defined, but if it isn't for some reason rebuild it + return code; + } + } + + const options = getBabelOptions(path); + const result = babel.transform(source, options); + + if (!result || !result.code || !result.map) { + throw new Error(`babel failed to transpile [${path}]`); + } + + cache.update(path, { + mtime, + map: result.map, + code: result.code, + }); + + return result.code; + } catch (error) { + throw error; + } +} + +let installed = false; + +export function registerNodeAutoTranspilation() { + if (installed) { + return; + } + installed = true; + + const cache = new Cache({ + prefix: determineCachePrefix(), + }); + + sourceMapSupport.install({ + handleUncaughtExceptions: false, + environment: 'node', + // @ts-expect-error bad source-map-support types + retrieveSourceMap(path: string) { + const map = cache.getSourceMap(path); + + if (map) { + return { + url: null, + map, + }; + } else { + return null; + } + }, + }); + + let compiling = false; + + addHook( + (code, path) => { + if (compiling) { + return code; + } + + if (IGNORE_PATTERNS.some((re) => re.test(path))) { + return code; + } + + try { + compiling = true; + return compile(cache, code, path); + } finally { + compiling = false; + } + }, + { + exts: ['.js', '.ts', '.tsx'], + ignoreNodeModules: false, + } + ); + + // require the polyfills after setting up the require hook so that @babel/preset-env + // will spot the import in the polyfill file and replace it with the necessary polyfills + // for the current node.js version + require('./polyfill'); +} diff --git a/packages/kbn-optimizer/src/node/polyfill.ts b/packages/kbn-optimizer/src/node/polyfill.ts new file mode 100644 index 0000000000000..5d445ef89f71e --- /dev/null +++ b/packages/kbn-optimizer/src/node/polyfill.ts @@ -0,0 +1,20 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import 'core-js/stable'; diff --git a/packages/kbn-optimizer/src/optimizer/get_mtimes.ts b/packages/kbn-optimizer/src/optimizer/get_mtimes.ts index 07777c323637a..b6c3678709880 100644 --- a/packages/kbn-optimizer/src/optimizer/get_mtimes.ts +++ b/packages/kbn-optimizer/src/optimizer/get_mtimes.ts @@ -20,7 +20,8 @@ import Fs from 'fs'; import * as Rx from 'rxjs'; -import { mergeMap, toArray, map, catchError } from 'rxjs/operators'; +import { mergeMap, map, catchError } from 'rxjs/operators'; +import { allValuesFrom } from '../common'; const stat$ = Rx.bindNodeCallback(Fs.stat); @@ -28,20 +29,22 @@ const stat$ = Rx.bindNodeCallback(Fs.stat); * get mtimes of referenced paths concurrently, limit concurrency to 100 */ export async function getMtimes(paths: Iterable) { - return await Rx.from(paths) - .pipe( - // map paths to [path, mtimeMs] entries with concurrency of - // 100 at a time, ignoring missing paths - mergeMap( - (path) => - stat$(path).pipe( - map((stat) => [path, stat.mtimeMs] as const), - catchError((error: any) => (error?.code === 'ENOENT' ? Rx.EMPTY : Rx.throwError(error))) - ), - 100 - ), - toArray(), - map((entries) => new Map(entries)) + return new Map( + await allValuesFrom( + Rx.from(paths).pipe( + // map paths to [path, mtimeMs] entries with concurrency of + // 100 at a time, ignoring missing paths + mergeMap( + (path) => + stat$(path).pipe( + map((stat) => [path, stat.mtimeMs] as const), + catchError((error: any) => + error?.code === 'ENOENT' ? Rx.EMPTY : Rx.throwError(error) + ) + ), + 100 + ) + ) ) - .toPromise(); + ); } diff --git a/packages/kbn-optimizer/src/optimizer/get_output_stats.ts b/packages/kbn-optimizer/src/optimizer/get_output_stats.ts new file mode 100644 index 0000000000000..cc4cd05f42c3f --- /dev/null +++ b/packages/kbn-optimizer/src/optimizer/get_output_stats.ts @@ -0,0 +1,124 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import Fs from 'fs'; +import Path from 'path'; + +import { ToolingLog, CiStatsMetrics } from '@kbn/dev-utils'; +import { OptimizerConfig } from './optimizer_config'; + +const flatten = (arr: Array): T[] => + arr.reduce((acc: T[], item) => acc.concat(item), []); + +interface Entry { + relPath: string; + stats: Fs.Stats; +} + +const IGNORED_EXTNAME = ['.map', '.br', '.gz']; + +const getFiles = (dir: string, parent?: string) => + flatten( + Fs.readdirSync(dir).map((name): Entry | Entry[] => { + const absPath = Path.join(dir, name); + const relPath = parent ? Path.join(parent, name) : name; + const stats = Fs.statSync(absPath); + + if (stats.isDirectory()) { + return getFiles(absPath, relPath); + } + + return { + relPath, + stats, + }; + }) + ).filter((file) => { + const filename = Path.basename(file.relPath); + if (filename.startsWith('.')) { + return false; + } + + const ext = Path.extname(filename); + if (IGNORED_EXTNAME.includes(ext)) { + return false; + } + + return true; + }); + +export function getMetrics(log: ToolingLog, config: OptimizerConfig) { + return flatten( + config.bundles.map((bundle) => { + // make the cache read from the cache file since it was likely updated by the worker + bundle.cache.refresh(); + + const outputFiles = getFiles(bundle.outputDir); + const entryName = `${bundle.id}.${bundle.type}.js`; + const entry = outputFiles.find((f) => f.relPath === entryName); + if (!entry) { + throw new Error( + `Unable to find bundle entry named [${entryName}] in [${bundle.outputDir}]` + ); + } + + const chunkPrefix = `${bundle.id}.chunk.`; + const asyncChunks = outputFiles.filter((f) => f.relPath.startsWith(chunkPrefix)); + const miscFiles = outputFiles.filter((f) => f !== entry && !asyncChunks.includes(f)); + + if (asyncChunks.length) { + log.verbose(bundle.id, 'async chunks', asyncChunks); + } + if (miscFiles.length) { + log.verbose(bundle.id, 'misc files', asyncChunks); + } + + const sumSize = (files: Entry[]) => files.reduce((acc: number, f) => acc + f.stats!.size, 0); + + const bundleMetrics: CiStatsMetrics = [ + { + group: `@kbn/optimizer bundle module count`, + id: bundle.id, + value: bundle.cache.getModuleCount() || 0, + }, + { + group: `page load bundle size`, + id: bundle.id, + value: entry.stats!.size, + limit: config.limits.pageLoadAssetSize?.[bundle.id], + limitConfigPath: `packages/kbn-optimizer/limits.yml`, + }, + { + group: `async chunks size`, + id: bundle.id, + value: sumSize(asyncChunks), + }, + { + group: `miscellaneous assets size`, + id: bundle.id, + value: sumSize(miscFiles), + }, + ]; + + log.debug(bundle.id, 'metrics', bundleMetrics); + + return bundleMetrics; + }) + ); +} diff --git a/packages/kbn-optimizer/src/optimizer/handle_optimizer_completion.test.ts b/packages/kbn-optimizer/src/optimizer/handle_optimizer_completion.test.ts index 6edcde56e26de..b92eee0a51fd5 100644 --- a/packages/kbn-optimizer/src/optimizer/handle_optimizer_completion.test.ts +++ b/packages/kbn-optimizer/src/optimizer/handle_optimizer_completion.test.ts @@ -20,12 +20,11 @@ import * as Rx from 'rxjs'; import { REPO_ROOT } from '@kbn/utils'; -import { Update } from '../common'; +import { Update, allValuesFrom } from '../common'; import { OptimizerState } from './optimizer_state'; import { OptimizerConfig } from './optimizer_config'; import { handleOptimizerCompletion } from './handle_optimizer_completion'; -import { toArray } from 'rxjs/operators'; const createUpdate$ = (phase: OptimizerState['phase']) => Rx.of>({ @@ -44,13 +43,12 @@ const config = (watch?: boolean) => repoRoot: REPO_ROOT, watch, }); -const collect = (stream: Rx.Observable): Promise => stream.pipe(toArray()).toPromise(); it('errors if the optimizer completes when in watch mode', async () => { const update$ = createUpdate$('success'); await expect( - collect(update$.pipe(handleOptimizerCompletion(config(true)))) + allValuesFrom(update$.pipe(handleOptimizerCompletion(config(true)))) ).rejects.toThrowErrorMatchingInlineSnapshot( `"optimizer unexpectedly completed when in watch mode"` ); @@ -60,7 +58,7 @@ it('errors if the optimizer completes in phase "issue"', async () => { const update$ = createUpdate$('issue'); await expect( - collect(update$.pipe(handleOptimizerCompletion(config()))) + allValuesFrom(update$.pipe(handleOptimizerCompletion(config()))) ).rejects.toThrowErrorMatchingInlineSnapshot(`"webpack issue"`); }); @@ -68,7 +66,7 @@ it('errors if the optimizer completes in phase "initializing"', async () => { const update$ = createUpdate$('initializing'); await expect( - collect(update$.pipe(handleOptimizerCompletion(config()))) + allValuesFrom(update$.pipe(handleOptimizerCompletion(config()))) ).rejects.toThrowErrorMatchingInlineSnapshot( `"optimizer unexpectedly exit in phase \\"initializing\\""` ); @@ -78,7 +76,7 @@ it('errors if the optimizer completes in phase "reallocating"', async () => { const update$ = createUpdate$('reallocating'); await expect( - collect(update$.pipe(handleOptimizerCompletion(config()))) + allValuesFrom(update$.pipe(handleOptimizerCompletion(config()))) ).rejects.toThrowErrorMatchingInlineSnapshot( `"optimizer unexpectedly exit in phase \\"reallocating\\""` ); @@ -88,7 +86,7 @@ it('errors if the optimizer completes in phase "running"', async () => { const update$ = createUpdate$('running'); await expect( - collect(update$.pipe(handleOptimizerCompletion(config()))) + allValuesFrom(update$.pipe(handleOptimizerCompletion(config()))) ).rejects.toThrowErrorMatchingInlineSnapshot( `"optimizer unexpectedly exit in phase \\"running\\""` ); @@ -98,7 +96,7 @@ it('passes through errors on the source stream', async () => { const error = new Error('foo'); const update$ = Rx.throwError(error); - await expect(collect(update$.pipe(handleOptimizerCompletion(config())))).rejects.toThrowError( - error - ); + await expect( + allValuesFrom(update$.pipe(handleOptimizerCompletion(config()))) + ).rejects.toThrowError(error); }); diff --git a/packages/kbn-optimizer/src/optimizer/index.ts b/packages/kbn-optimizer/src/optimizer/index.ts index 84fd395e98976..77df112b44351 100644 --- a/packages/kbn-optimizer/src/optimizer/index.ts +++ b/packages/kbn-optimizer/src/optimizer/index.ts @@ -25,3 +25,4 @@ export * from './watch_bundles_for_changes'; export * from './run_workers'; export * from './bundle_cache'; export * from './handle_optimizer_completion'; +export * from './get_output_stats'; diff --git a/packages/kbn-optimizer/src/optimizer/observe_stdio.test.ts b/packages/kbn-optimizer/src/optimizer/observe_stdio.test.ts index 9bf8f9db1fe45..a7c07358fa6d6 100644 --- a/packages/kbn-optimizer/src/optimizer/observe_stdio.test.ts +++ b/packages/kbn-optimizer/src/optimizer/observe_stdio.test.ts @@ -19,7 +19,7 @@ import { Readable } from 'stream'; -import { toArray } from 'rxjs/operators'; +import { allValuesFrom } from '../common'; import { observeStdio$ } from './observe_stdio'; @@ -27,18 +27,18 @@ it('notifies on every line, uncluding partial content at the end without a newli const chunks = [`foo\nba`, `r\nb`, `az`]; await expect( - observeStdio$( - new Readable({ - read() { - this.push(chunks.shift()!); - if (!chunks.length) { - this.push(null); - } - }, - }) + allValuesFrom( + observeStdio$( + new Readable({ + read() { + this.push(chunks.shift()!); + if (!chunks.length) { + this.push(null); + } + }, + }) + ) ) - .pipe(toArray()) - .toPromise() ).resolves.toMatchInlineSnapshot(` Array [ "foo", diff --git a/packages/kbn-optimizer/src/optimizer/optimizer_config.test.ts b/packages/kbn-optimizer/src/optimizer/optimizer_config.test.ts index fd887e8c2c012..948ba520931e5 100644 --- a/packages/kbn-optimizer/src/optimizer/optimizer_config.test.ts +++ b/packages/kbn-optimizer/src/optimizer/optimizer_config.test.ts @@ -22,6 +22,7 @@ jest.mock('./kibana_platform_plugins.ts'); jest.mock('./get_plugin_bundles.ts'); jest.mock('../common/theme_tags.ts'); jest.mock('./filter_by_id.ts'); +jest.mock('../limits.ts'); jest.mock('os', () => { const realOs = jest.requireActual('os'); @@ -385,6 +386,7 @@ describe('OptimizerConfig::create()', () => { .findKibanaPlatformPlugins; const getPluginBundles: jest.Mock = jest.requireMock('./get_plugin_bundles.ts').getPluginBundles; const filterById: jest.Mock = jest.requireMock('./filter_by_id.ts').filterById; + const readLimits: jest.Mock = jest.requireMock('../limits.ts').readLimits; beforeEach(() => { if ('mock' in OptimizerConfig.parseOptions) { @@ -398,6 +400,7 @@ describe('OptimizerConfig::create()', () => { findKibanaPlatformPlugins.mockReturnValue(Symbol('new platform plugins')); getPluginBundles.mockReturnValue([Symbol('bundle1'), Symbol('bundle2')]); filterById.mockReturnValue(Symbol('filtered bundles')); + readLimits.mockReturnValue(Symbol('limits')); jest.spyOn(OptimizerConfig, 'parseOptions').mockImplementation((): { [key in keyof ParsedOptions]: any; @@ -429,6 +432,7 @@ describe('OptimizerConfig::create()', () => { "cache": Symbol(parsed cache), "dist": Symbol(parsed dist), "inspectWorkers": Symbol(parsed inspect workers), + "limits": Symbol(limits), "maxWorkerCount": Symbol(parsed max worker count), "plugins": Symbol(new platform plugins), "profileWebpack": Symbol(parsed profile webpack), diff --git a/packages/kbn-optimizer/src/optimizer/optimizer_config.ts b/packages/kbn-optimizer/src/optimizer/optimizer_config.ts index 45598ff8831b0..b685d6ea01591 100644 --- a/packages/kbn-optimizer/src/optimizer/optimizer_config.ts +++ b/packages/kbn-optimizer/src/optimizer/optimizer_config.ts @@ -32,6 +32,13 @@ import { import { findKibanaPlatformPlugins, KibanaPlatformPlugin } from './kibana_platform_plugins'; import { getPluginBundles } from './get_plugin_bundles'; import { filterById } from './filter_by_id'; +import { readLimits } from '../limits'; + +export interface Limits { + pageLoadAssetSize?: { + [id: string]: number | undefined; + }; +} function pickMaxWorkerCount(dist: boolean) { // don't break if cpus() returns nothing, or an empty array @@ -161,7 +168,8 @@ export class OptimizerConfig { Path.resolve(repoRoot, 'src/plugins'), ...(oss ? [] : [Path.resolve(repoRoot, 'x-pack/plugins')]), Path.resolve(repoRoot, 'plugins'), - ...(examples ? [Path.resolve('examples'), Path.resolve('x-pack/examples')] : []), + ...(examples ? [Path.resolve('examples')] : []), + ...(examples && !oss ? [Path.resolve('x-pack/examples')] : []), Path.resolve(repoRoot, '../kibana-extra'), ]; if (!pluginScanDirs.every((p) => Path.isAbsolute(p))) { @@ -237,7 +245,8 @@ export class OptimizerConfig { options.maxWorkerCount, options.dist, options.profileWebpack, - options.themeTags + options.themeTags, + readLimits() ); } @@ -251,7 +260,8 @@ export class OptimizerConfig { public readonly maxWorkerCount: number, public readonly dist: boolean, public readonly profileWebpack: boolean, - public readonly themeTags: ThemeTags + public readonly themeTags: ThemeTags, + public readonly limits: Limits ) {} getWorkerConfig(optimizerCacheKey: unknown): WorkerConfig { diff --git a/packages/kbn-optimizer/src/report_optimizer_stats.ts b/packages/kbn-optimizer/src/report_optimizer_stats.ts index eff2bce0b827e..a0f59a3505e30 100644 --- a/packages/kbn-optimizer/src/report_optimizer_stats.ts +++ b/packages/kbn-optimizer/src/report_optimizer_stats.ts @@ -17,136 +17,41 @@ * under the License. */ -import Fs from 'fs'; -import Path from 'path'; - import { materialize, mergeMap, dematerialize } from 'rxjs/operators'; -import { CiStatsReporter, CiStatsMetrics, ToolingLog } from '@kbn/dev-utils'; +import { CiStatsReporter, ToolingLog } from '@kbn/dev-utils'; import { OptimizerUpdate$ } from './run_optimizer'; -import { OptimizerState, OptimizerConfig } from './optimizer'; +import { OptimizerConfig, getMetrics } from './optimizer'; import { pipeClosure } from './common'; -const flatten = (arr: Array): T[] => - arr.reduce((acc: T[], item) => acc.concat(item), []); - -interface Entry { - relPath: string; - stats: Fs.Stats; -} - -const IGNORED_EXTNAME = ['.map', '.br', '.gz']; - -const getFiles = (dir: string, parent?: string) => - flatten( - Fs.readdirSync(dir).map((name): Entry | Entry[] => { - const absPath = Path.join(dir, name); - const relPath = parent ? Path.join(parent, name) : name; - const stats = Fs.statSync(absPath); - - if (stats.isDirectory()) { - return getFiles(absPath, relPath); - } - - return { - relPath, - stats, - }; - }) - ).filter((file) => { - const filename = Path.basename(file.relPath); - if (filename.startsWith('.')) { - return false; - } - - const ext = Path.extname(filename); - if (IGNORED_EXTNAME.includes(ext)) { - return false; - } - - return true; - }); - export function reportOptimizerStats( reporter: CiStatsReporter, config: OptimizerConfig, log: ToolingLog ) { - return pipeClosure((update$: OptimizerUpdate$) => { - let lastState: OptimizerState | undefined; - return update$.pipe( + return pipeClosure((update$: OptimizerUpdate$) => + update$.pipe( materialize(), mergeMap(async (n) => { - if (n.kind === 'N' && n.value?.state) { - lastState = n.value?.state; - } - - if (n.kind === 'C' && lastState) { - await reporter.metrics( - flatten( - config.bundles.map((bundle) => { - // make the cache read from the cache file since it was likely updated by the worker - bundle.cache.refresh(); - - const outputFiles = getFiles(bundle.outputDir); - const entryName = `${bundle.id}.${bundle.type}.js`; - const entry = outputFiles.find((f) => f.relPath === entryName); - if (!entry) { - throw new Error( - `Unable to find bundle entry named [${entryName}] in [${bundle.outputDir}]` - ); - } - - const chunkPrefix = `${bundle.id}.chunk.`; - const asyncChunks = outputFiles.filter((f) => f.relPath.startsWith(chunkPrefix)); - const miscFiles = outputFiles.filter( - (f) => f !== entry && !asyncChunks.includes(f) - ); - - if (asyncChunks.length) { - log.verbose(bundle.id, 'async chunks', asyncChunks); - } - if (miscFiles.length) { - log.verbose(bundle.id, 'misc files', asyncChunks); - } - - const sumSize = (files: Entry[]) => - files.reduce((acc: number, f) => acc + f.stats!.size, 0); - - const metrics: CiStatsMetrics = [ - { - group: `@kbn/optimizer bundle module count`, - id: bundle.id, - value: bundle.cache.getModuleCount() || 0, - }, - { - group: `page load bundle size`, - id: bundle.id, - value: entry.stats!.size, - }, - { - group: `async chunks size`, - id: bundle.id, - value: sumSize(asyncChunks), - }, - { - group: `miscellaneous assets size`, - id: bundle.id, - value: sumSize(miscFiles), - }, - ]; - - log.info(bundle.id, 'metrics', metrics); - - return metrics; - }) - ) - ); + if (n.kind === 'C') { + const metrics = getMetrics(log, config); + + await reporter.metrics(metrics); + + for (const metric of metrics) { + if (metric.limit != null && metric.value > metric.limit) { + const value = metric.value.toLocaleString(); + const limit = metric.limit.toLocaleString(); + log.warning( + `Metric [${metric.group}] for [${metric.id}] of [${value}] over the limit of [${limit}]` + ); + } + } } return n; }), dematerialize() - ); - }); + ) + ); } diff --git a/packages/kbn-optimizer/src/worker/run_compilers.ts b/packages/kbn-optimizer/src/worker/run_compilers.ts index d78eb8214f607..0024d2801d173 100644 --- a/packages/kbn-optimizer/src/worker/run_compilers.ts +++ b/packages/kbn-optimizer/src/worker/run_compilers.ts @@ -182,7 +182,7 @@ const observeCompiler = ( ); bundle.cache.set({ - bundleRefExportIds, + bundleRefExportIds: bundleRefExportIds.sort(ascending((p) => p)), optimizerCacheKey: workerConfig.optimizerCacheKey, cacheKey: bundle.createCacheKey(files, mtimes), moduleCount, diff --git a/packages/kbn-optimizer/src/worker/webpack.config.ts b/packages/kbn-optimizer/src/worker/webpack.config.ts index 9f2c5654a8bd4..9678dd5de868b 100644 --- a/packages/kbn-optimizer/src/worker/webpack.config.ts +++ b/packages/kbn-optimizer/src/worker/webpack.config.ts @@ -200,6 +200,7 @@ export function getWebpackConfig(bundle: Bundle, bundleRefs: BundleRefs, worker: loader: 'babel-loader', options: { babelrc: false, + envName: worker.dist ? 'production' : 'development', presets: IS_CODE_COVERAGE ? [ISTANBUL_PRESET_PATH, BABEL_PRESET_PATH] : [BABEL_PRESET_PATH], @@ -216,7 +217,7 @@ export function getWebpackConfig(bundle: Bundle, bundleRefs: BundleRefs, worker: }, resolve: { - extensions: ['.js', '.ts', '.tsx', 'json'], + extensions: ['.js', '.ts', '.tsx', '.json'], mainFields: ['browser', 'main'], alias: { tinymath: require.resolve('tinymath/lib/tinymath.es5.js'), diff --git a/packages/kbn-plugin-helpers/package.json b/packages/kbn-plugin-helpers/package.json index f292387c12521..a2c4e1e2134e7 100644 --- a/packages/kbn-plugin-helpers/package.json +++ b/packages/kbn-plugin-helpers/package.json @@ -18,14 +18,14 @@ "del": "^5.1.0", "execa": "^4.0.2", "gulp-zip": "^5.0.2", - "inquirer": "^1.2.2", + "inquirer": "^7.3.3", "load-json-file": "^6.2.0", "vinyl-fs": "^3.0.3" }, "devDependencies": { "@types/extract-zip": "^1.6.2", "@types/gulp-zip": "^4.0.1", - "@types/inquirer": "^6.5.0", + "@types/inquirer": "^7.3.1", "extract-zip": "^2.0.1", "typescript": "4.0.2" } diff --git a/packages/kbn-pm/dist/index.js b/packages/kbn-pm/dist/index.js index 9a3bb1c687032..2e50f4214beb4 100644 --- a/packages/kbn-pm/dist/index.js +++ b/packages/kbn-pm/dist/index.js @@ -94,19 +94,19 @@ __webpack_require__.r(__webpack_exports__); /* harmony import */ var _cli__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(1); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "run", function() { return _cli__WEBPACK_IMPORTED_MODULE_0__["run"]; }); -/* harmony import */ var _production__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(503); +/* harmony import */ var _production__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(507); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "buildProductionProjects", function() { return _production__WEBPACK_IMPORTED_MODULE_1__["buildProductionProjects"]; }); -/* harmony import */ var _utils_projects__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(145); +/* harmony import */ var _utils_projects__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(146); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "getProjects", function() { return _utils_projects__WEBPACK_IMPORTED_MODULE_2__["getProjects"]; }); -/* harmony import */ var _utils_project__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(163); +/* harmony import */ var _utils_project__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(164); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "Project", function() { return _utils_project__WEBPACK_IMPORTED_MODULE_3__["Project"]; }); -/* harmony import */ var _utils_workspaces__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(279); +/* harmony import */ var _utils_workspaces__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(271); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "copyWorkspacePackages", function() { return _utils_workspaces__WEBPACK_IMPORTED_MODULE_4__["copyWorkspacePackages"]; }); -/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(280); +/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(272); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "getProjectPaths", function() { return _config__WEBPACK_IMPORTED_MODULE_5__["getProjectPaths"]; }); /* @@ -149,9 +149,9 @@ __webpack_require__.r(__webpack_exports__); /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_2__); /* harmony import */ var _kbn_dev_utils_tooling_log__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(5); /* harmony import */ var _kbn_dev_utils_tooling_log__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(_kbn_dev_utils_tooling_log__WEBPACK_IMPORTED_MODULE_3__); -/* harmony import */ var _commands__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(127); -/* harmony import */ var _run__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(496); -/* harmony import */ var _utils_log__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(143); +/* harmony import */ var _commands__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(128); +/* harmony import */ var _run__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(500); +/* harmony import */ var _utils_log__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(144); /* * Licensed to Elasticsearch B.V. under one or more contributor * license agreements. See the NOTICE file distributed with @@ -196,6 +196,7 @@ function help() { --oss Do not include the x-pack when running command. --skip-kibana-plugins Filter all plugins in ./plugins and ../kibana-extra when running command. --no-cache Disable the bootstrap cache + --no-validate Disable the bootstrap yarn.lock validation --verbose Set log level to verbose --debug Set log level to debug --quiet Set log level to error @@ -222,9 +223,10 @@ async function run(argv) { i: 'include' }, default: { - cache: true + cache: true, + validate: true }, - boolean: ['prefer-offline', 'frozen-lockfile', 'cache'] + boolean: ['prefer-offline', 'frozen-lockfile', 'cache', 'validate'] }); const args = options._; @@ -565,12 +567,12 @@ Object.defineProperty(exports, "__esModule", { value: true }); exports.ToolingLogCollectingWriter = exports.parseLogLevel = exports.pickLevelFromFlags = exports.ToolingLogTextWriter = exports.ToolingLog = void 0; var tooling_log_1 = __webpack_require__(6); Object.defineProperty(exports, "ToolingLog", { enumerable: true, get: function () { return tooling_log_1.ToolingLog; } }); -var tooling_log_text_writer_1 = __webpack_require__(110); +var tooling_log_text_writer_1 = __webpack_require__(111); Object.defineProperty(exports, "ToolingLogTextWriter", { enumerable: true, get: function () { return tooling_log_text_writer_1.ToolingLogTextWriter; } }); -var log_levels_1 = __webpack_require__(125); +var log_levels_1 = __webpack_require__(126); Object.defineProperty(exports, "pickLevelFromFlags", { enumerable: true, get: function () { return log_levels_1.pickLevelFromFlags; } }); Object.defineProperty(exports, "parseLogLevel", { enumerable: true, get: function () { return log_levels_1.parseLogLevel; } }); -var tooling_log_collecting_writer_1 = __webpack_require__(126); +var tooling_log_collecting_writer_1 = __webpack_require__(127); Object.defineProperty(exports, "ToolingLogCollectingWriter", { enumerable: true, get: function () { return tooling_log_collecting_writer_1.ToolingLogCollectingWriter; } }); @@ -602,7 +604,7 @@ Object.defineProperty(exports, "__esModule", { value: true }); exports.ToolingLog = void 0; const tslib_1 = __webpack_require__(7); const Rx = tslib_1.__importStar(__webpack_require__(8)); -const tooling_log_text_writer_1 = __webpack_require__(110); +const tooling_log_text_writer_1 = __webpack_require__(111); class ToolingLog { constructor(writerConfig) { this.identWidth = 0; @@ -711,7 +713,7 @@ PERFORMANCE OF THIS SOFTWARE. var extendStatics = function(d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || - function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; return extendStatics(d, b); }; @@ -805,8 +807,8 @@ var __createBinding = Object.create ? (function(o, m, k, k2) { o[k2] = m[k]; }); -function __exportStar(m, exports) { - for (var p in m) if (p !== "default" && !exports.hasOwnProperty(p)) __createBinding(exports, m, p); +function __exportStar(m, o) { + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(o, p)) __createBinding(o, m, p); } function __values(o) { @@ -896,7 +898,7 @@ var __setModuleDefault = Object.create ? (function(o, v) { function __importStar(mod) { if (mod && mod.__esModule) return mod; var result = {}; - if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; } @@ -952,16 +954,24 @@ __webpack_require__.r(__webpack_exports__); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "AsyncSubject", function() { return _internal_AsyncSubject__WEBPACK_IMPORTED_MODULE_7__["AsyncSubject"]; }); /* harmony import */ var _internal_scheduler_asap__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(51); -/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "asapScheduler", function() { return _internal_scheduler_asap__WEBPACK_IMPORTED_MODULE_8__["asap"]; }); +/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "asap", function() { return _internal_scheduler_asap__WEBPACK_IMPORTED_MODULE_8__["asap"]; }); + +/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "asapScheduler", function() { return _internal_scheduler_asap__WEBPACK_IMPORTED_MODULE_8__["asapScheduler"]; }); /* harmony import */ var _internal_scheduler_async__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(55); -/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "asyncScheduler", function() { return _internal_scheduler_async__WEBPACK_IMPORTED_MODULE_9__["async"]; }); +/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "async", function() { return _internal_scheduler_async__WEBPACK_IMPORTED_MODULE_9__["async"]; }); + +/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "asyncScheduler", function() { return _internal_scheduler_async__WEBPACK_IMPORTED_MODULE_9__["asyncScheduler"]; }); /* harmony import */ var _internal_scheduler_queue__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(34); -/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "queueScheduler", function() { return _internal_scheduler_queue__WEBPACK_IMPORTED_MODULE_10__["queue"]; }); +/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "queue", function() { return _internal_scheduler_queue__WEBPACK_IMPORTED_MODULE_10__["queue"]; }); + +/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "queueScheduler", function() { return _internal_scheduler_queue__WEBPACK_IMPORTED_MODULE_10__["queueScheduler"]; }); /* harmony import */ var _internal_scheduler_animationFrame__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(56); -/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "animationFrameScheduler", function() { return _internal_scheduler_animationFrame__WEBPACK_IMPORTED_MODULE_11__["animationFrame"]; }); +/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "animationFrame", function() { return _internal_scheduler_animationFrame__WEBPACK_IMPORTED_MODULE_11__["animationFrame"]; }); + +/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "animationFrameScheduler", function() { return _internal_scheduler_animationFrame__WEBPACK_IMPORTED_MODULE_11__["animationFrameScheduler"]; }); /* harmony import */ var _internal_scheduler_VirtualTimeScheduler__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(59); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "VirtualTimeScheduler", function() { return _internal_scheduler_VirtualTimeScheduler__WEBPACK_IMPORTED_MODULE_12__["VirtualTimeScheduler"]; }); @@ -1021,67 +1031,67 @@ __webpack_require__.r(__webpack_exports__); /* harmony import */ var _internal_observable_concat__WEBPACK_IMPORTED_MODULE_29__ = __webpack_require__(79); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "concat", function() { return _internal_observable_concat__WEBPACK_IMPORTED_MODULE_29__["concat"]; }); -/* harmony import */ var _internal_observable_defer__WEBPACK_IMPORTED_MODULE_30__ = __webpack_require__(90); +/* harmony import */ var _internal_observable_defer__WEBPACK_IMPORTED_MODULE_30__ = __webpack_require__(91); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "defer", function() { return _internal_observable_defer__WEBPACK_IMPORTED_MODULE_30__["defer"]; }); /* harmony import */ var _internal_observable_empty__WEBPACK_IMPORTED_MODULE_31__ = __webpack_require__(43); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "empty", function() { return _internal_observable_empty__WEBPACK_IMPORTED_MODULE_31__["empty"]; }); -/* harmony import */ var _internal_observable_forkJoin__WEBPACK_IMPORTED_MODULE_32__ = __webpack_require__(91); +/* harmony import */ var _internal_observable_forkJoin__WEBPACK_IMPORTED_MODULE_32__ = __webpack_require__(92); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "forkJoin", function() { return _internal_observable_forkJoin__WEBPACK_IMPORTED_MODULE_32__["forkJoin"]; }); /* harmony import */ var _internal_observable_from__WEBPACK_IMPORTED_MODULE_33__ = __webpack_require__(83); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "from", function() { return _internal_observable_from__WEBPACK_IMPORTED_MODULE_33__["from"]; }); -/* harmony import */ var _internal_observable_fromEvent__WEBPACK_IMPORTED_MODULE_34__ = __webpack_require__(92); +/* harmony import */ var _internal_observable_fromEvent__WEBPACK_IMPORTED_MODULE_34__ = __webpack_require__(93); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "fromEvent", function() { return _internal_observable_fromEvent__WEBPACK_IMPORTED_MODULE_34__["fromEvent"]; }); -/* harmony import */ var _internal_observable_fromEventPattern__WEBPACK_IMPORTED_MODULE_35__ = __webpack_require__(93); +/* harmony import */ var _internal_observable_fromEventPattern__WEBPACK_IMPORTED_MODULE_35__ = __webpack_require__(94); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "fromEventPattern", function() { return _internal_observable_fromEventPattern__WEBPACK_IMPORTED_MODULE_35__["fromEventPattern"]; }); -/* harmony import */ var _internal_observable_generate__WEBPACK_IMPORTED_MODULE_36__ = __webpack_require__(94); +/* harmony import */ var _internal_observable_generate__WEBPACK_IMPORTED_MODULE_36__ = __webpack_require__(95); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "generate", function() { return _internal_observable_generate__WEBPACK_IMPORTED_MODULE_36__["generate"]; }); -/* harmony import */ var _internal_observable_iif__WEBPACK_IMPORTED_MODULE_37__ = __webpack_require__(95); +/* harmony import */ var _internal_observable_iif__WEBPACK_IMPORTED_MODULE_37__ = __webpack_require__(96); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "iif", function() { return _internal_observable_iif__WEBPACK_IMPORTED_MODULE_37__["iif"]; }); -/* harmony import */ var _internal_observable_interval__WEBPACK_IMPORTED_MODULE_38__ = __webpack_require__(96); +/* harmony import */ var _internal_observable_interval__WEBPACK_IMPORTED_MODULE_38__ = __webpack_require__(97); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "interval", function() { return _internal_observable_interval__WEBPACK_IMPORTED_MODULE_38__["interval"]; }); -/* harmony import */ var _internal_observable_merge__WEBPACK_IMPORTED_MODULE_39__ = __webpack_require__(98); +/* harmony import */ var _internal_observable_merge__WEBPACK_IMPORTED_MODULE_39__ = __webpack_require__(99); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "merge", function() { return _internal_observable_merge__WEBPACK_IMPORTED_MODULE_39__["merge"]; }); -/* harmony import */ var _internal_observable_never__WEBPACK_IMPORTED_MODULE_40__ = __webpack_require__(99); +/* harmony import */ var _internal_observable_never__WEBPACK_IMPORTED_MODULE_40__ = __webpack_require__(100); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "never", function() { return _internal_observable_never__WEBPACK_IMPORTED_MODULE_40__["never"]; }); /* harmony import */ var _internal_observable_of__WEBPACK_IMPORTED_MODULE_41__ = __webpack_require__(44); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "of", function() { return _internal_observable_of__WEBPACK_IMPORTED_MODULE_41__["of"]; }); -/* harmony import */ var _internal_observable_onErrorResumeNext__WEBPACK_IMPORTED_MODULE_42__ = __webpack_require__(100); +/* harmony import */ var _internal_observable_onErrorResumeNext__WEBPACK_IMPORTED_MODULE_42__ = __webpack_require__(101); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "onErrorResumeNext", function() { return _internal_observable_onErrorResumeNext__WEBPACK_IMPORTED_MODULE_42__["onErrorResumeNext"]; }); -/* harmony import */ var _internal_observable_pairs__WEBPACK_IMPORTED_MODULE_43__ = __webpack_require__(101); +/* harmony import */ var _internal_observable_pairs__WEBPACK_IMPORTED_MODULE_43__ = __webpack_require__(102); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "pairs", function() { return _internal_observable_pairs__WEBPACK_IMPORTED_MODULE_43__["pairs"]; }); -/* harmony import */ var _internal_observable_partition__WEBPACK_IMPORTED_MODULE_44__ = __webpack_require__(102); +/* harmony import */ var _internal_observable_partition__WEBPACK_IMPORTED_MODULE_44__ = __webpack_require__(103); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "partition", function() { return _internal_observable_partition__WEBPACK_IMPORTED_MODULE_44__["partition"]; }); -/* harmony import */ var _internal_observable_race__WEBPACK_IMPORTED_MODULE_45__ = __webpack_require__(105); +/* harmony import */ var _internal_observable_race__WEBPACK_IMPORTED_MODULE_45__ = __webpack_require__(106); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "race", function() { return _internal_observable_race__WEBPACK_IMPORTED_MODULE_45__["race"]; }); -/* harmony import */ var _internal_observable_range__WEBPACK_IMPORTED_MODULE_46__ = __webpack_require__(106); +/* harmony import */ var _internal_observable_range__WEBPACK_IMPORTED_MODULE_46__ = __webpack_require__(107); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "range", function() { return _internal_observable_range__WEBPACK_IMPORTED_MODULE_46__["range"]; }); /* harmony import */ var _internal_observable_throwError__WEBPACK_IMPORTED_MODULE_47__ = __webpack_require__(49); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "throwError", function() { return _internal_observable_throwError__WEBPACK_IMPORTED_MODULE_47__["throwError"]; }); -/* harmony import */ var _internal_observable_timer__WEBPACK_IMPORTED_MODULE_48__ = __webpack_require__(107); +/* harmony import */ var _internal_observable_timer__WEBPACK_IMPORTED_MODULE_48__ = __webpack_require__(108); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "timer", function() { return _internal_observable_timer__WEBPACK_IMPORTED_MODULE_48__["timer"]; }); -/* harmony import */ var _internal_observable_using__WEBPACK_IMPORTED_MODULE_49__ = __webpack_require__(108); +/* harmony import */ var _internal_observable_using__WEBPACK_IMPORTED_MODULE_49__ = __webpack_require__(109); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "using", function() { return _internal_observable_using__WEBPACK_IMPORTED_MODULE_49__["using"]; }); -/* harmony import */ var _internal_observable_zip__WEBPACK_IMPORTED_MODULE_50__ = __webpack_require__(109); +/* harmony import */ var _internal_observable_zip__WEBPACK_IMPORTED_MODULE_50__ = __webpack_require__(110); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "zip", function() { return _internal_observable_zip__WEBPACK_IMPORTED_MODULE_50__["zip"]; }); /* harmony import */ var _internal_scheduled_scheduled__WEBPACK_IMPORTED_MODULE_51__ = __webpack_require__(84); @@ -1916,6 +1926,7 @@ var Subscription = /*@__PURE__*/ (function () { this._parentOrParents = null; this._subscriptions = null; if (unsubscribe) { + this._ctorUnsubscribe = true; this._unsubscribe = unsubscribe; } } @@ -1924,7 +1935,7 @@ var Subscription = /*@__PURE__*/ (function () { if (this.closed) { return; } - var _a = this, _parentOrParents = _a._parentOrParents, _unsubscribe = _a._unsubscribe, _subscriptions = _a._subscriptions; + var _a = this, _parentOrParents = _a._parentOrParents, _ctorUnsubscribe = _a._ctorUnsubscribe, _unsubscribe = _a._unsubscribe, _subscriptions = _a._subscriptions; this.closed = true; this._parentOrParents = null; this._subscriptions = null; @@ -1938,6 +1949,9 @@ var Subscription = /*@__PURE__*/ (function () { } } if (Object(_util_isFunction__WEBPACK_IMPORTED_MODULE_2__["isFunction"])(_unsubscribe)) { + if (_ctorUnsubscribe) { + this._unsubscribe = undefined; + } try { _unsubscribe.call(this); } @@ -3059,13 +3073,15 @@ var ReplayEvent = /*@__PURE__*/ (function () { "use strict"; __webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "queueScheduler", function() { return queueScheduler; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "queue", function() { return queue; }); /* harmony import */ var _QueueAction__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(35); /* harmony import */ var _QueueScheduler__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(38); /** PURE_IMPORTS_START _QueueAction,_QueueScheduler PURE_IMPORTS_END */ -var queue = /*@__PURE__*/ new _QueueScheduler__WEBPACK_IMPORTED_MODULE_1__["QueueScheduler"](_QueueAction__WEBPACK_IMPORTED_MODULE_0__["QueueAction"]); +var queueScheduler = /*@__PURE__*/ new _QueueScheduler__WEBPACK_IMPORTED_MODULE_1__["QueueScheduler"](_QueueAction__WEBPACK_IMPORTED_MODULE_0__["QueueAction"]); +var queue = queueScheduler; //# sourceMappingURL=queue.js.map @@ -3781,13 +3797,15 @@ var AsyncSubject = /*@__PURE__*/ (function (_super) { "use strict"; __webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "asapScheduler", function() { return asapScheduler; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "asap", function() { return asap; }); /* harmony import */ var _AsapAction__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(52); /* harmony import */ var _AsapScheduler__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(54); /** PURE_IMPORTS_START _AsapAction,_AsapScheduler PURE_IMPORTS_END */ -var asap = /*@__PURE__*/ new _AsapScheduler__WEBPACK_IMPORTED_MODULE_1__["AsapScheduler"](_AsapAction__WEBPACK_IMPORTED_MODULE_0__["AsapAction"]); +var asapScheduler = /*@__PURE__*/ new _AsapScheduler__WEBPACK_IMPORTED_MODULE_1__["AsapScheduler"](_AsapAction__WEBPACK_IMPORTED_MODULE_0__["AsapAction"]); +var asap = asapScheduler; //# sourceMappingURL=asap.js.map @@ -3930,13 +3948,15 @@ var AsapScheduler = /*@__PURE__*/ (function (_super) { "use strict"; __webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "asyncScheduler", function() { return asyncScheduler; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "async", function() { return async; }); /* harmony import */ var _AsyncAction__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(36); /* harmony import */ var _AsyncScheduler__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(39); /** PURE_IMPORTS_START _AsyncAction,_AsyncScheduler PURE_IMPORTS_END */ -var async = /*@__PURE__*/ new _AsyncScheduler__WEBPACK_IMPORTED_MODULE_1__["AsyncScheduler"](_AsyncAction__WEBPACK_IMPORTED_MODULE_0__["AsyncAction"]); +var asyncScheduler = /*@__PURE__*/ new _AsyncScheduler__WEBPACK_IMPORTED_MODULE_1__["AsyncScheduler"](_AsyncAction__WEBPACK_IMPORTED_MODULE_0__["AsyncAction"]); +var async = asyncScheduler; //# sourceMappingURL=async.js.map @@ -3946,13 +3966,15 @@ var async = /*@__PURE__*/ new _AsyncScheduler__WEBPACK_IMPORTED_MODULE_1__["Asyn "use strict"; __webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "animationFrameScheduler", function() { return animationFrameScheduler; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "animationFrame", function() { return animationFrame; }); /* harmony import */ var _AnimationFrameAction__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(57); /* harmony import */ var _AnimationFrameScheduler__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(58); /** PURE_IMPORTS_START _AnimationFrameAction,_AnimationFrameScheduler PURE_IMPORTS_END */ -var animationFrame = /*@__PURE__*/ new _AnimationFrameScheduler__WEBPACK_IMPORTED_MODULE_1__["AnimationFrameScheduler"](_AnimationFrameAction__WEBPACK_IMPORTED_MODULE_0__["AnimationFrameAction"]); +var animationFrameScheduler = /*@__PURE__*/ new _AnimationFrameScheduler__WEBPACK_IMPORTED_MODULE_1__["AnimationFrameScheduler"](_AnimationFrameAction__WEBPACK_IMPORTED_MODULE_0__["AnimationFrameAction"]); +var animationFrame = animationFrameScheduler; //# sourceMappingURL=animationFrame.js.map @@ -4599,8 +4621,8 @@ function combineLatest() { for (var _i = 0; _i < arguments.length; _i++) { observables[_i] = arguments[_i]; } - var resultSelector = null; - var scheduler = null; + var resultSelector = undefined; + var scheduler = undefined; if (Object(_util_isScheduler__WEBPACK_IMPORTED_MODULE_1__["isScheduler"])(observables[observables.length - 1])) { scheduler = observables.pop(); } @@ -4647,7 +4669,7 @@ var CombineLatestSubscriber = /*@__PURE__*/ (function (_super) { this.toRespond = len; for (var i = 0; i < len; i++) { var observable = observables[i]; - this.add(Object(_util_subscribeToResult__WEBPACK_IMPORTED_MODULE_4__["subscribeToResult"])(this, observable, observable, i)); + this.add(Object(_util_subscribeToResult__WEBPACK_IMPORTED_MODULE_4__["subscribeToResult"])(this, observable, undefined, i)); } } }; @@ -4656,7 +4678,7 @@ var CombineLatestSubscriber = /*@__PURE__*/ (function (_super) { this.destination.complete(); } }; - CombineLatestSubscriber.prototype.notifyNext = function (outerValue, innerValue, outerIndex, innerIndex, innerSub) { + CombineLatestSubscriber.prototype.notifyNext = function (_outerValue, innerValue, outerIndex) { var values = this.values; var oldVal = values[outerIndex]; var toRespond = !this.toRespond @@ -4877,7 +4899,14 @@ var subscribeToIterable = function (iterable) { return function (subscriber) { var iterator = iterable[_symbol_iterator__WEBPACK_IMPORTED_MODULE_0__["iterator"]](); do { - var item = iterator.next(); + var item = void 0; + try { + item = iterator.next(); + } + catch (err) { + subscriber.error(err); + return subscriber; + } if (item.done) { subscriber.complete(); break; @@ -5039,15 +5068,12 @@ __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "mergeMap", function() { return mergeMap; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "MergeMapOperator", function() { return MergeMapOperator; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "MergeMapSubscriber", function() { return MergeMapSubscriber; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "flatMap", function() { return flatMap; }); /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(12); -/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(70); -/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(69); -/* harmony import */ var _InnerSubscriber__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(71); -/* harmony import */ var _map__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(66); -/* harmony import */ var _observable_from__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(83); -/** PURE_IMPORTS_START tslib,_util_subscribeToResult,_OuterSubscriber,_InnerSubscriber,_map,_observable_from PURE_IMPORTS_END */ - - +/* harmony import */ var _map__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(66); +/* harmony import */ var _observable_from__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(83); +/* harmony import */ var _innerSubscribe__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(90); +/** PURE_IMPORTS_START tslib,_map,_observable_from,_innerSubscribe PURE_IMPORTS_END */ @@ -5057,7 +5083,7 @@ function mergeMap(project, resultSelector, concurrent) { concurrent = Number.POSITIVE_INFINITY; } if (typeof resultSelector === 'function') { - return function (source) { return source.pipe(mergeMap(function (a, i) { return Object(_observable_from__WEBPACK_IMPORTED_MODULE_5__["from"])(project(a, i)).pipe(Object(_map__WEBPACK_IMPORTED_MODULE_4__["map"])(function (b, ii) { return resultSelector(a, b, i, ii); })); }, concurrent)); }; + return function (source) { return source.pipe(mergeMap(function (a, i) { return Object(_observable_from__WEBPACK_IMPORTED_MODULE_2__["from"])(project(a, i)).pipe(Object(_map__WEBPACK_IMPORTED_MODULE_1__["map"])(function (b, ii) { return resultSelector(a, b, i, ii); })); }, concurrent)); }; } else if (typeof resultSelector === 'number') { concurrent = resultSelector; @@ -5112,13 +5138,13 @@ var MergeMapSubscriber = /*@__PURE__*/ (function (_super) { return; } this.active++; - this._innerSub(result, value, index); + this._innerSub(result); }; - MergeMapSubscriber.prototype._innerSub = function (ish, value, index) { - var innerSubscriber = new _InnerSubscriber__WEBPACK_IMPORTED_MODULE_3__["InnerSubscriber"](this, value, index); + MergeMapSubscriber.prototype._innerSub = function (ish) { + var innerSubscriber = new _innerSubscribe__WEBPACK_IMPORTED_MODULE_3__["SimpleInnerSubscriber"](this); var destination = this.destination; destination.add(innerSubscriber); - var innerSubscription = Object(_util_subscribeToResult__WEBPACK_IMPORTED_MODULE_1__["subscribeToResult"])(this, ish, undefined, undefined, innerSubscriber); + var innerSubscription = Object(_innerSubscribe__WEBPACK_IMPORTED_MODULE_3__["innerSubscribe"])(ish, innerSubscriber); if (innerSubscription !== innerSubscriber) { destination.add(innerSubscription); } @@ -5130,12 +5156,11 @@ var MergeMapSubscriber = /*@__PURE__*/ (function (_super) { } this.unsubscribe(); }; - MergeMapSubscriber.prototype.notifyNext = function (outerValue, innerValue, outerIndex, innerIndex, innerSub) { + MergeMapSubscriber.prototype.notifyNext = function (innerValue) { this.destination.next(innerValue); }; - MergeMapSubscriber.prototype.notifyComplete = function (innerSub) { + MergeMapSubscriber.prototype.notifyComplete = function () { var buffer = this.buffer; - this.remove(innerSub); this.active--; if (buffer.length > 0) { this._next(buffer.shift()); @@ -5145,8 +5170,9 @@ var MergeMapSubscriber = /*@__PURE__*/ (function (_super) { } }; return MergeMapSubscriber; -}(_OuterSubscriber__WEBPACK_IMPORTED_MODULE_2__["OuterSubscriber"])); +}(_innerSubscribe__WEBPACK_IMPORTED_MODULE_3__["SimpleOuterSubscriber"])); +var flatMap = mergeMap; //# sourceMappingURL=mergeMap.js.map @@ -5378,6 +5404,116 @@ function isIterable(input) { /* 90 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "SimpleInnerSubscriber", function() { return SimpleInnerSubscriber; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ComplexInnerSubscriber", function() { return ComplexInnerSubscriber; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "SimpleOuterSubscriber", function() { return SimpleOuterSubscriber; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ComplexOuterSubscriber", function() { return ComplexOuterSubscriber; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "innerSubscribe", function() { return innerSubscribe; }); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(12); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(11); +/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(9); +/* harmony import */ var _util_subscribeTo__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(72); +/** PURE_IMPORTS_START tslib,_Subscriber,_Observable,_util_subscribeTo PURE_IMPORTS_END */ + + + + +var SimpleInnerSubscriber = /*@__PURE__*/ (function (_super) { + tslib__WEBPACK_IMPORTED_MODULE_0__["__extends"](SimpleInnerSubscriber, _super); + function SimpleInnerSubscriber(parent) { + var _this = _super.call(this) || this; + _this.parent = parent; + return _this; + } + SimpleInnerSubscriber.prototype._next = function (value) { + this.parent.notifyNext(value); + }; + SimpleInnerSubscriber.prototype._error = function (error) { + this.parent.notifyError(error); + this.unsubscribe(); + }; + SimpleInnerSubscriber.prototype._complete = function () { + this.parent.notifyComplete(); + this.unsubscribe(); + }; + return SimpleInnerSubscriber; +}(_Subscriber__WEBPACK_IMPORTED_MODULE_1__["Subscriber"])); + +var ComplexInnerSubscriber = /*@__PURE__*/ (function (_super) { + tslib__WEBPACK_IMPORTED_MODULE_0__["__extends"](ComplexInnerSubscriber, _super); + function ComplexInnerSubscriber(parent, outerValue, outerIndex) { + var _this = _super.call(this) || this; + _this.parent = parent; + _this.outerValue = outerValue; + _this.outerIndex = outerIndex; + return _this; + } + ComplexInnerSubscriber.prototype._next = function (value) { + this.parent.notifyNext(this.outerValue, value, this.outerIndex, this); + }; + ComplexInnerSubscriber.prototype._error = function (error) { + this.parent.notifyError(error); + this.unsubscribe(); + }; + ComplexInnerSubscriber.prototype._complete = function () { + this.parent.notifyComplete(this); + this.unsubscribe(); + }; + return ComplexInnerSubscriber; +}(_Subscriber__WEBPACK_IMPORTED_MODULE_1__["Subscriber"])); + +var SimpleOuterSubscriber = /*@__PURE__*/ (function (_super) { + tslib__WEBPACK_IMPORTED_MODULE_0__["__extends"](SimpleOuterSubscriber, _super); + function SimpleOuterSubscriber() { + return _super !== null && _super.apply(this, arguments) || this; + } + SimpleOuterSubscriber.prototype.notifyNext = function (innerValue) { + this.destination.next(innerValue); + }; + SimpleOuterSubscriber.prototype.notifyError = function (err) { + this.destination.error(err); + }; + SimpleOuterSubscriber.prototype.notifyComplete = function () { + this.destination.complete(); + }; + return SimpleOuterSubscriber; +}(_Subscriber__WEBPACK_IMPORTED_MODULE_1__["Subscriber"])); + +var ComplexOuterSubscriber = /*@__PURE__*/ (function (_super) { + tslib__WEBPACK_IMPORTED_MODULE_0__["__extends"](ComplexOuterSubscriber, _super); + function ComplexOuterSubscriber() { + return _super !== null && _super.apply(this, arguments) || this; + } + ComplexOuterSubscriber.prototype.notifyNext = function (_outerValue, innerValue, _outerIndex, _innerSub) { + this.destination.next(innerValue); + }; + ComplexOuterSubscriber.prototype.notifyError = function (error) { + this.destination.error(error); + }; + ComplexOuterSubscriber.prototype.notifyComplete = function (_innerSub) { + this.destination.complete(); + }; + return ComplexOuterSubscriber; +}(_Subscriber__WEBPACK_IMPORTED_MODULE_1__["Subscriber"])); + +function innerSubscribe(result, innerSubscriber) { + if (innerSubscriber.closed) { + return undefined; + } + if (result instanceof _Observable__WEBPACK_IMPORTED_MODULE_2__["Observable"]) { + return result.subscribe(innerSubscriber); + } + return Object(_util_subscribeTo__WEBPACK_IMPORTED_MODULE_3__["subscribeTo"])(result)(innerSubscriber); +} +//# sourceMappingURL=innerSubscribe.js.map + + +/***/ }), +/* 91 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "defer", function() { return defer; }); @@ -5406,7 +5542,7 @@ function defer(observableFactory) { /***/ }), -/* 91 */ +/* 92 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -5489,7 +5625,7 @@ function forkJoinInternal(sources, keys) { /***/ }), -/* 92 */ +/* 93 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -5565,7 +5701,7 @@ function isEventTarget(sourceObj) { /***/ }), -/* 93 */ +/* 94 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -5610,7 +5746,7 @@ function fromEventPattern(addHandler, removeHandler, resultSelector) { /***/ }), -/* 94 */ +/* 95 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -5747,13 +5883,13 @@ function dispatch(state) { /***/ }), -/* 95 */ +/* 96 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "iif", function() { return iif; }); -/* harmony import */ var _defer__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(90); +/* harmony import */ var _defer__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(91); /* harmony import */ var _empty__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(43); /** PURE_IMPORTS_START _defer,_empty PURE_IMPORTS_END */ @@ -5771,7 +5907,7 @@ function iif(condition, trueResult, falseResult) { /***/ }), -/* 96 */ +/* 97 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -5779,7 +5915,7 @@ __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "interval", function() { return interval; }); /* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(9); /* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(55); -/* harmony import */ var _util_isNumeric__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(97); +/* harmony import */ var _util_isNumeric__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(98); /** PURE_IMPORTS_START _Observable,_scheduler_async,_util_isNumeric PURE_IMPORTS_END */ @@ -5811,7 +5947,7 @@ function dispatch(state) { /***/ }), -/* 97 */ +/* 98 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -5827,7 +5963,7 @@ function isNumeric(val) { /***/ }), -/* 98 */ +/* 99 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -5868,7 +6004,7 @@ function merge() { /***/ }), -/* 99 */ +/* 100 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -5888,7 +6024,7 @@ function never() { /***/ }), -/* 100 */ +/* 101 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -5928,7 +6064,7 @@ function onErrorResumeNext() { /***/ }), -/* 101 */ +/* 102 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -5979,15 +6115,15 @@ function dispatch(state) { /***/ }), -/* 102 */ +/* 103 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "partition", function() { return partition; }); -/* harmony import */ var _util_not__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(103); +/* harmony import */ var _util_not__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(104); /* harmony import */ var _util_subscribeTo__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(72); -/* harmony import */ var _operators_filter__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(104); +/* harmony import */ var _operators_filter__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(105); /* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(9); /** PURE_IMPORTS_START _util_not,_util_subscribeTo,_operators_filter,_Observable PURE_IMPORTS_END */ @@ -6004,7 +6140,7 @@ function partition(source, predicate, thisArg) { /***/ }), -/* 103 */ +/* 104 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -6023,7 +6159,7 @@ function not(pred, thisArg) { /***/ }), -/* 104 */ +/* 105 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -6077,7 +6213,7 @@ var FilterSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 105 */ +/* 106 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -6141,7 +6277,7 @@ var RaceSubscriber = /*@__PURE__*/ (function (_super) { else { for (var i = 0; i < len && !this.hasFirst; i++) { var observable = observables[i]; - var subscription = Object(_util_subscribeToResult__WEBPACK_IMPORTED_MODULE_4__["subscribeToResult"])(this, observable, observable, i); + var subscription = Object(_util_subscribeToResult__WEBPACK_IMPORTED_MODULE_4__["subscribeToResult"])(this, observable, undefined, i); if (this.subscriptions) { this.subscriptions.push(subscription); } @@ -6150,7 +6286,7 @@ var RaceSubscriber = /*@__PURE__*/ (function (_super) { this.observables = null; } }; - RaceSubscriber.prototype.notifyNext = function (outerValue, innerValue, outerIndex, innerIndex, innerSub) { + RaceSubscriber.prototype.notifyNext = function (_outerValue, innerValue, outerIndex) { if (!this.hasFirst) { this.hasFirst = true; for (var i = 0; i < this.subscriptions.length; i++) { @@ -6171,7 +6307,7 @@ var RaceSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 106 */ +/* 107 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -6230,7 +6366,7 @@ function dispatch(state) { /***/ }), -/* 107 */ +/* 108 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -6238,7 +6374,7 @@ __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "timer", function() { return timer; }); /* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(9); /* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(55); -/* harmony import */ var _util_isNumeric__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(97); +/* harmony import */ var _util_isNumeric__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(98); /* harmony import */ var _util_isScheduler__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(45); /** PURE_IMPORTS_START _Observable,_scheduler_async,_util_isNumeric,_util_isScheduler PURE_IMPORTS_END */ @@ -6284,7 +6420,7 @@ function dispatch(state) { /***/ }), -/* 108 */ +/* 109 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -6329,7 +6465,7 @@ function using(resourceFactory, observableFactory) { /***/ }), -/* 109 */ +/* 110 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -6341,11 +6477,9 @@ __webpack_require__.r(__webpack_exports__); /* harmony import */ var _fromArray__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(46); /* harmony import */ var _util_isArray__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(18); /* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(11); -/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(69); -/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(70); -/* harmony import */ var _internal_symbol_iterator__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(75); -/** PURE_IMPORTS_START tslib,_fromArray,_util_isArray,_Subscriber,_OuterSubscriber,_util_subscribeToResult,_.._internal_symbol_iterator PURE_IMPORTS_END */ - +/* harmony import */ var _internal_symbol_iterator__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(75); +/* harmony import */ var _innerSubscribe__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(90); +/** PURE_IMPORTS_START tslib,_fromArray,_util_isArray,_Subscriber,_.._internal_symbol_iterator,_innerSubscribe PURE_IMPORTS_END */ @@ -6380,10 +6514,10 @@ var ZipSubscriber = /*@__PURE__*/ (function (_super) { values = Object.create(null); } var _this = _super.call(this, destination) || this; + _this.resultSelector = resultSelector; _this.iterators = []; _this.active = 0; - _this.resultSelector = (typeof resultSelector === 'function') ? resultSelector : null; - _this.values = values; + _this.resultSelector = (typeof resultSelector === 'function') ? resultSelector : undefined; return _this; } ZipSubscriber.prototype._next = function (value) { @@ -6391,8 +6525,8 @@ var ZipSubscriber = /*@__PURE__*/ (function (_super) { if (Object(_util_isArray__WEBPACK_IMPORTED_MODULE_2__["isArray"])(value)) { iterators.push(new StaticArrayIterator(value)); } - else if (typeof value[_internal_symbol_iterator__WEBPACK_IMPORTED_MODULE_6__["iterator"]] === 'function') { - iterators.push(new StaticIterator(value[_internal_symbol_iterator__WEBPACK_IMPORTED_MODULE_6__["iterator"]]())); + else if (typeof value[_internal_symbol_iterator__WEBPACK_IMPORTED_MODULE_4__["iterator"]] === 'function') { + iterators.push(new StaticIterator(value[_internal_symbol_iterator__WEBPACK_IMPORTED_MODULE_4__["iterator"]]())); } else { iterators.push(new ZipBufferIterator(this.destination, this, value)); @@ -6411,7 +6545,7 @@ var ZipSubscriber = /*@__PURE__*/ (function (_super) { var iterator = iterators[i]; if (iterator.stillUnsubscribed) { var destination = this.destination; - destination.add(iterator.subscribe(iterator, i)); + destination.add(iterator.subscribe()); } else { this.active--; @@ -6487,7 +6621,7 @@ var StaticIterator = /*@__PURE__*/ (function () { }; StaticIterator.prototype.hasCompleted = function () { var nextResult = this.nextResult; - return nextResult && nextResult.done; + return Boolean(nextResult && nextResult.done); }; return StaticIterator; }()); @@ -6498,7 +6632,7 @@ var StaticArrayIterator = /*@__PURE__*/ (function () { this.length = 0; this.length = array.length; } - StaticArrayIterator.prototype[_internal_symbol_iterator__WEBPACK_IMPORTED_MODULE_6__["iterator"]] = function () { + StaticArrayIterator.prototype[_internal_symbol_iterator__WEBPACK_IMPORTED_MODULE_4__["iterator"]] = function () { return this; }; StaticArrayIterator.prototype.next = function (value) { @@ -6525,7 +6659,7 @@ var ZipBufferIterator = /*@__PURE__*/ (function (_super) { _this.isComplete = false; return _this; } - ZipBufferIterator.prototype[_internal_symbol_iterator__WEBPACK_IMPORTED_MODULE_6__["iterator"]] = function () { + ZipBufferIterator.prototype[_internal_symbol_iterator__WEBPACK_IMPORTED_MODULE_4__["iterator"]] = function () { return this; }; ZipBufferIterator.prototype.next = function () { @@ -6552,20 +6686,20 @@ var ZipBufferIterator = /*@__PURE__*/ (function (_super) { this.destination.complete(); } }; - ZipBufferIterator.prototype.notifyNext = function (outerValue, innerValue, outerIndex, innerIndex, innerSub) { + ZipBufferIterator.prototype.notifyNext = function (innerValue) { this.buffer.push(innerValue); this.parent.checkIterators(); }; - ZipBufferIterator.prototype.subscribe = function (value, index) { - return Object(_util_subscribeToResult__WEBPACK_IMPORTED_MODULE_5__["subscribeToResult"])(this, this.observable, this, index); + ZipBufferIterator.prototype.subscribe = function () { + return Object(_innerSubscribe__WEBPACK_IMPORTED_MODULE_5__["innerSubscribe"])(this.observable, new _innerSubscribe__WEBPACK_IMPORTED_MODULE_5__["SimpleInnerSubscriber"](this)); }; return ZipBufferIterator; -}(_OuterSubscriber__WEBPACK_IMPORTED_MODULE_4__["OuterSubscriber"])); +}(_innerSubscribe__WEBPACK_IMPORTED_MODULE_5__["SimpleOuterSubscriber"])); //# sourceMappingURL=zip.js.map /***/ }), -/* 110 */ +/* 111 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -6591,9 +6725,9 @@ var ZipBufferIterator = /*@__PURE__*/ (function (_super) { Object.defineProperty(exports, "__esModule", { value: true }); exports.ToolingLogTextWriter = void 0; const tslib_1 = __webpack_require__(7); -const util_1 = __webpack_require__(111); -const chalk_1 = tslib_1.__importDefault(__webpack_require__(112)); -const log_levels_1 = __webpack_require__(125); +const util_1 = __webpack_require__(112); +const chalk_1 = tslib_1.__importDefault(__webpack_require__(113)); +const log_levels_1 = __webpack_require__(126); const { magentaBright, yellow, red, blue, green, dim } = chalk_1.default; const PREFIX_INDENT = ' '.repeat(6); const MSG_PREFIXES = { @@ -6660,23 +6794,23 @@ exports.ToolingLogTextWriter = ToolingLogTextWriter; /***/ }), -/* 111 */ +/* 112 */ /***/ (function(module, exports) { module.exports = require("util"); /***/ }), -/* 112 */ +/* 113 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const ansiStyles = __webpack_require__(113); -const {stdout: stdoutColor, stderr: stderrColor} = __webpack_require__(119); +const ansiStyles = __webpack_require__(114); +const {stdout: stdoutColor, stderr: stderrColor} = __webpack_require__(120); const { stringReplaceAll, stringEncaseCRLFWithFirstIndex -} = __webpack_require__(123); +} = __webpack_require__(124); const {isArray} = Array; @@ -6885,7 +7019,7 @@ const chalkTag = (chalk, ...strings) => { } if (template === undefined) { - template = __webpack_require__(124); + template = __webpack_require__(125); } return template(chalk, parts.join('')); @@ -6902,7 +7036,7 @@ module.exports = chalk; /***/ }), -/* 113 */ +/* 114 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -6948,7 +7082,7 @@ const setLazyProperty = (object, property, get) => { let colorConvert; const makeDynamicStyles = (wrap, targetSpace, identity, isBackground) => { if (colorConvert === undefined) { - colorConvert = __webpack_require__(115); + colorConvert = __webpack_require__(116); } const offset = isBackground ? 10 : 0; @@ -7070,10 +7204,10 @@ Object.defineProperty(module, 'exports', { get: assembleStyles }); -/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(114)(module))) +/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(115)(module))) /***/ }), -/* 114 */ +/* 115 */ /***/ (function(module, exports) { module.exports = function(module) { @@ -7101,11 +7235,11 @@ module.exports = function(module) { /***/ }), -/* 115 */ +/* 116 */ /***/ (function(module, exports, __webpack_require__) { -const conversions = __webpack_require__(116); -const route = __webpack_require__(118); +const conversions = __webpack_require__(117); +const route = __webpack_require__(119); const convert = {}; @@ -7188,12 +7322,12 @@ module.exports = convert; /***/ }), -/* 116 */ +/* 117 */ /***/ (function(module, exports, __webpack_require__) { /* MIT license */ /* eslint-disable no-mixed-operators */ -const cssKeywords = __webpack_require__(117); +const cssKeywords = __webpack_require__(118); // NOTE: conversions should only return primitive values (i.e. arrays, or // values that give correct `typeof` results). @@ -8033,7 +8167,7 @@ convert.rgb.gray = function (rgb) { /***/ }), -/* 117 */ +/* 118 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -8192,10 +8326,10 @@ module.exports = { /***/ }), -/* 118 */ +/* 119 */ /***/ (function(module, exports, __webpack_require__) { -const conversions = __webpack_require__(116); +const conversions = __webpack_require__(117); /* This function routes a model to all other models. @@ -8295,14 +8429,14 @@ module.exports = function (fromModel) { /***/ }), -/* 119 */ +/* 120 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const os = __webpack_require__(120); -const tty = __webpack_require__(121); -const hasFlag = __webpack_require__(122); +const os = __webpack_require__(121); +const tty = __webpack_require__(122); +const hasFlag = __webpack_require__(123); const {env} = process; @@ -8441,19 +8575,19 @@ module.exports = { /***/ }), -/* 120 */ +/* 121 */ /***/ (function(module, exports) { module.exports = require("os"); /***/ }), -/* 121 */ +/* 122 */ /***/ (function(module, exports) { module.exports = require("tty"); /***/ }), -/* 122 */ +/* 123 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -8468,7 +8602,7 @@ module.exports = (flag, argv = process.argv) => { /***/ }), -/* 123 */ +/* 124 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -8514,7 +8648,7 @@ module.exports = { /***/ }), -/* 124 */ +/* 125 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -8655,7 +8789,7 @@ module.exports = (chalk, temporary) => { /***/ }), -/* 125 */ +/* 126 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -8712,7 +8846,7 @@ exports.parseLogLevel = parseLogLevel; /***/ }), -/* 126 */ +/* 127 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -8737,7 +8871,7 @@ exports.parseLogLevel = parseLogLevel; */ Object.defineProperty(exports, "__esModule", { value: true }); exports.ToolingLogCollectingWriter = void 0; -const tooling_log_text_writer_1 = __webpack_require__(110); +const tooling_log_text_writer_1 = __webpack_require__(111); class ToolingLogCollectingWriter extends tooling_log_text_writer_1.ToolingLogTextWriter { constructor(level = 'verbose') { super({ @@ -8756,16 +8890,16 @@ exports.ToolingLogCollectingWriter = ToolingLogCollectingWriter; /***/ }), -/* 127 */ +/* 128 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "commands", function() { return commands; }); -/* harmony import */ var _bootstrap__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(128); -/* harmony import */ var _clean__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(287); -/* harmony import */ var _run__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(395); -/* harmony import */ var _watch__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(396); +/* harmony import */ var _bootstrap__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(129); +/* harmony import */ var _clean__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(280); +/* harmony import */ var _run__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(399); +/* harmony import */ var _watch__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(400); /* * Licensed to Elasticsearch B.V. under one or more contributor * license agreements. See the NOTICE file distributed with @@ -8796,18 +8930,20 @@ const commands = { }; /***/ }), -/* 128 */ +/* 129 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "BootstrapCommand", function() { return BootstrapCommand; }); -/* harmony import */ var _utils_link_project_executables__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(129); -/* harmony import */ var _utils_log__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(143); -/* harmony import */ var _utils_parallelize__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(144); -/* harmony import */ var _utils_projects__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(145); -/* harmony import */ var _utils_project_checksums__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(281); -/* harmony import */ var _utils_bootstrap_cache_file__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(286); +/* harmony import */ var _utils_link_project_executables__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(130); +/* harmony import */ var _utils_log__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(144); +/* harmony import */ var _utils_parallelize__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(145); +/* harmony import */ var _utils_projects__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(146); +/* harmony import */ var _utils_project_checksums__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(273); +/* harmony import */ var _utils_bootstrap_cache_file__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(278); +/* harmony import */ var _utils_yarn_lock__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(275); +/* harmony import */ var _utils_validate_yarn_lock__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(279); /* * Licensed to Elasticsearch B.V. under one or more contributor * license agreements. See the NOTICE file distributed with @@ -8832,6 +8968,8 @@ __webpack_require__.r(__webpack_exports__); + + const BootstrapCommand = { description: 'Install dependencies and crosslink projects', name: 'bootstrap', @@ -8861,6 +8999,12 @@ const BootstrapCommand = { } } + const yarnLock = await Object(_utils_yarn_lock__WEBPACK_IMPORTED_MODULE_6__["readYarnLock"])(kbn); + + if (options.validate) { + await Object(_utils_validate_yarn_lock__WEBPACK_IMPORTED_MODULE_7__["validateYarnLock"])(kbn, yarnLock); + } + await Object(_utils_link_project_executables__WEBPACK_IMPORTED_MODULE_0__["linkProjectExecutables"])(projects, projectGraph); /** * At the end of the bootstrapping process we call all `kbn:bootstrap` scripts @@ -8869,7 +9013,7 @@ const BootstrapCommand = { * have to, as it will slow down the bootstrapping process. */ - const checksums = await Object(_utils_project_checksums__WEBPACK_IMPORTED_MODULE_4__["getAllChecksums"])(kbn, _utils_log__WEBPACK_IMPORTED_MODULE_1__["log"]); + const checksums = await Object(_utils_project_checksums__WEBPACK_IMPORTED_MODULE_4__["getAllChecksums"])(kbn, _utils_log__WEBPACK_IMPORTED_MODULE_1__["log"], yarnLock); const caches = new Map(); let cachedProjectCount = 0; @@ -8910,7 +9054,7 @@ const BootstrapCommand = { }; /***/ }), -/* 129 */ +/* 130 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -8918,8 +9062,8 @@ __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "linkProjectExecutables", function() { return linkProjectExecutables; }); /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(4); /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_0__); -/* harmony import */ var _fs__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(130); -/* harmony import */ var _log__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(143); +/* harmony import */ var _fs__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(131); +/* harmony import */ var _log__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(144); /* * Licensed to Elasticsearch B.V. under one or more contributor * license agreements. See the NOTICE file distributed with @@ -8981,12 +9125,13 @@ async function linkProjectExecutables(projectsByName, projectGraph) { } /***/ }), -/* 130 */ +/* 131 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "readFile", function() { return readFile; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "writeFile", function() { return writeFile; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "chmod", function() { return chmod; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "mkdirp", function() { return mkdirp; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "unlink", function() { return unlink; }); @@ -8995,15 +9140,15 @@ __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "isDirectory", function() { return isDirectory; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "isFile", function() { return isFile; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "createSymlink", function() { return createSymlink; }); -/* harmony import */ var cmd_shim__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(131); +/* harmony import */ var cmd_shim__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(132); /* harmony import */ var cmd_shim__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(cmd_shim__WEBPACK_IMPORTED_MODULE_0__); -/* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(133); +/* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(134); /* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(fs__WEBPACK_IMPORTED_MODULE_1__); -/* harmony import */ var ncp__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(142); +/* harmony import */ var ncp__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(143); /* harmony import */ var ncp__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(ncp__WEBPACK_IMPORTED_MODULE_2__); /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(4); /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_3__); -/* harmony import */ var util__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(111); +/* harmony import */ var util__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(112); /* harmony import */ var util__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(util__WEBPACK_IMPORTED_MODULE_4__); /* * Licensed to Elasticsearch B.V. under one or more contributor @@ -9030,6 +9175,7 @@ __webpack_require__.r(__webpack_exports__); const lstat = Object(util__WEBPACK_IMPORTED_MODULE_4__["promisify"])(fs__WEBPACK_IMPORTED_MODULE_1___default.a.lstat); const readFile = Object(util__WEBPACK_IMPORTED_MODULE_4__["promisify"])(fs__WEBPACK_IMPORTED_MODULE_1___default.a.readFile); +const writeFile = Object(util__WEBPACK_IMPORTED_MODULE_4__["promisify"])(fs__WEBPACK_IMPORTED_MODULE_1___default.a.writeFile); const symlink = Object(util__WEBPACK_IMPORTED_MODULE_4__["promisify"])(fs__WEBPACK_IMPORTED_MODULE_1___default.a.symlink); const chmod = Object(util__WEBPACK_IMPORTED_MODULE_4__["promisify"])(fs__WEBPACK_IMPORTED_MODULE_1___default.a.chmod); const cmdShim = Object(util__WEBPACK_IMPORTED_MODULE_4__["promisify"])(cmd_shim__WEBPACK_IMPORTED_MODULE_0___default.a); @@ -9115,7 +9261,7 @@ async function forceCreate(src, dest, type) { } /***/ }), -/* 131 */ +/* 132 */ /***/ (function(module, exports, __webpack_require__) { // On windows, create a .cmd file. @@ -9131,11 +9277,11 @@ async function forceCreate(src, dest, type) { module.exports = cmdShim cmdShim.ifExists = cmdShimIfExists -var fs = __webpack_require__(132) +var fs = __webpack_require__(133) -var mkdir = __webpack_require__(140) +var mkdir = __webpack_require__(141) , path = __webpack_require__(4) - , toBatchSyntax = __webpack_require__(141) + , toBatchSyntax = __webpack_require__(142) , shebangExpr = /^#\!\s*(?:\/usr\/bin\/env)?\s*([^ \t]+=[^ \t]+\s+)*\s*([^ \t]+)(.*)$/ function cmdShimIfExists (from, to, cb) { @@ -9368,15 +9514,15 @@ function times(n, ok, cb) { /***/ }), -/* 132 */ +/* 133 */ /***/ (function(module, exports, __webpack_require__) { -var fs = __webpack_require__(133) -var polyfills = __webpack_require__(134) -var legacy = __webpack_require__(136) -var clone = __webpack_require__(138) +var fs = __webpack_require__(134) +var polyfills = __webpack_require__(135) +var legacy = __webpack_require__(137) +var clone = __webpack_require__(139) -var util = __webpack_require__(111) +var util = __webpack_require__(112) /* istanbul ignore next - node 0.x polyfill */ var gracefulQueue @@ -9457,7 +9603,7 @@ if (!fs[gracefulQueue]) { if (/\bgfs4\b/i.test(process.env.NODE_DEBUG || '')) { process.on('exit', function() { debug(fs[gracefulQueue]) - __webpack_require__(139).equal(fs[gracefulQueue].length, 0) + __webpack_require__(140).equal(fs[gracefulQueue].length, 0) }) } } @@ -9728,16 +9874,16 @@ function retry () { /***/ }), -/* 133 */ +/* 134 */ /***/ (function(module, exports) { module.exports = require("fs"); /***/ }), -/* 134 */ +/* 135 */ /***/ (function(module, exports, __webpack_require__) { -var constants = __webpack_require__(135) +var constants = __webpack_require__(136) var origCwd = process.cwd var cwd = null @@ -10082,16 +10228,16 @@ function patch (fs) { /***/ }), -/* 135 */ +/* 136 */ /***/ (function(module, exports) { module.exports = require("constants"); /***/ }), -/* 136 */ +/* 137 */ /***/ (function(module, exports, __webpack_require__) { -var Stream = __webpack_require__(137).Stream +var Stream = __webpack_require__(138).Stream module.exports = legacy @@ -10212,13 +10358,13 @@ function legacy (fs) { /***/ }), -/* 137 */ +/* 138 */ /***/ (function(module, exports) { module.exports = require("stream"); /***/ }), -/* 138 */ +/* 139 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -10244,17 +10390,17 @@ function clone (obj) { /***/ }), -/* 139 */ +/* 140 */ /***/ (function(module, exports) { module.exports = require("assert"); /***/ }), -/* 140 */ +/* 141 */ /***/ (function(module, exports, __webpack_require__) { var path = __webpack_require__(4); -var fs = __webpack_require__(133); +var fs = __webpack_require__(134); var _0777 = parseInt('0777', 8); module.exports = mkdirP.mkdirp = mkdirP.mkdirP = mkdirP; @@ -10355,7 +10501,7 @@ mkdirP.sync = function sync (p, opts, made) { /***/ }), -/* 141 */ +/* 142 */ /***/ (function(module, exports) { exports.replaceDollarWithPercentPair = replaceDollarWithPercentPair @@ -10413,10 +10559,10 @@ function replaceDollarWithPercentPair(value) { /***/ }), -/* 142 */ +/* 143 */ /***/ (function(module, exports, __webpack_require__) { -var fs = __webpack_require__(133), +var fs = __webpack_require__(134), path = __webpack_require__(4); module.exports = ncp; @@ -10680,7 +10826,7 @@ function ncp (source, dest, options, callback) { /***/ }), -/* 143 */ +/* 144 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -10740,7 +10886,7 @@ const log = new Log(); /***/ }), -/* 144 */ +/* 145 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -10806,7 +10952,7 @@ async function parallelize(items, fn, concurrency = 4) { } /***/ }), -/* 145 */ +/* 146 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -10815,15 +10961,15 @@ __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "buildProjectGraph", function() { return buildProjectGraph; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "topologicallyBatchProjects", function() { return topologicallyBatchProjects; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "includeTransitiveProjects", function() { return includeTransitiveProjects; }); -/* harmony import */ var glob__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(146); +/* harmony import */ var glob__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(147); /* harmony import */ var glob__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(glob__WEBPACK_IMPORTED_MODULE_0__); /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(4); /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_1__); -/* harmony import */ var util__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(111); +/* harmony import */ var util__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(112); /* harmony import */ var util__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(util__WEBPACK_IMPORTED_MODULE_2__); -/* harmony import */ var _errors__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(162); -/* harmony import */ var _project__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(163); -/* harmony import */ var _workspaces__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(279); +/* harmony import */ var _errors__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(163); +/* harmony import */ var _project__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(164); +/* harmony import */ var _workspaces__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(271); /* * Licensed to Elasticsearch B.V. under one or more contributor * license agreements. See the NOTICE file distributed with @@ -11022,7 +11168,7 @@ function includeTransitiveProjects(subsetOfProjects, allProjects, { } /***/ }), -/* 146 */ +/* 147 */ /***/ (function(module, exports, __webpack_require__) { // Approach: @@ -11067,27 +11213,27 @@ function includeTransitiveProjects(subsetOfProjects, allProjects, { module.exports = glob -var fs = __webpack_require__(133) -var rp = __webpack_require__(147) -var minimatch = __webpack_require__(149) +var fs = __webpack_require__(134) +var rp = __webpack_require__(148) +var minimatch = __webpack_require__(150) var Minimatch = minimatch.Minimatch -var inherits = __webpack_require__(153) -var EE = __webpack_require__(155).EventEmitter +var inherits = __webpack_require__(154) +var EE = __webpack_require__(156).EventEmitter var path = __webpack_require__(4) -var assert = __webpack_require__(139) -var isAbsolute = __webpack_require__(156) -var globSync = __webpack_require__(157) -var common = __webpack_require__(158) +var assert = __webpack_require__(140) +var isAbsolute = __webpack_require__(157) +var globSync = __webpack_require__(158) +var common = __webpack_require__(159) var alphasort = common.alphasort var alphasorti = common.alphasorti var setopts = common.setopts var ownProp = common.ownProp -var inflight = __webpack_require__(159) -var util = __webpack_require__(111) +var inflight = __webpack_require__(160) +var util = __webpack_require__(112) var childrenIgnored = common.childrenIgnored var isIgnored = common.isIgnored -var once = __webpack_require__(161) +var once = __webpack_require__(162) function glob (pattern, options, cb) { if (typeof options === 'function') cb = options, options = {} @@ -11818,7 +11964,7 @@ Glob.prototype._stat2 = function (f, abs, er, stat, cb) { /***/ }), -/* 147 */ +/* 148 */ /***/ (function(module, exports, __webpack_require__) { module.exports = realpath @@ -11828,13 +11974,13 @@ realpath.realpathSync = realpathSync realpath.monkeypatch = monkeypatch realpath.unmonkeypatch = unmonkeypatch -var fs = __webpack_require__(133) +var fs = __webpack_require__(134) var origRealpath = fs.realpath var origRealpathSync = fs.realpathSync var version = process.version var ok = /^v[0-5]\./.test(version) -var old = __webpack_require__(148) +var old = __webpack_require__(149) function newError (er) { return er && er.syscall === 'realpath' && ( @@ -11890,7 +12036,7 @@ function unmonkeypatch () { /***/ }), -/* 148 */ +/* 149 */ /***/ (function(module, exports, __webpack_require__) { // Copyright Joyent, Inc. and other Node contributors. @@ -11916,7 +12062,7 @@ function unmonkeypatch () { var pathModule = __webpack_require__(4); var isWindows = process.platform === 'win32'; -var fs = __webpack_require__(133); +var fs = __webpack_require__(134); // JavaScript implementation of realpath, ported from node pre-v6 @@ -12199,7 +12345,7 @@ exports.realpath = function realpath(p, cache, cb) { /***/ }), -/* 149 */ +/* 150 */ /***/ (function(module, exports, __webpack_require__) { module.exports = minimatch @@ -12211,7 +12357,7 @@ try { } catch (er) {} var GLOBSTAR = minimatch.GLOBSTAR = Minimatch.GLOBSTAR = {} -var expand = __webpack_require__(150) +var expand = __webpack_require__(151) var plTypes = { '!': { open: '(?:(?!(?:', close: '))[^/]*?)'}, @@ -13128,11 +13274,11 @@ function regExpEscape (s) { /***/ }), -/* 150 */ +/* 151 */ /***/ (function(module, exports, __webpack_require__) { -var concatMap = __webpack_require__(151); -var balanced = __webpack_require__(152); +var concatMap = __webpack_require__(152); +var balanced = __webpack_require__(153); module.exports = expandTop; @@ -13335,7 +13481,7 @@ function expand(str, isTop) { /***/ }), -/* 151 */ +/* 152 */ /***/ (function(module, exports) { module.exports = function (xs, fn) { @@ -13354,7 +13500,7 @@ var isArray = Array.isArray || function (xs) { /***/ }), -/* 152 */ +/* 153 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -13420,22 +13566,22 @@ function range(a, b, str) { /***/ }), -/* 153 */ +/* 154 */ /***/ (function(module, exports, __webpack_require__) { try { - var util = __webpack_require__(111); + var util = __webpack_require__(112); /* istanbul ignore next */ if (typeof util.inherits !== 'function') throw ''; module.exports = util.inherits; } catch (e) { /* istanbul ignore next */ - module.exports = __webpack_require__(154); + module.exports = __webpack_require__(155); } /***/ }), -/* 154 */ +/* 155 */ /***/ (function(module, exports) { if (typeof Object.create === 'function') { @@ -13468,13 +13614,13 @@ if (typeof Object.create === 'function') { /***/ }), -/* 155 */ +/* 156 */ /***/ (function(module, exports) { module.exports = require("events"); /***/ }), -/* 156 */ +/* 157 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -13501,22 +13647,22 @@ module.exports.win32 = win32; /***/ }), -/* 157 */ +/* 158 */ /***/ (function(module, exports, __webpack_require__) { module.exports = globSync globSync.GlobSync = GlobSync -var fs = __webpack_require__(133) -var rp = __webpack_require__(147) -var minimatch = __webpack_require__(149) +var fs = __webpack_require__(134) +var rp = __webpack_require__(148) +var minimatch = __webpack_require__(150) var Minimatch = minimatch.Minimatch -var Glob = __webpack_require__(146).Glob -var util = __webpack_require__(111) +var Glob = __webpack_require__(147).Glob +var util = __webpack_require__(112) var path = __webpack_require__(4) -var assert = __webpack_require__(139) -var isAbsolute = __webpack_require__(156) -var common = __webpack_require__(158) +var assert = __webpack_require__(140) +var isAbsolute = __webpack_require__(157) +var common = __webpack_require__(159) var alphasort = common.alphasort var alphasorti = common.alphasorti var setopts = common.setopts @@ -13993,7 +14139,7 @@ GlobSync.prototype._makeAbs = function (f) { /***/ }), -/* 158 */ +/* 159 */ /***/ (function(module, exports, __webpack_require__) { exports.alphasort = alphasort @@ -14011,8 +14157,8 @@ function ownProp (obj, field) { } var path = __webpack_require__(4) -var minimatch = __webpack_require__(149) -var isAbsolute = __webpack_require__(156) +var minimatch = __webpack_require__(150) +var isAbsolute = __webpack_require__(157) var Minimatch = minimatch.Minimatch function alphasorti (a, b) { @@ -14239,12 +14385,12 @@ function childrenIgnored (self, path) { /***/ }), -/* 159 */ +/* 160 */ /***/ (function(module, exports, __webpack_require__) { -var wrappy = __webpack_require__(160) +var wrappy = __webpack_require__(161) var reqs = Object.create(null) -var once = __webpack_require__(161) +var once = __webpack_require__(162) module.exports = wrappy(inflight) @@ -14299,7 +14445,7 @@ function slice (args) { /***/ }), -/* 160 */ +/* 161 */ /***/ (function(module, exports) { // Returns a wrapper function that returns a wrapped callback @@ -14338,10 +14484,10 @@ function wrappy (fn, cb) { /***/ }), -/* 161 */ +/* 162 */ /***/ (function(module, exports, __webpack_require__) { -var wrappy = __webpack_require__(160) +var wrappy = __webpack_require__(161) module.exports = wrappy(once) module.exports.strict = wrappy(onceStrict) @@ -14386,7 +14532,7 @@ function onceStrict (fn) { /***/ }), -/* 162 */ +/* 163 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -14419,22 +14565,22 @@ class CliError extends Error { } /***/ }), -/* 163 */ +/* 164 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Project", function() { return Project; }); -/* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(133); +/* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(134); /* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(fs__WEBPACK_IMPORTED_MODULE_0__); /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(4); /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_1__); -/* harmony import */ var util__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(111); +/* harmony import */ var util__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(112); /* harmony import */ var util__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(util__WEBPACK_IMPORTED_MODULE_2__); -/* harmony import */ var _errors__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(162); -/* harmony import */ var _log__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(143); -/* harmony import */ var _package_json__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(164); -/* harmony import */ var _scripts__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(225); +/* harmony import */ var _errors__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(163); +/* harmony import */ var _log__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(144); +/* harmony import */ var _package_json__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(165); +/* harmony import */ var _scripts__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(226); function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; } function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } @@ -14671,7 +14817,7 @@ function normalizePath(path) { } /***/ }), -/* 164 */ +/* 165 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -14679,9 +14825,9 @@ __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "readPackageJson", function() { return readPackageJson; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "writePackageJson", function() { return writePackageJson; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "isLinkDependency", function() { return isLinkDependency; }); -/* harmony import */ var read_pkg__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(165); +/* harmony import */ var read_pkg__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(166); /* harmony import */ var read_pkg__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(read_pkg__WEBPACK_IMPORTED_MODULE_0__); -/* harmony import */ var write_pkg__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(213); +/* harmony import */ var write_pkg__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(214); /* harmony import */ var write_pkg__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(write_pkg__WEBPACK_IMPORTED_MODULE_1__); /* * Licensed to Elasticsearch B.V. under one or more contributor @@ -14715,15 +14861,15 @@ function writePackageJson(path, json) { const isLinkDependency = depVersion => depVersion.startsWith('link:'); /***/ }), -/* 165 */ +/* 166 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const {promisify} = __webpack_require__(111); -const fs = __webpack_require__(133); +const {promisify} = __webpack_require__(112); +const fs = __webpack_require__(134); const path = __webpack_require__(4); -const parseJson = __webpack_require__(166); +const parseJson = __webpack_require__(167); const readFileAsync = promisify(fs.readFile); @@ -14738,7 +14884,7 @@ module.exports = async options => { const json = parseJson(await readFileAsync(filePath, 'utf8')); if (options.normalize) { - __webpack_require__(187)(json); + __webpack_require__(188)(json); } return json; @@ -14755,7 +14901,7 @@ module.exports.sync = options => { const json = parseJson(fs.readFileSync(filePath, 'utf8')); if (options.normalize) { - __webpack_require__(187)(json); + __webpack_require__(188)(json); } return json; @@ -14763,15 +14909,15 @@ module.exports.sync = options => { /***/ }), -/* 166 */ +/* 167 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const errorEx = __webpack_require__(167); -const fallback = __webpack_require__(169); -const {default: LinesAndColumns} = __webpack_require__(170); -const {codeFrameColumns} = __webpack_require__(171); +const errorEx = __webpack_require__(168); +const fallback = __webpack_require__(170); +const {default: LinesAndColumns} = __webpack_require__(171); +const {codeFrameColumns} = __webpack_require__(172); const JSONError = errorEx('JSONError', { fileName: errorEx.append('in %s'), @@ -14820,14 +14966,14 @@ module.exports = (string, reviver, filename) => { /***/ }), -/* 167 */ +/* 168 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var util = __webpack_require__(111); -var isArrayish = __webpack_require__(168); +var util = __webpack_require__(112); +var isArrayish = __webpack_require__(169); var errorEx = function errorEx(name, properties) { if (!name || name.constructor !== String) { @@ -14960,7 +15106,7 @@ module.exports = errorEx; /***/ }), -/* 168 */ +/* 169 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -14977,7 +15123,7 @@ module.exports = function isArrayish(obj) { /***/ }), -/* 169 */ +/* 170 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -14989,6 +15135,12 @@ function parseJson (txt, reviver, context) { try { return JSON.parse(txt, reviver) } catch (e) { + if (typeof txt !== 'string') { + const isEmptyArray = Array.isArray(txt) && txt.length === 0 + const errorMessage = 'Cannot parse ' + + (isEmptyArray ? 'an empty array' : String(txt)) + throw new TypeError(errorMessage) + } const syntaxErr = e.message.match(/^Unexpected token.*position\s+(\d+)/i) const errIdx = syntaxErr ? +syntaxErr[1] @@ -15016,7 +15168,7 @@ function parseJson (txt, reviver, context) { /***/ }), -/* 170 */ +/* 171 */ /***/ (function(__webpack_module__, __webpack_exports__, __webpack_require__) { "use strict"; @@ -15080,7 +15232,7 @@ var LinesAndColumns = (function () { /***/ }), -/* 171 */ +/* 172 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -15092,7 +15244,7 @@ Object.defineProperty(exports, "__esModule", { exports.codeFrameColumns = codeFrameColumns; exports.default = _default; -var _highlight = _interopRequireWildcard(__webpack_require__(172)); +var _highlight = _interopRequireWildcard(__webpack_require__(173)); function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; } @@ -15253,7 +15405,7 @@ function _default(rawLines, lineNumber, colNumber, opts = {}) { } /***/ }), -/* 172 */ +/* 173 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -15266,11 +15418,11 @@ exports.shouldHighlight = shouldHighlight; exports.getChalk = getChalk; exports.default = highlight; -var _jsTokens = _interopRequireWildcard(__webpack_require__(173)); +var _jsTokens = _interopRequireWildcard(__webpack_require__(174)); -var _helperValidatorIdentifier = __webpack_require__(174); +var _helperValidatorIdentifier = __webpack_require__(175); -var _chalk = _interopRequireDefault(__webpack_require__(177)); +var _chalk = _interopRequireDefault(__webpack_require__(178)); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } @@ -15366,7 +15518,7 @@ function highlight(code, options = {}) { } /***/ }), -/* 173 */ +/* 174 */ /***/ (function(module, exports) { // Copyright 2014, 2015, 2016, 2017, 2018 Simon Lydell @@ -15395,7 +15547,7 @@ exports.matchToToken = function(match) { /***/ }), -/* 174 */ +/* 175 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -15453,12 +15605,12 @@ Object.defineProperty(exports, "isKeyword", { } }); -var _identifier = __webpack_require__(175); +var _identifier = __webpack_require__(176); -var _keyword = __webpack_require__(176); +var _keyword = __webpack_require__(177); /***/ }), -/* 175 */ +/* 176 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -15541,7 +15693,7 @@ function isIdentifierName(name) { } /***/ }), -/* 176 */ +/* 177 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -15585,16 +15737,16 @@ function isKeyword(word) { } /***/ }), -/* 177 */ +/* 178 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const escapeStringRegexp = __webpack_require__(178); -const ansiStyles = __webpack_require__(179); -const stdoutColor = __webpack_require__(184).stdout; +const escapeStringRegexp = __webpack_require__(179); +const ansiStyles = __webpack_require__(180); +const stdoutColor = __webpack_require__(185).stdout; -const template = __webpack_require__(186); +const template = __webpack_require__(187); const isSimpleWindowsTerm = process.platform === 'win32' && !(process.env.TERM || '').toLowerCase().startsWith('xterm'); @@ -15820,7 +15972,7 @@ module.exports.default = module.exports; // For TypeScript /***/ }), -/* 178 */ +/* 179 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -15838,12 +15990,12 @@ module.exports = function (str) { /***/ }), -/* 179 */ +/* 180 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; /* WEBPACK VAR INJECTION */(function(module) { -const colorConvert = __webpack_require__(180); +const colorConvert = __webpack_require__(181); const wrapAnsi16 = (fn, offset) => function () { const code = fn.apply(colorConvert, arguments); @@ -16008,14 +16160,14 @@ Object.defineProperty(module, 'exports', { get: assembleStyles }); -/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(114)(module))) +/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(115)(module))) /***/ }), -/* 180 */ +/* 181 */ /***/ (function(module, exports, __webpack_require__) { -var conversions = __webpack_require__(181); -var route = __webpack_require__(183); +var conversions = __webpack_require__(182); +var route = __webpack_require__(184); var convert = {}; @@ -16095,11 +16247,11 @@ module.exports = convert; /***/ }), -/* 181 */ +/* 182 */ /***/ (function(module, exports, __webpack_require__) { /* MIT license */ -var cssKeywords = __webpack_require__(182); +var cssKeywords = __webpack_require__(183); // NOTE: conversions should only return primitive values (i.e. arrays, or // values that give correct `typeof` results). @@ -16969,7 +17121,7 @@ convert.rgb.gray = function (rgb) { /***/ }), -/* 182 */ +/* 183 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -17128,10 +17280,10 @@ module.exports = { /***/ }), -/* 183 */ +/* 184 */ /***/ (function(module, exports, __webpack_require__) { -var conversions = __webpack_require__(181); +var conversions = __webpack_require__(182); /* this function routes a model to all other models. @@ -17231,13 +17383,13 @@ module.exports = function (fromModel) { /***/ }), -/* 184 */ +/* 185 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const os = __webpack_require__(120); -const hasFlag = __webpack_require__(185); +const os = __webpack_require__(121); +const hasFlag = __webpack_require__(186); const env = process.env; @@ -17369,7 +17521,7 @@ module.exports = { /***/ }), -/* 185 */ +/* 186 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -17384,7 +17536,7 @@ module.exports = (flag, argv) => { /***/ }), -/* 186 */ +/* 187 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -17519,15 +17671,15 @@ module.exports = (chalk, tmp) => { /***/ }), -/* 187 */ +/* 188 */ /***/ (function(module, exports, __webpack_require__) { module.exports = normalize -var fixer = __webpack_require__(188) +var fixer = __webpack_require__(189) normalize.fixer = fixer -var makeWarning = __webpack_require__(211) +var makeWarning = __webpack_require__(212) var fieldsToFix = ['name','version','description','repository','modules','scripts' ,'files','bin','man','bugs','keywords','readme','homepage','license'] @@ -17564,17 +17716,17 @@ function ucFirst (string) { /***/ }), -/* 188 */ +/* 189 */ /***/ (function(module, exports, __webpack_require__) { -var semver = __webpack_require__(189) -var validateLicense = __webpack_require__(190); -var hostedGitInfo = __webpack_require__(195) -var isBuiltinModule = __webpack_require__(199).isCore +var semver = __webpack_require__(190) +var validateLicense = __webpack_require__(191); +var hostedGitInfo = __webpack_require__(196) +var isBuiltinModule = __webpack_require__(200).isCore var depTypes = ["dependencies","devDependencies","optionalDependencies"] -var extractDescription = __webpack_require__(209) -var url = __webpack_require__(196) -var typos = __webpack_require__(210) +var extractDescription = __webpack_require__(210) +var url = __webpack_require__(197) +var typos = __webpack_require__(211) var fixer = module.exports = { // default warning function @@ -17988,7 +18140,7 @@ function bugsTypos(bugs, warn) { /***/ }), -/* 189 */ +/* 190 */ /***/ (function(module, exports) { exports = module.exports = SemVer @@ -19477,11 +19629,11 @@ function coerce (version) { /***/ }), -/* 190 */ +/* 191 */ /***/ (function(module, exports, __webpack_require__) { -var parse = __webpack_require__(191); -var correct = __webpack_require__(193); +var parse = __webpack_require__(192); +var correct = __webpack_require__(194); var genericWarning = ( 'license should be ' + @@ -19567,10 +19719,10 @@ module.exports = function(argument) { /***/ }), -/* 191 */ +/* 192 */ /***/ (function(module, exports, __webpack_require__) { -var parser = __webpack_require__(192).parser +var parser = __webpack_require__(193).parser module.exports = function (argument) { return parser.parse(argument) @@ -19578,7 +19730,7 @@ module.exports = function (argument) { /***/ }), -/* 192 */ +/* 193 */ /***/ (function(module, exports, __webpack_require__) { /* WEBPACK VAR INJECTION */(function(module) {/* parser generated by jison 0.4.17 */ @@ -20931,7 +21083,7 @@ exports.main = function commonjsMain(args) { console.log('Usage: '+args[0]+' FILE'); process.exit(1); } - var source = __webpack_require__(133).readFileSync(__webpack_require__(4).normalize(args[1]), "utf8"); + var source = __webpack_require__(134).readFileSync(__webpack_require__(4).normalize(args[1]), "utf8"); return exports.parser.parse(source); }; if ( true && __webpack_require__.c[__webpack_require__.s] === module) { @@ -20939,13 +21091,13 @@ if ( true && __webpack_require__.c[__webpack_require__.s] === module) { } } -/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(114)(module))) +/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(115)(module))) /***/ }), -/* 193 */ +/* 194 */ /***/ (function(module, exports, __webpack_require__) { -var licenseIDs = __webpack_require__(194); +var licenseIDs = __webpack_require__(195); function valid(string) { return licenseIDs.indexOf(string) > -1; @@ -21185,20 +21337,20 @@ module.exports = function(identifier) { /***/ }), -/* 194 */ +/* 195 */ /***/ (function(module) { module.exports = JSON.parse("[\"Glide\",\"Abstyles\",\"AFL-1.1\",\"AFL-1.2\",\"AFL-2.0\",\"AFL-2.1\",\"AFL-3.0\",\"AMPAS\",\"APL-1.0\",\"Adobe-Glyph\",\"APAFML\",\"Adobe-2006\",\"AGPL-1.0\",\"Afmparse\",\"Aladdin\",\"ADSL\",\"AMDPLPA\",\"ANTLR-PD\",\"Apache-1.0\",\"Apache-1.1\",\"Apache-2.0\",\"AML\",\"APSL-1.0\",\"APSL-1.1\",\"APSL-1.2\",\"APSL-2.0\",\"Artistic-1.0\",\"Artistic-1.0-Perl\",\"Artistic-1.0-cl8\",\"Artistic-2.0\",\"AAL\",\"Bahyph\",\"Barr\",\"Beerware\",\"BitTorrent-1.0\",\"BitTorrent-1.1\",\"BSL-1.0\",\"Borceux\",\"BSD-2-Clause\",\"BSD-2-Clause-FreeBSD\",\"BSD-2-Clause-NetBSD\",\"BSD-3-Clause\",\"BSD-3-Clause-Clear\",\"BSD-4-Clause\",\"BSD-Protection\",\"BSD-Source-Code\",\"BSD-3-Clause-Attribution\",\"0BSD\",\"BSD-4-Clause-UC\",\"bzip2-1.0.5\",\"bzip2-1.0.6\",\"Caldera\",\"CECILL-1.0\",\"CECILL-1.1\",\"CECILL-2.0\",\"CECILL-2.1\",\"CECILL-B\",\"CECILL-C\",\"ClArtistic\",\"MIT-CMU\",\"CNRI-Jython\",\"CNRI-Python\",\"CNRI-Python-GPL-Compatible\",\"CPOL-1.02\",\"CDDL-1.0\",\"CDDL-1.1\",\"CPAL-1.0\",\"CPL-1.0\",\"CATOSL-1.1\",\"Condor-1.1\",\"CC-BY-1.0\",\"CC-BY-2.0\",\"CC-BY-2.5\",\"CC-BY-3.0\",\"CC-BY-4.0\",\"CC-BY-ND-1.0\",\"CC-BY-ND-2.0\",\"CC-BY-ND-2.5\",\"CC-BY-ND-3.0\",\"CC-BY-ND-4.0\",\"CC-BY-NC-1.0\",\"CC-BY-NC-2.0\",\"CC-BY-NC-2.5\",\"CC-BY-NC-3.0\",\"CC-BY-NC-4.0\",\"CC-BY-NC-ND-1.0\",\"CC-BY-NC-ND-2.0\",\"CC-BY-NC-ND-2.5\",\"CC-BY-NC-ND-3.0\",\"CC-BY-NC-ND-4.0\",\"CC-BY-NC-SA-1.0\",\"CC-BY-NC-SA-2.0\",\"CC-BY-NC-SA-2.5\",\"CC-BY-NC-SA-3.0\",\"CC-BY-NC-SA-4.0\",\"CC-BY-SA-1.0\",\"CC-BY-SA-2.0\",\"CC-BY-SA-2.5\",\"CC-BY-SA-3.0\",\"CC-BY-SA-4.0\",\"CC0-1.0\",\"Crossword\",\"CrystalStacker\",\"CUA-OPL-1.0\",\"Cube\",\"curl\",\"D-FSL-1.0\",\"diffmark\",\"WTFPL\",\"DOC\",\"Dotseqn\",\"DSDP\",\"dvipdfm\",\"EPL-1.0\",\"ECL-1.0\",\"ECL-2.0\",\"eGenix\",\"EFL-1.0\",\"EFL-2.0\",\"MIT-advertising\",\"MIT-enna\",\"Entessa\",\"ErlPL-1.1\",\"EUDatagrid\",\"EUPL-1.0\",\"EUPL-1.1\",\"Eurosym\",\"Fair\",\"MIT-feh\",\"Frameworx-1.0\",\"FreeImage\",\"FTL\",\"FSFAP\",\"FSFUL\",\"FSFULLR\",\"Giftware\",\"GL2PS\",\"Glulxe\",\"AGPL-3.0\",\"GFDL-1.1\",\"GFDL-1.2\",\"GFDL-1.3\",\"GPL-1.0\",\"GPL-2.0\",\"GPL-3.0\",\"LGPL-2.1\",\"LGPL-3.0\",\"LGPL-2.0\",\"gnuplot\",\"gSOAP-1.3b\",\"HaskellReport\",\"HPND\",\"IBM-pibs\",\"IPL-1.0\",\"ICU\",\"ImageMagick\",\"iMatix\",\"Imlib2\",\"IJG\",\"Info-ZIP\",\"Intel-ACPI\",\"Intel\",\"Interbase-1.0\",\"IPA\",\"ISC\",\"JasPer-2.0\",\"JSON\",\"LPPL-1.0\",\"LPPL-1.1\",\"LPPL-1.2\",\"LPPL-1.3a\",\"LPPL-1.3c\",\"Latex2e\",\"BSD-3-Clause-LBNL\",\"Leptonica\",\"LGPLLR\",\"Libpng\",\"libtiff\",\"LAL-1.2\",\"LAL-1.3\",\"LiLiQ-P-1.1\",\"LiLiQ-Rplus-1.1\",\"LiLiQ-R-1.1\",\"LPL-1.02\",\"LPL-1.0\",\"MakeIndex\",\"MTLL\",\"MS-PL\",\"MS-RL\",\"MirOS\",\"MITNFA\",\"MIT\",\"Motosoto\",\"MPL-1.0\",\"MPL-1.1\",\"MPL-2.0\",\"MPL-2.0-no-copyleft-exception\",\"mpich2\",\"Multics\",\"Mup\",\"NASA-1.3\",\"Naumen\",\"NBPL-1.0\",\"NetCDF\",\"NGPL\",\"NOSL\",\"NPL-1.0\",\"NPL-1.1\",\"Newsletr\",\"NLPL\",\"Nokia\",\"NPOSL-3.0\",\"NLOD-1.0\",\"Noweb\",\"NRL\",\"NTP\",\"Nunit\",\"OCLC-2.0\",\"ODbL-1.0\",\"PDDL-1.0\",\"OCCT-PL\",\"OGTSL\",\"OLDAP-2.2.2\",\"OLDAP-1.1\",\"OLDAP-1.2\",\"OLDAP-1.3\",\"OLDAP-1.4\",\"OLDAP-2.0\",\"OLDAP-2.0.1\",\"OLDAP-2.1\",\"OLDAP-2.2\",\"OLDAP-2.2.1\",\"OLDAP-2.3\",\"OLDAP-2.4\",\"OLDAP-2.5\",\"OLDAP-2.6\",\"OLDAP-2.7\",\"OLDAP-2.8\",\"OML\",\"OPL-1.0\",\"OSL-1.0\",\"OSL-1.1\",\"OSL-2.0\",\"OSL-2.1\",\"OSL-3.0\",\"OpenSSL\",\"OSET-PL-2.1\",\"PHP-3.0\",\"PHP-3.01\",\"Plexus\",\"PostgreSQL\",\"psfrag\",\"psutils\",\"Python-2.0\",\"QPL-1.0\",\"Qhull\",\"Rdisc\",\"RPSL-1.0\",\"RPL-1.1\",\"RPL-1.5\",\"RHeCos-1.1\",\"RSCPL\",\"RSA-MD\",\"Ruby\",\"SAX-PD\",\"Saxpath\",\"SCEA\",\"SWL\",\"SMPPL\",\"Sendmail\",\"SGI-B-1.0\",\"SGI-B-1.1\",\"SGI-B-2.0\",\"OFL-1.0\",\"OFL-1.1\",\"SimPL-2.0\",\"Sleepycat\",\"SNIA\",\"Spencer-86\",\"Spencer-94\",\"Spencer-99\",\"SMLNJ\",\"SugarCRM-1.1.3\",\"SISSL\",\"SISSL-1.2\",\"SPL-1.0\",\"Watcom-1.0\",\"TCL\",\"Unlicense\",\"TMate\",\"TORQUE-1.1\",\"TOSL\",\"Unicode-TOU\",\"UPL-1.0\",\"NCSA\",\"Vim\",\"VOSTROM\",\"VSL-1.0\",\"W3C-19980720\",\"W3C\",\"Wsuipa\",\"Xnet\",\"X11\",\"Xerox\",\"XFree86-1.1\",\"xinetd\",\"xpp\",\"XSkat\",\"YPL-1.0\",\"YPL-1.1\",\"Zed\",\"Zend-2.0\",\"Zimbra-1.3\",\"Zimbra-1.4\",\"Zlib\",\"zlib-acknowledgement\",\"ZPL-1.1\",\"ZPL-2.0\",\"ZPL-2.1\",\"BSD-3-Clause-No-Nuclear-License\",\"BSD-3-Clause-No-Nuclear-Warranty\",\"BSD-3-Clause-No-Nuclear-License-2014\",\"eCos-2.0\",\"GPL-2.0-with-autoconf-exception\",\"GPL-2.0-with-bison-exception\",\"GPL-2.0-with-classpath-exception\",\"GPL-2.0-with-font-exception\",\"GPL-2.0-with-GCC-exception\",\"GPL-3.0-with-autoconf-exception\",\"GPL-3.0-with-GCC-exception\",\"StandardML-NJ\",\"WXwindows\"]"); /***/ }), -/* 195 */ +/* 196 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var url = __webpack_require__(196) -var gitHosts = __webpack_require__(197) -var GitHost = module.exports = __webpack_require__(198) +var url = __webpack_require__(197) +var gitHosts = __webpack_require__(198) +var GitHost = module.exports = __webpack_require__(199) var protocolToRepresentationMap = { 'git+ssh': 'sshurl', @@ -21319,13 +21471,13 @@ function parseGitUrl (giturl) { /***/ }), -/* 196 */ +/* 197 */ /***/ (function(module, exports) { module.exports = require("url"); /***/ }), -/* 197 */ +/* 198 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -21400,13 +21552,13 @@ Object.keys(gitHosts).forEach(function (name) { /***/ }), -/* 198 */ +/* 199 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var gitHosts = __webpack_require__(197) -var extend = Object.assign || __webpack_require__(111)._extend +var gitHosts = __webpack_require__(198) +var extend = Object.assign || __webpack_require__(112)._extend var GitHost = module.exports = function (type, user, auth, project, committish, defaultRepresentation, opts) { var gitHostInfo = this @@ -21521,27 +21673,27 @@ GitHost.prototype.toString = function (opts) { /***/ }), -/* 199 */ +/* 200 */ /***/ (function(module, exports, __webpack_require__) { -var async = __webpack_require__(200); -async.core = __webpack_require__(206); -async.isCore = __webpack_require__(205); -async.sync = __webpack_require__(208); +var async = __webpack_require__(201); +async.core = __webpack_require__(207); +async.isCore = __webpack_require__(206); +async.sync = __webpack_require__(209); module.exports = async; /***/ }), -/* 200 */ +/* 201 */ /***/ (function(module, exports, __webpack_require__) { -var fs = __webpack_require__(133); +var fs = __webpack_require__(134); var path = __webpack_require__(4); -var caller = __webpack_require__(201); -var nodeModulesPaths = __webpack_require__(202); -var normalizeOptions = __webpack_require__(204); -var isCore = __webpack_require__(205); +var caller = __webpack_require__(202); +var nodeModulesPaths = __webpack_require__(203); +var normalizeOptions = __webpack_require__(205); +var isCore = __webpack_require__(206); var realpathFS = fs.realpath && typeof fs.realpath.native === 'function' ? fs.realpath.native : fs.realpath; @@ -21837,7 +21989,7 @@ module.exports = function resolve(x, options, callback) { /***/ }), -/* 201 */ +/* 202 */ /***/ (function(module, exports) { module.exports = function () { @@ -21851,11 +22003,11 @@ module.exports = function () { /***/ }), -/* 202 */ +/* 203 */ /***/ (function(module, exports, __webpack_require__) { var path = __webpack_require__(4); -var parse = path.parse || __webpack_require__(203); +var parse = path.parse || __webpack_require__(204); var getNodeModulesDirs = function getNodeModulesDirs(absoluteStart, modules) { var prefix = '/'; @@ -21899,7 +22051,7 @@ module.exports = function nodeModulesPaths(start, opts, request) { /***/ }), -/* 203 */ +/* 204 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -21999,7 +22151,7 @@ module.exports.win32 = win32.parse; /***/ }), -/* 204 */ +/* 205 */ /***/ (function(module, exports) { module.exports = function (x, opts) { @@ -22015,10 +22167,10 @@ module.exports = function (x, opts) { /***/ }), -/* 205 */ +/* 206 */ /***/ (function(module, exports, __webpack_require__) { -var core = __webpack_require__(206); +var core = __webpack_require__(207); module.exports = function isCore(x) { return Object.prototype.hasOwnProperty.call(core, x); @@ -22026,7 +22178,7 @@ module.exports = function isCore(x) { /***/ }), -/* 206 */ +/* 207 */ /***/ (function(module, exports, __webpack_require__) { var current = (process.versions && process.versions.node && process.versions.node.split('.')) || []; @@ -22073,7 +22225,7 @@ function versionIncluded(specifierValue) { return matchesRange(specifierValue); } -var data = __webpack_require__(207); +var data = __webpack_require__(208); var core = {}; for (var mod in data) { // eslint-disable-line no-restricted-syntax @@ -22085,21 +22237,21 @@ module.exports = core; /***/ }), -/* 207 */ +/* 208 */ /***/ (function(module) { module.exports = JSON.parse("{\"assert\":true,\"async_hooks\":\">= 8\",\"buffer_ieee754\":\"< 0.9.7\",\"buffer\":true,\"child_process\":true,\"cluster\":true,\"console\":true,\"constants\":true,\"crypto\":true,\"_debug_agent\":\">= 1 && < 8\",\"_debugger\":\"< 8\",\"dgram\":true,\"dns\":true,\"domain\":true,\"events\":true,\"freelist\":\"< 6\",\"fs\":true,\"fs/promises\":[\">= 10 && < 10.1\",\">= 14\"],\"_http_agent\":\">= 0.11.1\",\"_http_client\":\">= 0.11.1\",\"_http_common\":\">= 0.11.1\",\"_http_incoming\":\">= 0.11.1\",\"_http_outgoing\":\">= 0.11.1\",\"_http_server\":\">= 0.11.1\",\"http\":true,\"http2\":\">= 8.8\",\"https\":true,\"inspector\":\">= 8.0.0\",\"_linklist\":\"< 8\",\"module\":true,\"net\":true,\"node-inspect/lib/_inspect\":\">= 7.6.0 && < 12\",\"node-inspect/lib/internal/inspect_client\":\">= 7.6.0 && < 12\",\"node-inspect/lib/internal/inspect_repl\":\">= 7.6.0 && < 12\",\"os\":true,\"path\":true,\"perf_hooks\":\">= 8.5\",\"process\":\">= 1\",\"punycode\":true,\"querystring\":true,\"readline\":true,\"repl\":true,\"smalloc\":\">= 0.11.5 && < 3\",\"_stream_duplex\":\">= 0.9.4\",\"_stream_transform\":\">= 0.9.4\",\"_stream_wrap\":\">= 1.4.1\",\"_stream_passthrough\":\">= 0.9.4\",\"_stream_readable\":\">= 0.9.4\",\"_stream_writable\":\">= 0.9.4\",\"stream\":true,\"string_decoder\":true,\"sys\":true,\"timers\":true,\"_tls_common\":\">= 0.11.13\",\"_tls_legacy\":\">= 0.11.3 && < 10\",\"_tls_wrap\":\">= 0.11.3\",\"tls\":true,\"trace_events\":\">= 10\",\"tty\":true,\"url\":true,\"util\":true,\"v8/tools/arguments\":\">= 10 && < 12\",\"v8/tools/codemap\":[\">= 4.4.0 && < 5\",\">= 5.2.0 && < 12\"],\"v8/tools/consarray\":[\">= 4.4.0 && < 5\",\">= 5.2.0 && < 12\"],\"v8/tools/csvparser\":[\">= 4.4.0 && < 5\",\">= 5.2.0 && < 12\"],\"v8/tools/logreader\":[\">= 4.4.0 && < 5\",\">= 5.2.0 && < 12\"],\"v8/tools/profile_view\":[\">= 4.4.0 && < 5\",\">= 5.2.0 && < 12\"],\"v8/tools/splaytree\":[\">= 4.4.0 && < 5\",\">= 5.2.0 && < 12\"],\"v8\":\">= 1\",\"vm\":true,\"wasi\":\">= 13.4 && < 13.5\",\"worker_threads\":\">= 11.7\",\"zlib\":true}"); /***/ }), -/* 208 */ +/* 209 */ /***/ (function(module, exports, __webpack_require__) { -var isCore = __webpack_require__(205); -var fs = __webpack_require__(133); +var isCore = __webpack_require__(206); +var fs = __webpack_require__(134); var path = __webpack_require__(4); -var caller = __webpack_require__(201); -var nodeModulesPaths = __webpack_require__(202); -var normalizeOptions = __webpack_require__(204); +var caller = __webpack_require__(202); +var nodeModulesPaths = __webpack_require__(203); +var normalizeOptions = __webpack_require__(205); var realpathFS = fs.realpathSync && typeof fs.realpathSync.native === 'function' ? fs.realpathSync.native : fs.realpathSync; @@ -22288,7 +22440,7 @@ module.exports = function resolveSync(x, options) { /***/ }), -/* 209 */ +/* 210 */ /***/ (function(module, exports) { module.exports = extractDescription @@ -22308,17 +22460,17 @@ function extractDescription (d) { /***/ }), -/* 210 */ +/* 211 */ /***/ (function(module) { module.exports = JSON.parse("{\"topLevel\":{\"dependancies\":\"dependencies\",\"dependecies\":\"dependencies\",\"depdenencies\":\"dependencies\",\"devEependencies\":\"devDependencies\",\"depends\":\"dependencies\",\"dev-dependencies\":\"devDependencies\",\"devDependences\":\"devDependencies\",\"devDepenencies\":\"devDependencies\",\"devdependencies\":\"devDependencies\",\"repostitory\":\"repository\",\"repo\":\"repository\",\"prefereGlobal\":\"preferGlobal\",\"hompage\":\"homepage\",\"hampage\":\"homepage\",\"autohr\":\"author\",\"autor\":\"author\",\"contributers\":\"contributors\",\"publicationConfig\":\"publishConfig\",\"script\":\"scripts\"},\"bugs\":{\"web\":\"url\",\"name\":\"url\"},\"script\":{\"server\":\"start\",\"tests\":\"test\"}}"); /***/ }), -/* 211 */ +/* 212 */ /***/ (function(module, exports, __webpack_require__) { -var util = __webpack_require__(111) -var messages = __webpack_require__(212) +var util = __webpack_require__(112) +var messages = __webpack_require__(213) module.exports = function() { var args = Array.prototype.slice.call(arguments, 0) @@ -22343,20 +22495,20 @@ function makeTypoWarning (providedName, probableName, field) { /***/ }), -/* 212 */ +/* 213 */ /***/ (function(module) { module.exports = JSON.parse("{\"repositories\":\"'repositories' (plural) Not supported. Please pick one as the 'repository' field\",\"missingRepository\":\"No repository field.\",\"brokenGitUrl\":\"Probably broken git url: %s\",\"nonObjectScripts\":\"scripts must be an object\",\"nonStringScript\":\"script values must be string commands\",\"nonArrayFiles\":\"Invalid 'files' member\",\"invalidFilename\":\"Invalid filename in 'files' list: %s\",\"nonArrayBundleDependencies\":\"Invalid 'bundleDependencies' list. Must be array of package names\",\"nonStringBundleDependency\":\"Invalid bundleDependencies member: %s\",\"nonDependencyBundleDependency\":\"Non-dependency in bundleDependencies: %s\",\"nonObjectDependencies\":\"%s field must be an object\",\"nonStringDependency\":\"Invalid dependency: %s %s\",\"deprecatedArrayDependencies\":\"specifying %s as array is deprecated\",\"deprecatedModules\":\"modules field is deprecated\",\"nonArrayKeywords\":\"keywords should be an array of strings\",\"nonStringKeyword\":\"keywords should be an array of strings\",\"conflictingName\":\"%s is also the name of a node core module.\",\"nonStringDescription\":\"'description' field should be a string\",\"missingDescription\":\"No description\",\"missingReadme\":\"No README data\",\"missingLicense\":\"No license field.\",\"nonEmailUrlBugsString\":\"Bug string field must be url, email, or {email,url}\",\"nonUrlBugsUrlField\":\"bugs.url field must be a string url. Deleted.\",\"nonEmailBugsEmailField\":\"bugs.email field must be a string email. Deleted.\",\"emptyNormalizedBugs\":\"Normalized value of bugs field is an empty object. Deleted.\",\"nonUrlHomepage\":\"homepage field must be a string url. Deleted.\",\"invalidLicense\":\"license should be a valid SPDX license expression\",\"typo\":\"%s should probably be %s.\"}"); /***/ }), -/* 213 */ +/* 214 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const path = __webpack_require__(4); -const writeJsonFile = __webpack_require__(214); -const sortKeys = __webpack_require__(220); +const writeJsonFile = __webpack_require__(215); +const sortKeys = __webpack_require__(221); const dependencyKeys = new Set([ 'dependencies', @@ -22421,18 +22573,18 @@ module.exports.sync = (filePath, data, options) => { /***/ }), -/* 214 */ +/* 215 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const path = __webpack_require__(4); -const fs = __webpack_require__(132); -const writeFileAtomic = __webpack_require__(215); -const sortKeys = __webpack_require__(220); -const makeDir = __webpack_require__(222); -const pify = __webpack_require__(223); -const detectIndent = __webpack_require__(224); +const fs = __webpack_require__(133); +const writeFileAtomic = __webpack_require__(216); +const sortKeys = __webpack_require__(221); +const makeDir = __webpack_require__(223); +const pify = __webpack_require__(224); +const detectIndent = __webpack_require__(225); const init = (fn, filePath, data, options) => { if (!filePath) { @@ -22504,7 +22656,7 @@ module.exports.sync = (filePath, data, options) => { /***/ }), -/* 215 */ +/* 216 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -22514,9 +22666,9 @@ module.exports.sync = writeFileSync module.exports._getTmpname = getTmpname // for testing module.exports._cleanupOnExit = cleanupOnExit -var fs = __webpack_require__(132) -var MurmurHash3 = __webpack_require__(216) -var onExit = __webpack_require__(217) +var fs = __webpack_require__(133) +var MurmurHash3 = __webpack_require__(217) +var onExit = __webpack_require__(218) var path = __webpack_require__(4) var activeFiles = {} @@ -22524,7 +22676,7 @@ var activeFiles = {} /* istanbul ignore next */ var threadId = (function getId () { try { - var workerThreads = __webpack_require__(219) + var workerThreads = __webpack_require__(220) /// if we are in main thread, this is set to `0` return workerThreads.threadId @@ -22749,7 +22901,7 @@ function writeFileSync (filename, data, options) { /***/ }), -/* 216 */ +/* 217 */ /***/ (function(module, exports, __webpack_require__) { /** @@ -22891,16 +23043,16 @@ function writeFileSync (filename, data, options) { /***/ }), -/* 217 */ +/* 218 */ /***/ (function(module, exports, __webpack_require__) { // Note: since nyc uses this module to output coverage, any lines // that are in the direct sync flow of nyc's outputCoverage are // ignored, since we can never get coverage for them. -var assert = __webpack_require__(139) -var signals = __webpack_require__(218) +var assert = __webpack_require__(140) +var signals = __webpack_require__(219) -var EE = __webpack_require__(155) +var EE = __webpack_require__(156) /* istanbul ignore if */ if (typeof EE !== 'function') { EE = EE.EventEmitter @@ -23054,7 +23206,7 @@ function processEmit (ev, arg) { /***/ }), -/* 218 */ +/* 219 */ /***/ (function(module, exports) { // This is not the set of all possible signals. @@ -23113,18 +23265,18 @@ if (process.platform === 'linux') { /***/ }), -/* 219 */ +/* 220 */ /***/ (function(module, exports) { module.exports = require(undefined); /***/ }), -/* 220 */ +/* 221 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const isPlainObj = __webpack_require__(221); +const isPlainObj = __webpack_require__(222); module.exports = (obj, opts) => { if (!isPlainObj(obj)) { @@ -23181,7 +23333,7 @@ module.exports = (obj, opts) => { /***/ }), -/* 221 */ +/* 222 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -23195,15 +23347,15 @@ module.exports = function (x) { /***/ }), -/* 222 */ +/* 223 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const fs = __webpack_require__(133); +const fs = __webpack_require__(134); const path = __webpack_require__(4); -const pify = __webpack_require__(223); -const semver = __webpack_require__(189); +const pify = __webpack_require__(224); +const semver = __webpack_require__(190); const defaults = { mode: 0o777 & (~process.umask()), @@ -23341,7 +23493,7 @@ module.exports.sync = (input, options) => { /***/ }), -/* 223 */ +/* 224 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -23416,7 +23568,7 @@ module.exports = (input, options) => { /***/ }), -/* 224 */ +/* 225 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -23545,7 +23697,7 @@ module.exports = str => { /***/ }), -/* 225 */ +/* 226 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -23554,7 +23706,7 @@ __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "runScriptInPackage", function() { return runScriptInPackage; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "runScriptInPackageStreaming", function() { return runScriptInPackageStreaming; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "yarnWorkspacesInfo", function() { return yarnWorkspacesInfo; }); -/* harmony import */ var _child_process__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(226); +/* harmony import */ var _child_process__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(227); /* * Licensed to Elasticsearch B.V. under one or more contributor * license agreements. See the NOTICE file distributed with @@ -23631,22 +23783,22 @@ async function yarnWorkspacesInfo(directory) { } /***/ }), -/* 226 */ +/* 227 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "spawn", function() { return spawn; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "spawnStreaming", function() { return spawnStreaming; }); -/* harmony import */ var stream__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(137); +/* harmony import */ var stream__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(138); /* harmony import */ var stream__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(stream__WEBPACK_IMPORTED_MODULE_0__); -/* harmony import */ var chalk__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(227); +/* harmony import */ var chalk__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(113); /* harmony import */ var chalk__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(chalk__WEBPACK_IMPORTED_MODULE_1__); -/* harmony import */ var execa__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(236); +/* harmony import */ var execa__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(228); /* harmony import */ var execa__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(execa__WEBPACK_IMPORTED_MODULE_2__); -/* harmony import */ var strong_log_transformer__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(271); +/* harmony import */ var strong_log_transformer__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(263); /* harmony import */ var strong_log_transformer__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(strong_log_transformer__WEBPACK_IMPORTED_MODULE_3__); -/* harmony import */ var _log__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(143); +/* harmony import */ var _log__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(144); function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; } function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } @@ -23730,5578 +23882,5756 @@ function spawnStreaming(command, args, opts, { } /***/ }), -/* 227 */ +/* 228 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const ansiStyles = __webpack_require__(228); -const {stdout: stdoutColor, stderr: stderrColor} = __webpack_require__(232); -const { - stringReplaceAll, - stringEncaseCRLFWithFirstIndex -} = __webpack_require__(234); - -const {isArray} = Array; +const path = __webpack_require__(4); +const childProcess = __webpack_require__(229); +const crossSpawn = __webpack_require__(230); +const stripFinalNewline = __webpack_require__(243); +const npmRunPath = __webpack_require__(244); +const onetime = __webpack_require__(245); +const makeError = __webpack_require__(247); +const normalizeStdio = __webpack_require__(252); +const {spawnedKill, spawnedCancel, setupTimeout, setExitHandler} = __webpack_require__(253); +const {handleInput, getSpawnedResult, makeAllStream, validateInputSync} = __webpack_require__(254); +const {mergePromise, getSpawnedPromise} = __webpack_require__(261); +const {joinCommand, parseCommand} = __webpack_require__(262); -// `supportsColor.level` → `ansiStyles.color[name]` mapping -const levelMapping = [ - 'ansi', - 'ansi', - 'ansi256', - 'ansi16m' -]; +const DEFAULT_MAX_BUFFER = 1000 * 1000 * 100; -const styles = Object.create(null); +const getEnv = ({env: envOption, extendEnv, preferLocal, localDir, execPath}) => { + const env = extendEnv ? {...process.env, ...envOption} : envOption; -const applyOptions = (object, options = {}) => { - if (options.level && !(Number.isInteger(options.level) && options.level >= 0 && options.level <= 3)) { - throw new Error('The `level` option should be an integer from 0 to 3'); + if (preferLocal) { + return npmRunPath.env({env, cwd: localDir, execPath}); } - // Detect level if not set manually - const colorLevel = stdoutColor ? stdoutColor.level : 0; - object.level = options.level === undefined ? colorLevel : options.level; + return env; }; -class ChalkClass { - constructor(options) { - // eslint-disable-next-line no-constructor-return - return chalkFactory(options); - } -} - -const chalkFactory = options => { - const chalk = {}; - applyOptions(chalk, options); +const handleArguments = (file, args, options = {}) => { + const parsed = crossSpawn._parse(file, args, options); + file = parsed.command; + args = parsed.args; + options = parsed.options; - chalk.template = (...arguments_) => chalkTag(chalk.template, ...arguments_); + options = { + maxBuffer: DEFAULT_MAX_BUFFER, + buffer: true, + stripFinalNewline: true, + extendEnv: true, + preferLocal: false, + localDir: options.cwd || process.cwd(), + execPath: process.execPath, + encoding: 'utf8', + reject: true, + cleanup: true, + all: false, + windowsHide: true, + ...options + }; - Object.setPrototypeOf(chalk, Chalk.prototype); - Object.setPrototypeOf(chalk.template, chalk); + options.env = getEnv(options); - chalk.template.constructor = () => { - throw new Error('`chalk.constructor()` is deprecated. Use `new chalk.Instance()` instead.'); - }; + options.stdio = normalizeStdio(options); - chalk.template.Instance = ChalkClass; + if (process.platform === 'win32' && path.basename(file, '.exe') === 'cmd') { + // #116 + args.unshift('/q'); + } - return chalk.template; + return {file, args, options, parsed}; }; -function Chalk(options) { - return chalkFactory(options); -} - -for (const [styleName, style] of Object.entries(ansiStyles)) { - styles[styleName] = { - get() { - const builder = createBuilder(this, createStyler(style.open, style.close, this._styler), this._isEmpty); - Object.defineProperty(this, styleName, {value: builder}); - return builder; - } - }; -} +const handleOutput = (options, value, error) => { + if (typeof value !== 'string' && !Buffer.isBuffer(value)) { + // When `execa.sync()` errors, we normalize it to '' to mimic `execa()` + return error === undefined ? undefined : ''; + } -styles.visible = { - get() { - const builder = createBuilder(this, this._styler, true); - Object.defineProperty(this, 'visible', {value: builder}); - return builder; + if (options.stripFinalNewline) { + return stripFinalNewline(value); } + + return value; }; -const usedModels = ['rgb', 'hex', 'keyword', 'hsl', 'hsv', 'hwb', 'ansi', 'ansi256']; +const execa = (file, args, options) => { + const parsed = handleArguments(file, args, options); + const command = joinCommand(file, args); -for (const model of usedModels) { - styles[model] = { - get() { - const {level} = this; - return function (...arguments_) { - const styler = createStyler(ansiStyles.color[levelMapping[level]][model](...arguments_), ansiStyles.color.close, this._styler); - return createBuilder(this, styler, this._isEmpty); - }; - } - }; -} + let spawned; + try { + spawned = childProcess.spawn(parsed.file, parsed.args, parsed.options); + } catch (error) { + // Ensure the returned error is always both a promise and a child process + const dummySpawned = new childProcess.ChildProcess(); + const errorPromise = Promise.reject(makeError({ + error, + stdout: '', + stderr: '', + all: '', + command, + parsed, + timedOut: false, + isCanceled: false, + killed: false + })); + return mergePromise(dummySpawned, errorPromise); + } -for (const model of usedModels) { - const bgModel = 'bg' + model[0].toUpperCase() + model.slice(1); - styles[bgModel] = { - get() { - const {level} = this; - return function (...arguments_) { - const styler = createStyler(ansiStyles.bgColor[levelMapping[level]][model](...arguments_), ansiStyles.bgColor.close, this._styler); - return createBuilder(this, styler, this._isEmpty); - }; - } - }; -} + const spawnedPromise = getSpawnedPromise(spawned); + const timedPromise = setupTimeout(spawned, parsed.options, spawnedPromise); + const processDone = setExitHandler(spawned, parsed.options, timedPromise); -const proto = Object.defineProperties(() => {}, { - ...styles, - level: { - enumerable: true, - get() { - return this._generator.level; - }, - set(level) { - this._generator.level = level; - } - } -}); + const context = {isCanceled: false}; -const createStyler = (open, close, parent) => { - let openAll; - let closeAll; - if (parent === undefined) { - openAll = open; - closeAll = close; - } else { - openAll = parent.openAll + open; - closeAll = close + parent.closeAll; - } + spawned.kill = spawnedKill.bind(null, spawned.kill.bind(spawned)); + spawned.cancel = spawnedCancel.bind(null, spawned, context); - return { - open, - close, - openAll, - closeAll, - parent - }; -}; + const handlePromise = async () => { + const [{error, exitCode, signal, timedOut}, stdoutResult, stderrResult, allResult] = await getSpawnedResult(spawned, parsed.options, processDone); + const stdout = handleOutput(parsed.options, stdoutResult); + const stderr = handleOutput(parsed.options, stderrResult); + const all = handleOutput(parsed.options, allResult); -const createBuilder = (self, _styler, _isEmpty) => { - const builder = (...arguments_) => { - if (isArray(arguments_[0]) && isArray(arguments_[0].raw)) { - // Called as a template literal, for example: chalk.red`2 + 3 = {bold ${2+3}}` - return applyStyle(builder, chalkTag(builder, ...arguments_)); + if (error || exitCode !== 0 || signal !== null) { + const returnedError = makeError({ + error, + exitCode, + signal, + stdout, + stderr, + all, + command, + parsed, + timedOut, + isCanceled: context.isCanceled, + killed: spawned.killed + }); + + if (!parsed.options.reject) { + return returnedError; + } + + throw returnedError; } - // Single argument is hot path, implicit coercion is faster than anything - // eslint-disable-next-line no-implicit-coercion - return applyStyle(builder, (arguments_.length === 1) ? ('' + arguments_[0]) : arguments_.join(' ')); + return { + command, + exitCode: 0, + stdout, + stderr, + all, + failed: false, + timedOut: false, + isCanceled: false, + killed: false + }; }; - // We alter the prototype because we must return a function, but there is - // no way to create a function with a different prototype - Object.setPrototypeOf(builder, proto); + const handlePromiseOnce = onetime(handlePromise); - builder._generator = self; - builder._styler = _styler; - builder._isEmpty = _isEmpty; + crossSpawn._enoent.hookChildProcess(spawned, parsed.parsed); - return builder; + handleInput(spawned, parsed.options.input); + + spawned.all = makeAllStream(spawned, parsed.options); + + return mergePromise(spawned, handlePromiseOnce); }; -const applyStyle = (self, string) => { - if (self.level <= 0 || !string) { - return self._isEmpty ? '' : string; - } +module.exports = execa; - let styler = self._styler; +module.exports.sync = (file, args, options) => { + const parsed = handleArguments(file, args, options); + const command = joinCommand(file, args); - if (styler === undefined) { - return string; + validateInputSync(parsed.options); + + let result; + try { + result = childProcess.spawnSync(parsed.file, parsed.args, parsed.options); + } catch (error) { + throw makeError({ + error, + stdout: '', + stderr: '', + all: '', + command, + parsed, + timedOut: false, + isCanceled: false, + killed: false + }); } - const {openAll, closeAll} = styler; - if (string.indexOf('\u001B') !== -1) { - while (styler !== undefined) { - // Replace any instances already present with a re-opening code - // otherwise only the part of the string until said closing code - // will be colored, and the rest will simply be 'plain'. - string = stringReplaceAll(string, styler.close, styler.open); + const stdout = handleOutput(parsed.options, result.stdout, result.error); + const stderr = handleOutput(parsed.options, result.stderr, result.error); - styler = styler.parent; + if (result.error || result.status !== 0 || result.signal !== null) { + const error = makeError({ + stdout, + stderr, + error: result.error, + signal: result.signal, + exitCode: result.status, + command, + parsed, + timedOut: result.error && result.error.code === 'ETIMEDOUT', + isCanceled: false, + killed: result.signal !== null + }); + + if (!parsed.options.reject) { + return error; } - } - // We can move both next actions out of loop, because remaining actions in loop won't have - // any/visible effect on parts we add here. Close the styling before a linebreak and reopen - // after next line to fix a bleed issue on macOS: https://github.com/chalk/chalk/pull/92 - const lfIndex = string.indexOf('\n'); - if (lfIndex !== -1) { - string = stringEncaseCRLFWithFirstIndex(string, closeAll, openAll, lfIndex); + throw error; } - return openAll + string + closeAll; + return { + command, + exitCode: 0, + stdout, + stderr, + failed: false, + timedOut: false, + isCanceled: false, + killed: false + }; }; -let template; -const chalkTag = (chalk, ...strings) => { - const [firstString] = strings; - - if (!isArray(firstString) || !isArray(firstString.raw)) { - // If chalk() was called by itself or with a string, - // return the string itself as a string. - return strings.join(' '); - } +module.exports.command = (command, options) => { + const [file, ...args] = parseCommand(command); + return execa(file, args, options); +}; - const arguments_ = strings.slice(1); - const parts = [firstString.raw[0]]; +module.exports.commandSync = (command, options) => { + const [file, ...args] = parseCommand(command); + return execa.sync(file, args, options); +}; - for (let i = 1; i < firstString.length; i++) { - parts.push( - String(arguments_[i - 1]).replace(/[{}\\]/g, '\\$&'), - String(firstString.raw[i]) - ); +module.exports.node = (scriptPath, args, options = {}) => { + if (args && !Array.isArray(args) && typeof args === 'object') { + options = args; + args = []; } - if (template === undefined) { - template = __webpack_require__(235); - } + const stdio = normalizeStdio.node(options); - return template(chalk, parts.join('')); -}; + const {nodePath = process.execPath, nodeOptions = process.execArgv} = options; -Object.defineProperties(Chalk.prototype, styles); + return execa( + nodePath, + [ + ...nodeOptions, + scriptPath, + ...(Array.isArray(args) ? args : []) + ], + { + ...options, + stdin: undefined, + stdout: undefined, + stderr: undefined, + stdio, + shell: false + } + ); +}; -const chalk = Chalk(); // eslint-disable-line new-cap -chalk.supportsColor = stdoutColor; -chalk.stderr = Chalk({level: stderrColor ? stderrColor.level : 0}); // eslint-disable-line new-cap -chalk.stderr.supportsColor = stderrColor; -module.exports = chalk; +/***/ }), +/* 229 */ +/***/ (function(module, exports) { +module.exports = require("child_process"); /***/ }), -/* 228 */ +/* 230 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -/* WEBPACK VAR INJECTION */(function(module) { -const wrapAnsi16 = (fn, offset) => (...args) => { - const code = fn(...args); - return `\u001B[${code + offset}m`; -}; -const wrapAnsi256 = (fn, offset) => (...args) => { - const code = fn(...args); - return `\u001B[${38 + offset};5;${code}m`; -}; +const cp = __webpack_require__(229); +const parse = __webpack_require__(231); +const enoent = __webpack_require__(242); -const wrapAnsi16m = (fn, offset) => (...args) => { - const rgb = fn(...args); - return `\u001B[${38 + offset};2;${rgb[0]};${rgb[1]};${rgb[2]}m`; -}; +function spawn(command, args, options) { + // Parse the arguments + const parsed = parse(command, args, options); -const ansi2ansi = n => n; -const rgb2rgb = (r, g, b) => [r, g, b]; + // Spawn the child process + const spawned = cp.spawn(parsed.command, parsed.args, parsed.options); -const setLazyProperty = (object, property, get) => { - Object.defineProperty(object, property, { - get: () => { - const value = get(); + // Hook into child process "exit" event to emit an error if the command + // does not exists, see: https://github.com/IndigoUnited/node-cross-spawn/issues/16 + enoent.hookChildProcess(spawned, parsed); - Object.defineProperty(object, property, { - value, - enumerable: true, - configurable: true - }); + return spawned; +} - return value; - }, - enumerable: true, - configurable: true - }); -}; +function spawnSync(command, args, options) { + // Parse the arguments + const parsed = parse(command, args, options); -/** @type {typeof import('color-convert')} */ -let colorConvert; -const makeDynamicStyles = (wrap, targetSpace, identity, isBackground) => { - if (colorConvert === undefined) { - colorConvert = __webpack_require__(229); - } + // Spawn the child process + const result = cp.spawnSync(parsed.command, parsed.args, parsed.options); - const offset = isBackground ? 10 : 0; - const styles = {}; + // Analyze if the command does not exist, see: https://github.com/IndigoUnited/node-cross-spawn/issues/16 + result.error = result.error || enoent.verifyENOENTSync(result.status, parsed); - for (const [sourceSpace, suite] of Object.entries(colorConvert)) { - const name = sourceSpace === 'ansi16' ? 'ansi' : sourceSpace; - if (sourceSpace === targetSpace) { - styles[name] = wrap(identity, offset); - } else if (typeof suite === 'object') { - styles[name] = wrap(suite[targetSpace], offset); - } - } + return result; +} - return styles; -}; +module.exports = spawn; +module.exports.spawn = spawn; +module.exports.sync = spawnSync; -function assembleStyles() { - const codes = new Map(); - const styles = { - modifier: { - reset: [0, 0], - // 21 isn't widely supported and 22 does the same thing - bold: [1, 22], - dim: [2, 22], - italic: [3, 23], - underline: [4, 24], - inverse: [7, 27], - hidden: [8, 28], - strikethrough: [9, 29] - }, - color: { - black: [30, 39], - red: [31, 39], - green: [32, 39], - yellow: [33, 39], - blue: [34, 39], - magenta: [35, 39], - cyan: [36, 39], - white: [37, 39], +module.exports._parse = parse; +module.exports._enoent = enoent; - // Bright color - blackBright: [90, 39], - redBright: [91, 39], - greenBright: [92, 39], - yellowBright: [93, 39], - blueBright: [94, 39], - magentaBright: [95, 39], - cyanBright: [96, 39], - whiteBright: [97, 39] - }, - bgColor: { - bgBlack: [40, 49], - bgRed: [41, 49], - bgGreen: [42, 49], - bgYellow: [43, 49], - bgBlue: [44, 49], - bgMagenta: [45, 49], - bgCyan: [46, 49], - bgWhite: [47, 49], - // Bright color - bgBlackBright: [100, 49], - bgRedBright: [101, 49], - bgGreenBright: [102, 49], - bgYellowBright: [103, 49], - bgBlueBright: [104, 49], - bgMagentaBright: [105, 49], - bgCyanBright: [106, 49], - bgWhiteBright: [107, 49] - } - }; +/***/ }), +/* 231 */ +/***/ (function(module, exports, __webpack_require__) { - // Alias bright black as gray (and grey) - styles.color.gray = styles.color.blackBright; - styles.bgColor.bgGray = styles.bgColor.bgBlackBright; - styles.color.grey = styles.color.blackBright; - styles.bgColor.bgGrey = styles.bgColor.bgBlackBright; +"use strict"; - for (const [groupName, group] of Object.entries(styles)) { - for (const [styleName, style] of Object.entries(group)) { - styles[styleName] = { - open: `\u001B[${style[0]}m`, - close: `\u001B[${style[1]}m` - }; - group[styleName] = styles[styleName]; +const path = __webpack_require__(4); +const resolveCommand = __webpack_require__(232); +const escape = __webpack_require__(238); +const readShebang = __webpack_require__(239); - codes.set(style[0], style[1]); - } +const isWin = process.platform === 'win32'; +const isExecutableRegExp = /\.(?:com|exe)$/i; +const isCmdShimRegExp = /node_modules[\\/].bin[\\/][^\\/]+\.cmd$/i; - Object.defineProperty(styles, groupName, { - value: group, - enumerable: false - }); - } +function detectShebang(parsed) { + parsed.file = resolveCommand(parsed); - Object.defineProperty(styles, 'codes', { - value: codes, - enumerable: false - }); + const shebang = parsed.file && readShebang(parsed.file); - styles.color.close = '\u001B[39m'; - styles.bgColor.close = '\u001B[49m'; + if (shebang) { + parsed.args.unshift(parsed.file); + parsed.command = shebang; - setLazyProperty(styles.color, 'ansi', () => makeDynamicStyles(wrapAnsi16, 'ansi16', ansi2ansi, false)); - setLazyProperty(styles.color, 'ansi256', () => makeDynamicStyles(wrapAnsi256, 'ansi256', ansi2ansi, false)); - setLazyProperty(styles.color, 'ansi16m', () => makeDynamicStyles(wrapAnsi16m, 'rgb', rgb2rgb, false)); - setLazyProperty(styles.bgColor, 'ansi', () => makeDynamicStyles(wrapAnsi16, 'ansi16', ansi2ansi, true)); - setLazyProperty(styles.bgColor, 'ansi256', () => makeDynamicStyles(wrapAnsi256, 'ansi256', ansi2ansi, true)); - setLazyProperty(styles.bgColor, 'ansi16m', () => makeDynamicStyles(wrapAnsi16m, 'rgb', rgb2rgb, true)); + return resolveCommand(parsed); + } - return styles; + return parsed.file; } -// Make the export immutable -Object.defineProperty(module, 'exports', { - enumerable: true, - get: assembleStyles -}); +function parseNonShell(parsed) { + if (!isWin) { + return parsed; + } -/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(114)(module))) + // Detect & add support for shebangs + const commandFile = detectShebang(parsed); -/***/ }), -/* 229 */ -/***/ (function(module, exports, __webpack_require__) { + // We don't need a shell if the command filename is an executable + const needsShell = !isExecutableRegExp.test(commandFile); -const conversions = __webpack_require__(230); -const route = __webpack_require__(231); + // If a shell is required, use cmd.exe and take care of escaping everything correctly + // Note that `forceShell` is an hidden option used only in tests + if (parsed.options.forceShell || needsShell) { + // Need to double escape meta chars if the command is a cmd-shim located in `node_modules/.bin/` + // The cmd-shim simply calls execute the package bin file with NodeJS, proxying any argument + // Because the escape of metachars with ^ gets interpreted when the cmd.exe is first called, + // we need to double escape them + const needsDoubleEscapeMetaChars = isCmdShimRegExp.test(commandFile); -const convert = {}; + // Normalize posix paths into OS compatible paths (e.g.: foo/bar -> foo\bar) + // This is necessary otherwise it will always fail with ENOENT in those cases + parsed.command = path.normalize(parsed.command); -const models = Object.keys(conversions); + // Escape command & arguments + parsed.command = escape.command(parsed.command); + parsed.args = parsed.args.map((arg) => escape.argument(arg, needsDoubleEscapeMetaChars)); -function wrapRaw(fn) { - const wrappedFn = function (...args) { - const arg0 = args[0]; - if (arg0 === undefined || arg0 === null) { - return arg0; - } + const shellCommand = [parsed.command].concat(parsed.args).join(' '); - if (arg0.length > 1) { - args = arg0; - } + parsed.args = ['/d', '/s', '/c', `"${shellCommand}"`]; + parsed.command = process.env.comspec || 'cmd.exe'; + parsed.options.windowsVerbatimArguments = true; // Tell node's spawn that the arguments are already escaped + } - return fn(args); - }; + return parsed; +} - // Preserve .conversion property if there is one - if ('conversion' in fn) { - wrappedFn.conversion = fn.conversion; - } +function parse(command, args, options) { + // Normalize arguments, similar to nodejs + if (args && !Array.isArray(args)) { + options = args; + args = null; + } - return wrappedFn; + args = args ? args.slice(0) : []; // Clone array to avoid changing the original + options = Object.assign({}, options); // Clone object to avoid changing the original + + // Build our parsed object + const parsed = { + command, + args, + options, + file: undefined, + original: { + command, + args, + }, + }; + + // Delegate further parsing to shell or non-shell + return options.shell ? parsed : parseNonShell(parsed); } -function wrapRounded(fn) { - const wrappedFn = function (...args) { - const arg0 = args[0]; +module.exports = parse; - if (arg0 === undefined || arg0 === null) { - return arg0; - } - if (arg0.length > 1) { - args = arg0; - } +/***/ }), +/* 232 */ +/***/ (function(module, exports, __webpack_require__) { - const result = fn(args); +"use strict"; - // We're assuming the result is an array here. - // see notice in conversions.js; don't use box types - // in conversion functions. - if (typeof result === 'object') { - for (let len = result.length, i = 0; i < len; i++) { - result[i] = Math.round(result[i]); - } - } - return result; - }; +const path = __webpack_require__(4); +const which = __webpack_require__(233); +const pathKey = __webpack_require__(237)(); - // Preserve .conversion property if there is one - if ('conversion' in fn) { - wrappedFn.conversion = fn.conversion; - } +function resolveCommandAttempt(parsed, withoutPathExt) { + const cwd = process.cwd(); + const hasCustomCwd = parsed.options.cwd != null; + // Worker threads do not have process.chdir() + const shouldSwitchCwd = hasCustomCwd && process.chdir !== undefined; - return wrappedFn; -} + // If a custom `cwd` was specified, we need to change the process cwd + // because `which` will do stat calls but does not support a custom cwd + if (shouldSwitchCwd) { + try { + process.chdir(parsed.options.cwd); + } catch (err) { + /* Empty */ + } + } -models.forEach(fromModel => { - convert[fromModel] = {}; + let resolved; - Object.defineProperty(convert[fromModel], 'channels', {value: conversions[fromModel].channels}); - Object.defineProperty(convert[fromModel], 'labels', {value: conversions[fromModel].labels}); + try { + resolved = which.sync(parsed.command, { + path: (parsed.options.env || process.env)[pathKey], + pathExt: withoutPathExt ? path.delimiter : undefined, + }); + } catch (e) { + /* Empty */ + } finally { + if (shouldSwitchCwd) { + process.chdir(cwd); + } + } - const routes = route(fromModel); - const routeModels = Object.keys(routes); + // If we successfully resolved, ensure that an absolute path is returned + // Note that when a custom `cwd` was used, we need to resolve to an absolute path based on it + if (resolved) { + resolved = path.resolve(hasCustomCwd ? parsed.options.cwd : '', resolved); + } - routeModels.forEach(toModel => { - const fn = routes[toModel]; + return resolved; +} - convert[fromModel][toModel] = wrapRounded(fn); - convert[fromModel][toModel].raw = wrapRaw(fn); - }); -}); +function resolveCommand(parsed) { + return resolveCommandAttempt(parsed) || resolveCommandAttempt(parsed, true); +} -module.exports = convert; +module.exports = resolveCommand; /***/ }), -/* 230 */ +/* 233 */ /***/ (function(module, exports, __webpack_require__) { -/* MIT license */ -/* eslint-disable no-mixed-operators */ -const cssKeywords = __webpack_require__(117); - -// NOTE: conversions should only return primitive values (i.e. arrays, or -// values that give correct `typeof` results). -// do not use box values types (i.e. Number(), String(), etc.) - -const reverseKeywords = {}; -for (const key of Object.keys(cssKeywords)) { - reverseKeywords[cssKeywords[key]] = key; -} +const isWindows = process.platform === 'win32' || + process.env.OSTYPE === 'cygwin' || + process.env.OSTYPE === 'msys' -const convert = { - rgb: {channels: 3, labels: 'rgb'}, - hsl: {channels: 3, labels: 'hsl'}, - hsv: {channels: 3, labels: 'hsv'}, - hwb: {channels: 3, labels: 'hwb'}, - cmyk: {channels: 4, labels: 'cmyk'}, - xyz: {channels: 3, labels: 'xyz'}, - lab: {channels: 3, labels: 'lab'}, - lch: {channels: 3, labels: 'lch'}, - hex: {channels: 1, labels: ['hex']}, - keyword: {channels: 1, labels: ['keyword']}, - ansi16: {channels: 1, labels: ['ansi16']}, - ansi256: {channels: 1, labels: ['ansi256']}, - hcg: {channels: 3, labels: ['h', 'c', 'g']}, - apple: {channels: 3, labels: ['r16', 'g16', 'b16']}, - gray: {channels: 1, labels: ['gray']} -}; +const path = __webpack_require__(4) +const COLON = isWindows ? ';' : ':' +const isexe = __webpack_require__(234) -module.exports = convert; +const getNotFoundError = (cmd) => + Object.assign(new Error(`not found: ${cmd}`), { code: 'ENOENT' }) -// Hide .channels and .labels properties -for (const model of Object.keys(convert)) { - if (!('channels' in convert[model])) { - throw new Error('missing channels property: ' + model); - } +const getPathInfo = (cmd, opt) => { + const colon = opt.colon || COLON - if (!('labels' in convert[model])) { - throw new Error('missing channel labels property: ' + model); - } + // If it has a slash, then we don't bother searching the pathenv. + // just check the file itself, and that's it. + const pathEnv = cmd.match(/\//) || isWindows && cmd.match(/\\/) ? [''] + : ( + [ + // windows always checks the cwd first + ...(isWindows ? [process.cwd()] : []), + ...(opt.path || process.env.PATH || + /* istanbul ignore next: very unusual */ '').split(colon), + ] + ) + const pathExtExe = isWindows + ? opt.pathExt || process.env.PATHEXT || '.EXE;.CMD;.BAT;.COM' + : '' + const pathExt = isWindows ? pathExtExe.split(colon) : [''] - if (convert[model].labels.length !== convert[model].channels) { - throw new Error('channel and label counts mismatch: ' + model); - } + if (isWindows) { + if (cmd.indexOf('.') !== -1 && pathExt[0] !== '') + pathExt.unshift('') + } - const {channels, labels} = convert[model]; - delete convert[model].channels; - delete convert[model].labels; - Object.defineProperty(convert[model], 'channels', {value: channels}); - Object.defineProperty(convert[model], 'labels', {value: labels}); + return { + pathEnv, + pathExt, + pathExtExe, + } } -convert.rgb.hsl = function (rgb) { - const r = rgb[0] / 255; - const g = rgb[1] / 255; - const b = rgb[2] / 255; - const min = Math.min(r, g, b); - const max = Math.max(r, g, b); - const delta = max - min; - let h; - let s; - - if (max === min) { - h = 0; - } else if (r === max) { - h = (g - b) / delta; - } else if (g === max) { - h = 2 + (b - r) / delta; - } else if (b === max) { - h = 4 + (r - g) / delta; - } +const which = (cmd, opt, cb) => { + if (typeof opt === 'function') { + cb = opt + opt = {} + } + if (!opt) + opt = {} - h = Math.min(h * 60, 360); + const { pathEnv, pathExt, pathExtExe } = getPathInfo(cmd, opt) + const found = [] - if (h < 0) { - h += 360; - } + const step = i => new Promise((resolve, reject) => { + if (i === pathEnv.length) + return opt.all && found.length ? resolve(found) + : reject(getNotFoundError(cmd)) - const l = (min + max) / 2; + const ppRaw = pathEnv[i] + const pathPart = /^".*"$/.test(ppRaw) ? ppRaw.slice(1, -1) : ppRaw - if (max === min) { - s = 0; - } else if (l <= 0.5) { - s = delta / (max + min); - } else { - s = delta / (2 - max - min); - } + const pCmd = path.join(pathPart, cmd) + const p = !pathPart && /^\.[\\\/]/.test(cmd) ? cmd.slice(0, 2) + pCmd + : pCmd - return [h, s * 100, l * 100]; -}; + resolve(subStep(p, i, 0)) + }) -convert.rgb.hsv = function (rgb) { - let rdif; - let gdif; - let bdif; - let h; - let s; + const subStep = (p, i, ii) => new Promise((resolve, reject) => { + if (ii === pathExt.length) + return resolve(step(i + 1)) + const ext = pathExt[ii] + isexe(p + ext, { pathExt: pathExtExe }, (er, is) => { + if (!er && is) { + if (opt.all) + found.push(p + ext) + else + return resolve(p + ext) + } + return resolve(subStep(p, i, ii + 1)) + }) + }) - const r = rgb[0] / 255; - const g = rgb[1] / 255; - const b = rgb[2] / 255; - const v = Math.max(r, g, b); - const diff = v - Math.min(r, g, b); - const diffc = function (c) { - return (v - c) / 6 / diff + 1 / 2; - }; + return cb ? step(0).then(res => cb(null, res), cb) : step(0) +} - if (diff === 0) { - h = 0; - s = 0; - } else { - s = diff / v; - rdif = diffc(r); - gdif = diffc(g); - bdif = diffc(b); +const whichSync = (cmd, opt) => { + opt = opt || {} - if (r === v) { - h = bdif - gdif; - } else if (g === v) { - h = (1 / 3) + rdif - bdif; - } else if (b === v) { - h = (2 / 3) + gdif - rdif; - } + const { pathEnv, pathExt, pathExtExe } = getPathInfo(cmd, opt) + const found = [] - if (h < 0) { - h += 1; - } else if (h > 1) { - h -= 1; - } - } + for (let i = 0; i < pathEnv.length; i ++) { + const ppRaw = pathEnv[i] + const pathPart = /^".*"$/.test(ppRaw) ? ppRaw.slice(1, -1) : ppRaw - return [ - h * 360, - s * 100, - v * 100 - ]; -}; + const pCmd = path.join(pathPart, cmd) + const p = !pathPart && /^\.[\\\/]/.test(cmd) ? cmd.slice(0, 2) + pCmd + : pCmd -convert.rgb.hwb = function (rgb) { - const r = rgb[0]; - const g = rgb[1]; - let b = rgb[2]; - const h = convert.rgb.hsl(rgb)[0]; - const w = 1 / 255 * Math.min(r, Math.min(g, b)); + for (let j = 0; j < pathExt.length; j ++) { + const cur = p + pathExt[j] + try { + const is = isexe.sync(cur, { pathExt: pathExtExe }) + if (is) { + if (opt.all) + found.push(cur) + else + return cur + } + } catch (ex) {} + } + } - b = 1 - 1 / 255 * Math.max(r, Math.max(g, b)); + if (opt.all && found.length) + return found - return [h, w * 100, b * 100]; -}; + if (opt.nothrow) + return null -convert.rgb.cmyk = function (rgb) { - const r = rgb[0] / 255; - const g = rgb[1] / 255; - const b = rgb[2] / 255; + throw getNotFoundError(cmd) +} - const k = Math.min(1 - r, 1 - g, 1 - b); - const c = (1 - r - k) / (1 - k) || 0; - const m = (1 - g - k) / (1 - k) || 0; - const y = (1 - b - k) / (1 - k) || 0; +module.exports = which +which.sync = whichSync - return [c * 100, m * 100, y * 100, k * 100]; -}; -function comparativeDistance(x, y) { - /* - See https://en.m.wikipedia.org/wiki/Euclidean_distance#Squared_Euclidean_distance - */ - return ( - ((x[0] - y[0]) ** 2) + - ((x[1] - y[1]) ** 2) + - ((x[2] - y[2]) ** 2) - ); +/***/ }), +/* 234 */ +/***/ (function(module, exports, __webpack_require__) { + +var fs = __webpack_require__(134) +var core +if (process.platform === 'win32' || global.TESTING_WINDOWS) { + core = __webpack_require__(235) +} else { + core = __webpack_require__(236) } -convert.rgb.keyword = function (rgb) { - const reversed = reverseKeywords[rgb]; - if (reversed) { - return reversed; - } +module.exports = isexe +isexe.sync = sync - let currentClosestDistance = Infinity; - let currentClosestKeyword; +function isexe (path, options, cb) { + if (typeof options === 'function') { + cb = options + options = {} + } - for (const keyword of Object.keys(cssKeywords)) { - const value = cssKeywords[keyword]; + if (!cb) { + if (typeof Promise !== 'function') { + throw new TypeError('callback not provided') + } - // Compute comparative distance - const distance = comparativeDistance(rgb, value); + return new Promise(function (resolve, reject) { + isexe(path, options || {}, function (er, is) { + if (er) { + reject(er) + } else { + resolve(is) + } + }) + }) + } - // Check if its less, if so set as closest - if (distance < currentClosestDistance) { - currentClosestDistance = distance; - currentClosestKeyword = keyword; - } - } + core(path, options || {}, function (er, is) { + // ignore EACCES because that just means we aren't allowed to run it + if (er) { + if (er.code === 'EACCES' || options && options.ignoreErrors) { + er = null + is = false + } + } + cb(er, is) + }) +} - return currentClosestKeyword; -}; +function sync (path, options) { + // my kingdom for a filtered catch + try { + return core.sync(path, options || {}) + } catch (er) { + if (options && options.ignoreErrors || er.code === 'EACCES') { + return false + } else { + throw er + } + } +} -convert.keyword.rgb = function (keyword) { - return cssKeywords[keyword]; -}; -convert.rgb.xyz = function (rgb) { - let r = rgb[0] / 255; - let g = rgb[1] / 255; - let b = rgb[2] / 255; +/***/ }), +/* 235 */ +/***/ (function(module, exports, __webpack_require__) { - // Assume sRGB - r = r > 0.04045 ? (((r + 0.055) / 1.055) ** 2.4) : (r / 12.92); - g = g > 0.04045 ? (((g + 0.055) / 1.055) ** 2.4) : (g / 12.92); - b = b > 0.04045 ? (((b + 0.055) / 1.055) ** 2.4) : (b / 12.92); +module.exports = isexe +isexe.sync = sync - const x = (r * 0.4124) + (g * 0.3576) + (b * 0.1805); - const y = (r * 0.2126) + (g * 0.7152) + (b * 0.0722); - const z = (r * 0.0193) + (g * 0.1192) + (b * 0.9505); +var fs = __webpack_require__(134) - return [x * 100, y * 100, z * 100]; -}; +function checkPathExt (path, options) { + var pathext = options.pathExt !== undefined ? + options.pathExt : process.env.PATHEXT -convert.rgb.lab = function (rgb) { - const xyz = convert.rgb.xyz(rgb); - let x = xyz[0]; - let y = xyz[1]; - let z = xyz[2]; + if (!pathext) { + return true + } - x /= 95.047; - y /= 100; - z /= 108.883; + pathext = pathext.split(';') + if (pathext.indexOf('') !== -1) { + return true + } + for (var i = 0; i < pathext.length; i++) { + var p = pathext[i].toLowerCase() + if (p && path.substr(-p.length).toLowerCase() === p) { + return true + } + } + return false +} - x = x > 0.008856 ? (x ** (1 / 3)) : (7.787 * x) + (16 / 116); - y = y > 0.008856 ? (y ** (1 / 3)) : (7.787 * y) + (16 / 116); - z = z > 0.008856 ? (z ** (1 / 3)) : (7.787 * z) + (16 / 116); +function checkStat (stat, path, options) { + if (!stat.isSymbolicLink() && !stat.isFile()) { + return false + } + return checkPathExt(path, options) +} - const l = (116 * y) - 16; - const a = 500 * (x - y); - const b = 200 * (y - z); +function isexe (path, options, cb) { + fs.stat(path, function (er, stat) { + cb(er, er ? false : checkStat(stat, path, options)) + }) +} - return [l, a, b]; -}; +function sync (path, options) { + return checkStat(fs.statSync(path), path, options) +} -convert.hsl.rgb = function (hsl) { - const h = hsl[0] / 360; - const s = hsl[1] / 100; - const l = hsl[2] / 100; - let t2; - let t3; - let val; - if (s === 0) { - val = l * 255; - return [val, val, val]; - } +/***/ }), +/* 236 */ +/***/ (function(module, exports, __webpack_require__) { - if (l < 0.5) { - t2 = l * (1 + s); - } else { - t2 = l + s - l * s; - } +module.exports = isexe +isexe.sync = sync - const t1 = 2 * l - t2; +var fs = __webpack_require__(134) - const rgb = [0, 0, 0]; - for (let i = 0; i < 3; i++) { - t3 = h + 1 / 3 * -(i - 1); - if (t3 < 0) { - t3++; - } +function isexe (path, options, cb) { + fs.stat(path, function (er, stat) { + cb(er, er ? false : checkStat(stat, options)) + }) +} - if (t3 > 1) { - t3--; - } +function sync (path, options) { + return checkStat(fs.statSync(path), options) +} - if (6 * t3 < 1) { - val = t1 + (t2 - t1) * 6 * t3; - } else if (2 * t3 < 1) { - val = t2; - } else if (3 * t3 < 2) { - val = t1 + (t2 - t1) * (2 / 3 - t3) * 6; - } else { - val = t1; - } +function checkStat (stat, options) { + return stat.isFile() && checkMode(stat, options) +} - rgb[i] = val * 255; - } +function checkMode (stat, options) { + var mod = stat.mode + var uid = stat.uid + var gid = stat.gid - return rgb; -}; + var myUid = options.uid !== undefined ? + options.uid : process.getuid && process.getuid() + var myGid = options.gid !== undefined ? + options.gid : process.getgid && process.getgid() -convert.hsl.hsv = function (hsl) { - const h = hsl[0]; - let s = hsl[1] / 100; - let l = hsl[2] / 100; - let smin = s; - const lmin = Math.max(l, 0.01); + var u = parseInt('100', 8) + var g = parseInt('010', 8) + var o = parseInt('001', 8) + var ug = u | g - l *= 2; - s *= (l <= 1) ? l : 2 - l; - smin *= lmin <= 1 ? lmin : 2 - lmin; - const v = (l + s) / 2; - const sv = l === 0 ? (2 * smin) / (lmin + smin) : (2 * s) / (l + s); + var ret = (mod & o) || + (mod & g) && gid === myGid || + (mod & u) && uid === myUid || + (mod & ug) && myUid === 0 - return [h, sv * 100, v * 100]; -}; + return ret +} -convert.hsv.rgb = function (hsv) { - const h = hsv[0] / 60; - const s = hsv[1] / 100; - let v = hsv[2] / 100; - const hi = Math.floor(h) % 6; - const f = h - Math.floor(h); - const p = 255 * v * (1 - s); - const q = 255 * v * (1 - (s * f)); - const t = 255 * v * (1 - (s * (1 - f))); - v *= 255; +/***/ }), +/* 237 */ +/***/ (function(module, exports, __webpack_require__) { - switch (hi) { - case 0: - return [v, t, p]; - case 1: - return [q, v, p]; - case 2: - return [p, v, t]; - case 3: - return [p, q, v]; - case 4: - return [t, p, v]; - case 5: - return [v, p, q]; - } -}; +"use strict"; -convert.hsv.hsl = function (hsv) { - const h = hsv[0]; - const s = hsv[1] / 100; - const v = hsv[2] / 100; - const vmin = Math.max(v, 0.01); - let sl; - let l; - l = (2 - s) * v; - const lmin = (2 - s) * vmin; - sl = s * vmin; - sl /= (lmin <= 1) ? lmin : 2 - lmin; - sl = sl || 0; - l /= 2; +const pathKey = (options = {}) => { + const environment = options.env || process.env; + const platform = options.platform || process.platform; - return [h, sl * 100, l * 100]; + if (platform !== 'win32') { + return 'PATH'; + } + + return Object.keys(environment).find(key => key.toUpperCase() === 'PATH') || 'Path'; }; -// http://dev.w3.org/csswg/css-color/#hwb-to-rgb -convert.hwb.rgb = function (hwb) { - const h = hwb[0] / 360; - let wh = hwb[1] / 100; - let bl = hwb[2] / 100; - const ratio = wh + bl; - let f; +module.exports = pathKey; +// TODO: Remove this for the next major release +module.exports.default = pathKey; - // Wh + bl cant be > 1 - if (ratio > 1) { - wh /= ratio; - bl /= ratio; - } - const i = Math.floor(6 * h); - const v = 1 - bl; - f = 6 * h - i; +/***/ }), +/* 238 */ +/***/ (function(module, exports, __webpack_require__) { - if ((i & 0x01) !== 0) { - f = 1 - f; - } +"use strict"; - const n = wh + f * (v - wh); // Linear interpolation - let r; - let g; - let b; - /* eslint-disable max-statements-per-line,no-multi-spaces */ - switch (i) { - default: - case 6: - case 0: r = v; g = n; b = wh; break; - case 1: r = n; g = v; b = wh; break; - case 2: r = wh; g = v; b = n; break; - case 3: r = wh; g = n; b = v; break; - case 4: r = n; g = wh; b = v; break; - case 5: r = v; g = wh; b = n; break; - } - /* eslint-enable max-statements-per-line,no-multi-spaces */ +// See http://www.robvanderwoude.com/escapechars.php +const metaCharsRegExp = /([()\][%!^"`<>&|;, *?])/g; - return [r * 255, g * 255, b * 255]; -}; +function escapeCommand(arg) { + // Escape meta chars + arg = arg.replace(metaCharsRegExp, '^$1'); -convert.cmyk.rgb = function (cmyk) { - const c = cmyk[0] / 100; - const m = cmyk[1] / 100; - const y = cmyk[2] / 100; - const k = cmyk[3] / 100; + return arg; +} - const r = 1 - Math.min(1, c * (1 - k) + k); - const g = 1 - Math.min(1, m * (1 - k) + k); - const b = 1 - Math.min(1, y * (1 - k) + k); +function escapeArgument(arg, doubleEscapeMetaChars) { + // Convert to string + arg = `${arg}`; - return [r * 255, g * 255, b * 255]; -}; + // Algorithm below is based on https://qntm.org/cmd -convert.xyz.rgb = function (xyz) { - const x = xyz[0] / 100; - const y = xyz[1] / 100; - const z = xyz[2] / 100; - let r; - let g; - let b; + // Sequence of backslashes followed by a double quote: + // double up all the backslashes and escape the double quote + arg = arg.replace(/(\\*)"/g, '$1$1\\"'); - r = (x * 3.2406) + (y * -1.5372) + (z * -0.4986); - g = (x * -0.9689) + (y * 1.8758) + (z * 0.0415); - b = (x * 0.0557) + (y * -0.2040) + (z * 1.0570); + // Sequence of backslashes followed by the end of the string + // (which will become a double quote later): + // double up all the backslashes + arg = arg.replace(/(\\*)$/, '$1$1'); - // Assume sRGB - r = r > 0.0031308 - ? ((1.055 * (r ** (1.0 / 2.4))) - 0.055) - : r * 12.92; + // All other backslashes occur literally - g = g > 0.0031308 - ? ((1.055 * (g ** (1.0 / 2.4))) - 0.055) - : g * 12.92; + // Quote the whole thing: + arg = `"${arg}"`; - b = b > 0.0031308 - ? ((1.055 * (b ** (1.0 / 2.4))) - 0.055) - : b * 12.92; + // Escape meta chars + arg = arg.replace(metaCharsRegExp, '^$1'); - r = Math.min(Math.max(0, r), 1); - g = Math.min(Math.max(0, g), 1); - b = Math.min(Math.max(0, b), 1); + // Double escape meta chars if necessary + if (doubleEscapeMetaChars) { + arg = arg.replace(metaCharsRegExp, '^$1'); + } - return [r * 255, g * 255, b * 255]; -}; + return arg; +} -convert.xyz.lab = function (xyz) { - let x = xyz[0]; - let y = xyz[1]; - let z = xyz[2]; +module.exports.command = escapeCommand; +module.exports.argument = escapeArgument; - x /= 95.047; - y /= 100; - z /= 108.883; - x = x > 0.008856 ? (x ** (1 / 3)) : (7.787 * x) + (16 / 116); - y = y > 0.008856 ? (y ** (1 / 3)) : (7.787 * y) + (16 / 116); - z = z > 0.008856 ? (z ** (1 / 3)) : (7.787 * z) + (16 / 116); +/***/ }), +/* 239 */ +/***/ (function(module, exports, __webpack_require__) { - const l = (116 * y) - 16; - const a = 500 * (x - y); - const b = 200 * (y - z); +"use strict"; - return [l, a, b]; -}; -convert.lab.xyz = function (lab) { - const l = lab[0]; - const a = lab[1]; - const b = lab[2]; - let x; - let y; - let z; +const fs = __webpack_require__(134); +const shebangCommand = __webpack_require__(240); - y = (l + 16) / 116; - x = a / 500 + y; - z = y - b / 200; +function readShebang(command) { + // Read the first 150 bytes from the file + const size = 150; + const buffer = Buffer.alloc(size); - const y2 = y ** 3; - const x2 = x ** 3; - const z2 = z ** 3; - y = y2 > 0.008856 ? y2 : (y - 16 / 116) / 7.787; - x = x2 > 0.008856 ? x2 : (x - 16 / 116) / 7.787; - z = z2 > 0.008856 ? z2 : (z - 16 / 116) / 7.787; + let fd; - x *= 95.047; - y *= 100; - z *= 108.883; + try { + fd = fs.openSync(command, 'r'); + fs.readSync(fd, buffer, 0, size, 0); + fs.closeSync(fd); + } catch (e) { /* Empty */ } - return [x, y, z]; -}; + // Attempt to extract shebang (null is returned if not a shebang) + return shebangCommand(buffer.toString()); +} -convert.lab.lch = function (lab) { - const l = lab[0]; - const a = lab[1]; - const b = lab[2]; - let h; +module.exports = readShebang; - const hr = Math.atan2(b, a); - h = hr * 360 / 2 / Math.PI; - if (h < 0) { - h += 360; - } +/***/ }), +/* 240 */ +/***/ (function(module, exports, __webpack_require__) { - const c = Math.sqrt(a * a + b * b); +"use strict"; - return [l, c, h]; -}; +const shebangRegex = __webpack_require__(241); -convert.lch.lab = function (lch) { - const l = lch[0]; - const c = lch[1]; - const h = lch[2]; +module.exports = (string = '') => { + const match = string.match(shebangRegex); - const hr = h / 360 * 2 * Math.PI; - const a = c * Math.cos(hr); - const b = c * Math.sin(hr); - - return [l, a, b]; -}; - -convert.rgb.ansi16 = function (args, saturation = null) { - const [r, g, b] = args; - let value = saturation === null ? convert.rgb.hsv(args)[2] : saturation; // Hsv -> ansi16 optimization - - value = Math.round(value / 50); - - if (value === 0) { - return 30; + if (!match) { + return null; } - let ansi = 30 - + ((Math.round(b / 255) << 2) - | (Math.round(g / 255) << 1) - | Math.round(r / 255)); + const [path, argument] = match[0].replace(/#! ?/, '').split(' '); + const binary = path.split('/').pop(); - if (value === 2) { - ansi += 60; + if (binary === 'env') { + return argument; } - return ansi; + return argument ? `${binary} ${argument}` : binary; }; -convert.hsv.ansi16 = function (args) { - // Optimization here; we already know the value and don't need to get - // it converted for us. - return convert.rgb.ansi16(convert.hsv.rgb(args), args[2]); -}; -convert.rgb.ansi256 = function (args) { - const r = args[0]; - const g = args[1]; - const b = args[2]; +/***/ }), +/* 241 */ +/***/ (function(module, exports, __webpack_require__) { - // We use the extended greyscale palette here, with the exception of - // black and white. normal palette only has 4 greyscale shades. - if (r === g && g === b) { - if (r < 8) { - return 16; - } +"use strict"; - if (r > 248) { - return 231; - } +module.exports = /^#!(.*)/; - return Math.round(((r - 8) / 247) * 24) + 232; - } - const ansi = 16 - + (36 * Math.round(r / 255 * 5)) - + (6 * Math.round(g / 255 * 5)) - + Math.round(b / 255 * 5); +/***/ }), +/* 242 */ +/***/ (function(module, exports, __webpack_require__) { - return ansi; -}; +"use strict"; -convert.ansi16.rgb = function (args) { - let color = args % 10; - // Handle greyscale - if (color === 0 || color === 7) { - if (args > 50) { - color += 3.5; - } +const isWin = process.platform === 'win32'; - color = color / 10.5 * 255; +function notFoundError(original, syscall) { + return Object.assign(new Error(`${syscall} ${original.command} ENOENT`), { + code: 'ENOENT', + errno: 'ENOENT', + syscall: `${syscall} ${original.command}`, + path: original.command, + spawnargs: original.args, + }); +} - return [color, color, color]; - } +function hookChildProcess(cp, parsed) { + if (!isWin) { + return; + } - const mult = (~~(args > 50) + 1) * 0.5; - const r = ((color & 1) * mult) * 255; - const g = (((color >> 1) & 1) * mult) * 255; - const b = (((color >> 2) & 1) * mult) * 255; + const originalEmit = cp.emit; - return [r, g, b]; -}; + cp.emit = function (name, arg1) { + // If emitting "exit" event and exit code is 1, we need to check if + // the command exists and emit an "error" instead + // See https://github.com/IndigoUnited/node-cross-spawn/issues/16 + if (name === 'exit') { + const err = verifyENOENT(arg1, parsed, 'spawn'); -convert.ansi256.rgb = function (args) { - // Handle greyscale - if (args >= 232) { - const c = (args - 232) * 10 + 8; - return [c, c, c]; - } + if (err) { + return originalEmit.call(cp, 'error', err); + } + } - args -= 16; + return originalEmit.apply(cp, arguments); // eslint-disable-line prefer-rest-params + }; +} - let rem; - const r = Math.floor(args / 36) / 5 * 255; - const g = Math.floor((rem = args % 36) / 6) / 5 * 255; - const b = (rem % 6) / 5 * 255; +function verifyENOENT(status, parsed) { + if (isWin && status === 1 && !parsed.file) { + return notFoundError(parsed.original, 'spawn'); + } - return [r, g, b]; -}; + return null; +} -convert.rgb.hex = function (args) { - const integer = ((Math.round(args[0]) & 0xFF) << 16) - + ((Math.round(args[1]) & 0xFF) << 8) - + (Math.round(args[2]) & 0xFF); +function verifyENOENTSync(status, parsed) { + if (isWin && status === 1 && !parsed.file) { + return notFoundError(parsed.original, 'spawnSync'); + } - const string = integer.toString(16).toUpperCase(); - return '000000'.substring(string.length) + string; -}; + return null; +} -convert.hex.rgb = function (args) { - const match = args.toString(16).match(/[a-f0-9]{6}|[a-f0-9]{3}/i); - if (!match) { - return [0, 0, 0]; - } +module.exports = { + hookChildProcess, + verifyENOENT, + verifyENOENTSync, + notFoundError, +}; - let colorString = match[0]; - if (match[0].length === 3) { - colorString = colorString.split('').map(char => { - return char + char; - }).join(''); - } +/***/ }), +/* 243 */ +/***/ (function(module, exports, __webpack_require__) { - const integer = parseInt(colorString, 16); - const r = (integer >> 16) & 0xFF; - const g = (integer >> 8) & 0xFF; - const b = integer & 0xFF; +"use strict"; - return [r, g, b]; -}; -convert.rgb.hcg = function (rgb) { - const r = rgb[0] / 255; - const g = rgb[1] / 255; - const b = rgb[2] / 255; - const max = Math.max(Math.max(r, g), b); - const min = Math.min(Math.min(r, g), b); - const chroma = (max - min); - let grayscale; - let hue; +module.exports = input => { + const LF = typeof input === 'string' ? '\n' : '\n'.charCodeAt(); + const CR = typeof input === 'string' ? '\r' : '\r'.charCodeAt(); - if (chroma < 1) { - grayscale = min / (1 - chroma); - } else { - grayscale = 0; + if (input[input.length - 1] === LF) { + input = input.slice(0, input.length - 1); } - if (chroma <= 0) { - hue = 0; - } else - if (max === r) { - hue = ((g - b) / chroma) % 6; - } else - if (max === g) { - hue = 2 + (b - r) / chroma; - } else { - hue = 4 + (r - g) / chroma; + if (input[input.length - 1] === CR) { + input = input.slice(0, input.length - 1); } - hue /= 6; - hue %= 1; - - return [hue * 360, chroma * 100, grayscale * 100]; + return input; }; -convert.hsl.hcg = function (hsl) { - const s = hsl[1] / 100; - const l = hsl[2] / 100; - const c = l < 0.5 ? (2.0 * s * l) : (2.0 * s * (1.0 - l)); +/***/ }), +/* 244 */ +/***/ (function(module, exports, __webpack_require__) { - let f = 0; - if (c < 1.0) { - f = (l - 0.5 * c) / (1.0 - c); - } +"use strict"; - return [hsl[0], c * 100, f * 100]; -}; +const path = __webpack_require__(4); +const pathKey = __webpack_require__(237); -convert.hsv.hcg = function (hsv) { - const s = hsv[1] / 100; - const v = hsv[2] / 100; +const npmRunPath = options => { + options = { + cwd: process.cwd(), + path: process.env[pathKey()], + execPath: process.execPath, + ...options + }; - const c = s * v; - let f = 0; + let previous; + let cwdPath = path.resolve(options.cwd); + const result = []; - if (c < 1.0) { - f = (v - c) / (1 - c); + while (previous !== cwdPath) { + result.push(path.join(cwdPath, 'node_modules/.bin')); + previous = cwdPath; + cwdPath = path.resolve(cwdPath, '..'); } - return [hsv[0], c * 100, f * 100]; -}; + // Ensure the running `node` binary is used + const execPathDir = path.resolve(options.cwd, options.execPath, '..'); + result.push(execPathDir); -convert.hcg.rgb = function (hcg) { - const h = hcg[0] / 360; - const c = hcg[1] / 100; - const g = hcg[2] / 100; + return result.concat(options.path).join(path.delimiter); +}; - if (c === 0.0) { - return [g * 255, g * 255, g * 255]; - } +module.exports = npmRunPath; +// TODO: Remove this for the next major release +module.exports.default = npmRunPath; - const pure = [0, 0, 0]; - const hi = (h % 1) * 6; - const v = hi % 1; - const w = 1 - v; - let mg = 0; +module.exports.env = options => { + options = { + env: process.env, + ...options + }; - /* eslint-disable max-statements-per-line */ - switch (Math.floor(hi)) { - case 0: - pure[0] = 1; pure[1] = v; pure[2] = 0; break; - case 1: - pure[0] = w; pure[1] = 1; pure[2] = 0; break; - case 2: - pure[0] = 0; pure[1] = 1; pure[2] = v; break; - case 3: - pure[0] = 0; pure[1] = w; pure[2] = 1; break; - case 4: - pure[0] = v; pure[1] = 0; pure[2] = 1; break; - default: - pure[0] = 1; pure[1] = 0; pure[2] = w; - } - /* eslint-enable max-statements-per-line */ + const env = {...options.env}; + const path = pathKey({env}); - mg = (1.0 - c) * g; + options.path = env[path]; + env[path] = module.exports(options); - return [ - (c * pure[0] + mg) * 255, - (c * pure[1] + mg) * 255, - (c * pure[2] + mg) * 255 - ]; + return env; }; -convert.hcg.hsv = function (hcg) { - const c = hcg[1] / 100; - const g = hcg[2] / 100; - - const v = c + g * (1.0 - c); - let f = 0; - if (v > 0.0) { - f = c / v; - } +/***/ }), +/* 245 */ +/***/ (function(module, exports, __webpack_require__) { - return [hcg[0], f * 100, v * 100]; -}; +"use strict"; -convert.hcg.hsl = function (hcg) { - const c = hcg[1] / 100; - const g = hcg[2] / 100; +const mimicFn = __webpack_require__(246); - const l = g * (1.0 - c) + 0.5 * c; - let s = 0; +const calledFunctions = new WeakMap(); - if (l > 0.0 && l < 0.5) { - s = c / (2 * l); - } else - if (l >= 0.5 && l < 1.0) { - s = c / (2 * (1 - l)); +const oneTime = (fn, options = {}) => { + if (typeof fn !== 'function') { + throw new TypeError('Expected a function'); } - return [hcg[0], s * 100, l * 100]; -}; + let ret; + let isCalled = false; + let callCount = 0; + const functionName = fn.displayName || fn.name || ''; -convert.hcg.hwb = function (hcg) { - const c = hcg[1] / 100; - const g = hcg[2] / 100; - const v = c + g * (1.0 - c); - return [hcg[0], (v - c) * 100, (1 - v) * 100]; -}; + const onetime = function (...args) { + calledFunctions.set(onetime, ++callCount); -convert.hwb.hcg = function (hwb) { - const w = hwb[1] / 100; - const b = hwb[2] / 100; - const v = 1 - b; - const c = v - w; - let g = 0; + if (isCalled) { + if (options.throw === true) { + throw new Error(`Function \`${functionName}\` can only be called once`); + } - if (c < 1) { - g = (v - c) / (1 - c); - } + return ret; + } - return [hwb[0], c * 100, g * 100]; -}; + isCalled = true; + ret = fn.apply(this, args); + fn = null; -convert.apple.rgb = function (apple) { - return [(apple[0] / 65535) * 255, (apple[1] / 65535) * 255, (apple[2] / 65535) * 255]; -}; + return ret; + }; -convert.rgb.apple = function (rgb) { - return [(rgb[0] / 255) * 65535, (rgb[1] / 255) * 65535, (rgb[2] / 255) * 65535]; -}; + mimicFn(onetime, fn); + calledFunctions.set(onetime, callCount); -convert.gray.rgb = function (args) { - return [args[0] / 100 * 255, args[0] / 100 * 255, args[0] / 100 * 255]; + return onetime; }; -convert.gray.hsl = function (args) { - return [0, 0, args[0]]; -}; +module.exports = oneTime; +// TODO: Remove this for the next major release +module.exports.default = oneTime; -convert.gray.hsv = convert.gray.hsl; +module.exports.callCount = fn => { + if (!calledFunctions.has(fn)) { + throw new Error(`The given function \`${fn.name}\` is not wrapped by the \`onetime\` package`); + } -convert.gray.hwb = function (gray) { - return [0, 100, gray[0]]; + return calledFunctions.get(fn); }; -convert.gray.cmyk = function (gray) { - return [0, 0, 0, gray[0]]; -}; -convert.gray.lab = function (gray) { - return [gray[0], 0, 0]; -}; +/***/ }), +/* 246 */ +/***/ (function(module, exports, __webpack_require__) { -convert.gray.hex = function (gray) { - const val = Math.round(gray[0] / 100 * 255) & 0xFF; - const integer = (val << 16) + (val << 8) + val; +"use strict"; - const string = integer.toString(16).toUpperCase(); - return '000000'.substring(string.length) + string; -}; -convert.rgb.gray = function (rgb) { - const val = (rgb[0] + rgb[1] + rgb[2]) / 3; - return [val / 255 * 100]; +const mimicFn = (to, from) => { + for (const prop of Reflect.ownKeys(from)) { + Object.defineProperty(to, prop, Object.getOwnPropertyDescriptor(from, prop)); + } + + return to; }; +module.exports = mimicFn; +// TODO: Remove this for the next major release +module.exports.default = mimicFn; + /***/ }), -/* 231 */ +/* 247 */ /***/ (function(module, exports, __webpack_require__) { -const conversions = __webpack_require__(230); +"use strict"; -/* - This function routes a model to all other models. +const {signalsByName} = __webpack_require__(248); - all functions that are routed have a property `.conversion` attached - to the returned synthetic function. This property is an array - of strings, each with the steps in between the 'from' and 'to' - color models (inclusive). +const getErrorPrefix = ({timedOut, timeout, errorCode, signal, signalDescription, exitCode, isCanceled}) => { + if (timedOut) { + return `timed out after ${timeout} milliseconds`; + } - conversions that are not possible simply are not included. -*/ + if (isCanceled) { + return 'was canceled'; + } -function buildGraph() { - const graph = {}; - // https://jsperf.com/object-keys-vs-for-in-with-closure/3 - const models = Object.keys(conversions); + if (errorCode !== undefined) { + return `failed with ${errorCode}`; + } - for (let len = models.length, i = 0; i < len; i++) { - graph[models[i]] = { - // http://jsperf.com/1-vs-infinity - // micro-opt, but this is simple. - distance: -1, - parent: null - }; + if (signal !== undefined) { + return `was killed with ${signal} (${signalDescription})`; } - return graph; -} + if (exitCode !== undefined) { + return `failed with exit code ${exitCode}`; + } -// https://en.wikipedia.org/wiki/Breadth-first_search -function deriveBFS(fromModel) { - const graph = buildGraph(); - const queue = [fromModel]; // Unshift -> queue -> pop + return 'failed'; +}; - graph[fromModel].distance = 0; +const makeError = ({ + stdout, + stderr, + all, + error, + signal, + exitCode, + command, + timedOut, + isCanceled, + killed, + parsed: {options: {timeout}} +}) => { + // `signal` and `exitCode` emitted on `spawned.on('exit')` event can be `null`. + // We normalize them to `undefined` + exitCode = exitCode === null ? undefined : exitCode; + signal = signal === null ? undefined : signal; + const signalDescription = signal === undefined ? undefined : signalsByName[signal].description; - while (queue.length) { - const current = queue.pop(); - const adjacents = Object.keys(conversions[current]); + const errorCode = error && error.code; - for (let len = adjacents.length, i = 0; i < len; i++) { - const adjacent = adjacents[i]; - const node = graph[adjacent]; + const prefix = getErrorPrefix({timedOut, timeout, errorCode, signal, signalDescription, exitCode, isCanceled}); + const execaMessage = `Command ${prefix}: ${command}`; + const isError = Object.prototype.toString.call(error) === '[object Error]'; + const shortMessage = isError ? `${execaMessage}\n${error.message}` : execaMessage; + const message = [shortMessage, stderr, stdout].filter(Boolean).join('\n'); - if (node.distance === -1) { - node.distance = graph[current].distance + 1; - node.parent = current; - queue.unshift(adjacent); - } - } + if (isError) { + error.originalMessage = error.message; + error.message = message; + } else { + error = new Error(message); } - return graph; -} - -function link(from, to) { - return function (args) { - return to(from(args)); - }; -} + error.shortMessage = shortMessage; + error.command = command; + error.exitCode = exitCode; + error.signal = signal; + error.signalDescription = signalDescription; + error.stdout = stdout; + error.stderr = stderr; -function wrapConversion(toModel, graph) { - const path = [graph[toModel].parent, toModel]; - let fn = conversions[graph[toModel].parent][toModel]; - - let cur = graph[toModel].parent; - while (graph[cur].parent) { - path.unshift(graph[cur].parent); - fn = link(conversions[graph[cur].parent][cur], fn); - cur = graph[cur].parent; + if (all !== undefined) { + error.all = all; } - fn.conversion = path; - return fn; -} - -module.exports = function (fromModel) { - const graph = deriveBFS(fromModel); - const conversion = {}; - - const models = Object.keys(graph); - for (let len = models.length, i = 0; i < len; i++) { - const toModel = models[i]; - const node = graph[toModel]; - - if (node.parent === null) { - // No possible conversion, or this node is the source model. - continue; - } - - conversion[toModel] = wrapConversion(toModel, graph); + if ('bufferedData' in error) { + delete error.bufferedData; } - return conversion; + error.failed = true; + error.timedOut = Boolean(timedOut); + error.isCanceled = isCanceled; + error.killed = killed && !timedOut; + + return error; }; +module.exports = makeError; /***/ }), -/* 232 */ +/* 248 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; +Object.defineProperty(exports,"__esModule",{value:true});exports.signalsByNumber=exports.signalsByName=void 0;var _os=__webpack_require__(121); -const os = __webpack_require__(120); -const tty = __webpack_require__(121); -const hasFlag = __webpack_require__(233); - -const {env} = process; - -let forceColor; -if (hasFlag('no-color') || - hasFlag('no-colors') || - hasFlag('color=false') || - hasFlag('color=never')) { - forceColor = 0; -} else if (hasFlag('color') || - hasFlag('colors') || - hasFlag('color=true') || - hasFlag('color=always')) { - forceColor = 1; -} - -if ('FORCE_COLOR' in env) { - if (env.FORCE_COLOR === 'true') { - forceColor = 1; - } else if (env.FORCE_COLOR === 'false') { - forceColor = 0; - } else { - forceColor = env.FORCE_COLOR.length === 0 ? 1 : Math.min(parseInt(env.FORCE_COLOR, 10), 3); - } -} - -function translateLevel(level) { - if (level === 0) { - return false; - } - - return { - level, - hasBasic: true, - has256: level >= 2, - has16m: level >= 3 - }; -} +var _signals=__webpack_require__(249); +var _realtime=__webpack_require__(251); -function supportsColor(haveStream, streamIsTTY) { - if (forceColor === 0) { - return 0; - } - if (hasFlag('color=16m') || - hasFlag('color=full') || - hasFlag('color=truecolor')) { - return 3; - } - if (hasFlag('color=256')) { - return 2; - } +const getSignalsByName=function(){ +const signals=(0,_signals.getSignals)(); +return signals.reduce(getSignalByName,{}); +}; - if (haveStream && !streamIsTTY && forceColor === undefined) { - return 0; - } +const getSignalByName=function( +signalByNameMemo, +{name,number,description,supported,action,forced,standard}) +{ +return{ +...signalByNameMemo, +[name]:{name,number,description,supported,action,forced,standard}}; - const min = forceColor || 0; +}; - if (env.TERM === 'dumb') { - return min; - } +const signalsByName=getSignalsByName();exports.signalsByName=signalsByName; - if (process.platform === 'win32') { - // Windows 10 build 10586 is the first Windows release that supports 256 colors. - // Windows 10 build 14931 is the first release that supports 16m/TrueColor. - const osRelease = os.release().split('.'); - if ( - Number(osRelease[0]) >= 10 && - Number(osRelease[2]) >= 10586 - ) { - return Number(osRelease[2]) >= 14931 ? 3 : 2; - } - return 1; - } - if ('CI' in env) { - if (['TRAVIS', 'CIRCLECI', 'APPVEYOR', 'GITLAB_CI'].some(sign => sign in env) || env.CI_NAME === 'codeship') { - return 1; - } - return min; - } +const getSignalsByNumber=function(){ +const signals=(0,_signals.getSignals)(); +const length=_realtime.SIGRTMAX+1; +const signalsA=Array.from({length},(value,number)=> +getSignalByNumber(number,signals)); - if ('TEAMCITY_VERSION' in env) { - return /^(9\.(0*[1-9]\d*)\.|\d{2,}\.)/.test(env.TEAMCITY_VERSION) ? 1 : 0; - } +return Object.assign({},...signalsA); +}; - if ('GITHUB_ACTIONS' in env) { - return 1; - } +const getSignalByNumber=function(number,signals){ +const signal=findSignalByNumber(number,signals); - if (env.COLORTERM === 'truecolor') { - return 3; - } +if(signal===undefined){ +return{}; +} - if ('TERM_PROGRAM' in env) { - const version = parseInt((env.TERM_PROGRAM_VERSION || '').split('.')[0], 10); +const{name,description,supported,action,forced,standard}=signal; +return{ +[number]:{ +name, +number, +description, +supported, +action, +forced, +standard}}; - switch (env.TERM_PROGRAM) { - case 'iTerm.app': - return version >= 3 ? 3 : 2; - case 'Apple_Terminal': - return 2; - // No default - } - } - if (/-256(color)?$/i.test(env.TERM)) { - return 2; - } +}; - if (/^screen|^xterm|^vt100|^vt220|^rxvt|color|ansi|cygwin|linux/i.test(env.TERM)) { - return 1; - } - if ('COLORTERM' in env) { - return 1; - } - return min; -} +const findSignalByNumber=function(number,signals){ +const signal=signals.find(({name})=>_os.constants.signals[name]===number); -function getSupportLevel(stream) { - const level = supportsColor(stream, stream && stream.isTTY); - return translateLevel(level); +if(signal!==undefined){ +return signal; } -module.exports = { - supportsColor: getSupportLevel, - stdout: translateLevel(supportsColor(true, tty.isatty(1))), - stderr: translateLevel(supportsColor(true, tty.isatty(2))) +return signals.find(signalA=>signalA.number===number); }; +const signalsByNumber=getSignalsByNumber();exports.signalsByNumber=signalsByNumber; +//# sourceMappingURL=main.js.map /***/ }), -/* 233 */ +/* 249 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; +Object.defineProperty(exports,"__esModule",{value:true});exports.getSignals=void 0;var _os=__webpack_require__(121); - -module.exports = (flag, argv = process.argv) => { - const prefix = flag.startsWith('-') ? '' : (flag.length === 1 ? '-' : '--'); - const position = argv.indexOf(prefix + flag); - const terminatorPosition = argv.indexOf('--'); - return position !== -1 && (terminatorPosition === -1 || position < terminatorPosition); -}; +var _core=__webpack_require__(250); +var _realtime=__webpack_require__(251); -/***/ }), -/* 234 */ -/***/ (function(module, exports, __webpack_require__) { -"use strict"; +const getSignals=function(){ +const realtimeSignals=(0,_realtime.getRealtimeSignals)(); +const signals=[..._core.SIGNALS,...realtimeSignals].map(normalizeSignal); +return signals; +};exports.getSignals=getSignals; -const stringReplaceAll = (string, substring, replacer) => { - let index = string.indexOf(substring); - if (index === -1) { - return string; - } - const substringLength = substring.length; - let endIndex = 0; - let returnValue = ''; - do { - returnValue += string.substr(endIndex, index - endIndex) + substring + replacer; - endIndex = index + substringLength; - index = string.indexOf(substring, endIndex); - } while (index !== -1); - returnValue += string.substr(endIndex); - return returnValue; -}; -const stringEncaseCRLFWithFirstIndex = (string, prefix, postfix, index) => { - let endIndex = 0; - let returnValue = ''; - do { - const gotCR = string[index - 1] === '\r'; - returnValue += string.substr(endIndex, (gotCR ? index - 1 : index) - endIndex) + prefix + (gotCR ? '\r\n' : '\n') + postfix; - endIndex = index + 1; - index = string.indexOf('\n', endIndex); - } while (index !== -1); - returnValue += string.substr(endIndex); - return returnValue; -}; -module.exports = { - stringReplaceAll, - stringEncaseCRLFWithFirstIndex +const normalizeSignal=function({ +name, +number:defaultNumber, +description, +action, +forced=false, +standard}) +{ +const{ +signals:{[name]:constantSignal}}= +_os.constants; +const supported=constantSignal!==undefined; +const number=supported?constantSignal:defaultNumber; +return{name,number,description,supported,action,forced,standard}; }; - +//# sourceMappingURL=signals.js.map /***/ }), -/* 235 */ +/* 250 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; +Object.defineProperty(exports,"__esModule",{value:true});exports.SIGNALS=void 0; -const TEMPLATE_REGEX = /(?:\\(u(?:[a-f\d]{4}|\{[a-f\d]{1,6}\})|x[a-f\d]{2}|.))|(?:\{(~)?(\w+(?:\([^)]*\))?(?:\.\w+(?:\([^)]*\))?)*)(?:[ \t]|(?=\r?\n)))|(\})|((?:.|[\r\n\f])+?)/gi; -const STYLE_REGEX = /(?:^|\.)(\w+)(?:\(([^)]*)\))?/g; -const STRING_REGEX = /^(['"])((?:\\.|(?!\1)[^\\])*)\1$/; -const ESCAPE_REGEX = /\\(u(?:[a-f\d]{4}|{[a-f\d]{1,6}})|x[a-f\d]{2}|.)|([^\\])/gi; - -const ESCAPES = new Map([ - ['n', '\n'], - ['r', '\r'], - ['t', '\t'], - ['b', '\b'], - ['f', '\f'], - ['v', '\v'], - ['0', '\0'], - ['\\', '\\'], - ['e', '\u001B'], - ['a', '\u0007'] -]); +const SIGNALS=[ +{ +name:"SIGHUP", +number:1, +action:"terminate", +description:"Terminal closed", +standard:"posix"}, -function unescape(c) { - const u = c[0] === 'u'; - const bracket = c[1] === '{'; +{ +name:"SIGINT", +number:2, +action:"terminate", +description:"User interruption with CTRL-C", +standard:"ansi"}, - if ((u && !bracket && c.length === 5) || (c[0] === 'x' && c.length === 3)) { - return String.fromCharCode(parseInt(c.slice(1), 16)); - } +{ +name:"SIGQUIT", +number:3, +action:"core", +description:"User interruption with CTRL-\\", +standard:"posix"}, - if (u && bracket) { - return String.fromCodePoint(parseInt(c.slice(2, -1), 16)); - } +{ +name:"SIGILL", +number:4, +action:"core", +description:"Invalid machine instruction", +standard:"ansi"}, - return ESCAPES.get(c) || c; -} +{ +name:"SIGTRAP", +number:5, +action:"core", +description:"Debugger breakpoint", +standard:"posix"}, -function parseArguments(name, arguments_) { - const results = []; - const chunks = arguments_.trim().split(/\s*,\s*/g); - let matches; +{ +name:"SIGABRT", +number:6, +action:"core", +description:"Aborted", +standard:"ansi"}, - for (const chunk of chunks) { - const number = Number(chunk); - if (!Number.isNaN(number)) { - results.push(number); - } else if ((matches = chunk.match(STRING_REGEX))) { - results.push(matches[2].replace(ESCAPE_REGEX, (m, escape, character) => escape ? unescape(escape) : character)); - } else { - throw new Error(`Invalid Chalk template style argument: ${chunk} (in style '${name}')`); - } - } +{ +name:"SIGIOT", +number:6, +action:"core", +description:"Aborted", +standard:"bsd"}, - return results; -} +{ +name:"SIGBUS", +number:7, +action:"core", +description: +"Bus error due to misaligned, non-existing address or paging error", +standard:"bsd"}, -function parseStyle(style) { - STYLE_REGEX.lastIndex = 0; +{ +name:"SIGEMT", +number:7, +action:"terminate", +description:"Command should be emulated but is not implemented", +standard:"other"}, - const results = []; - let matches; +{ +name:"SIGFPE", +number:8, +action:"core", +description:"Floating point arithmetic error", +standard:"ansi"}, - while ((matches = STYLE_REGEX.exec(style)) !== null) { - const name = matches[1]; +{ +name:"SIGKILL", +number:9, +action:"terminate", +description:"Forced termination", +standard:"posix", +forced:true}, - if (matches[2]) { - const args = parseArguments(name, matches[2]); - results.push([name].concat(args)); - } else { - results.push([name]); - } - } +{ +name:"SIGUSR1", +number:10, +action:"terminate", +description:"Application-specific signal", +standard:"posix"}, - return results; -} +{ +name:"SIGSEGV", +number:11, +action:"core", +description:"Segmentation fault", +standard:"ansi"}, -function buildStyle(chalk, styles) { - const enabled = {}; +{ +name:"SIGUSR2", +number:12, +action:"terminate", +description:"Application-specific signal", +standard:"posix"}, - for (const layer of styles) { - for (const style of layer.styles) { - enabled[style[0]] = layer.inverse ? null : style.slice(1); - } - } +{ +name:"SIGPIPE", +number:13, +action:"terminate", +description:"Broken pipe or socket", +standard:"posix"}, - let current = chalk; - for (const [styleName, styles] of Object.entries(enabled)) { - if (!Array.isArray(styles)) { - continue; - } +{ +name:"SIGALRM", +number:14, +action:"terminate", +description:"Timeout or timer", +standard:"posix"}, - if (!(styleName in current)) { - throw new Error(`Unknown Chalk style: ${styleName}`); - } +{ +name:"SIGTERM", +number:15, +action:"terminate", +description:"Termination", +standard:"ansi"}, - current = styles.length > 0 ? current[styleName](...styles) : current[styleName]; - } +{ +name:"SIGSTKFLT", +number:16, +action:"terminate", +description:"Stack is empty or overflowed", +standard:"other"}, - return current; -} +{ +name:"SIGCHLD", +number:17, +action:"ignore", +description:"Child process terminated, paused or unpaused", +standard:"posix"}, -module.exports = (chalk, temporary) => { - const styles = []; - const chunks = []; - let chunk = []; +{ +name:"SIGCLD", +number:17, +action:"ignore", +description:"Child process terminated, paused or unpaused", +standard:"other"}, - // eslint-disable-next-line max-params - temporary.replace(TEMPLATE_REGEX, (m, escapeCharacter, inverse, style, close, character) => { - if (escapeCharacter) { - chunk.push(unescape(escapeCharacter)); - } else if (style) { - const string = chunk.join(''); - chunk = []; - chunks.push(styles.length === 0 ? string : buildStyle(chalk, styles)(string)); - styles.push({inverse, styles: parseStyle(style)}); - } else if (close) { - if (styles.length === 0) { - throw new Error('Found extraneous } in Chalk template literal'); - } +{ +name:"SIGCONT", +number:18, +action:"unpause", +description:"Unpaused", +standard:"posix", +forced:true}, - chunks.push(buildStyle(chalk, styles)(chunk.join(''))); - chunk = []; - styles.pop(); - } else { - chunk.push(character); - } - }); +{ +name:"SIGSTOP", +number:19, +action:"pause", +description:"Paused", +standard:"posix", +forced:true}, - chunks.push(chunk.join('')); +{ +name:"SIGTSTP", +number:20, +action:"pause", +description:"Paused using CTRL-Z or \"suspend\"", +standard:"posix"}, - if (styles.length > 0) { - const errMessage = `Chalk template literal is missing ${styles.length} closing bracket${styles.length === 1 ? '' : 's'} (\`}\`)`; - throw new Error(errMessage); - } +{ +name:"SIGTTIN", +number:21, +action:"pause", +description:"Background process cannot read terminal input", +standard:"posix"}, - return chunks.join(''); -}; +{ +name:"SIGBREAK", +number:21, +action:"terminate", +description:"User interruption with CTRL-BREAK", +standard:"other"}, + +{ +name:"SIGTTOU", +number:22, +action:"pause", +description:"Background process cannot write to terminal output", +standard:"posix"}, + +{ +name:"SIGURG", +number:23, +action:"ignore", +description:"Socket received out-of-band data", +standard:"bsd"}, + +{ +name:"SIGXCPU", +number:24, +action:"core", +description:"Process timed out", +standard:"bsd"}, + +{ +name:"SIGXFSZ", +number:25, +action:"core", +description:"File too big", +standard:"bsd"}, + +{ +name:"SIGVTALRM", +number:26, +action:"terminate", +description:"Timeout or timer", +standard:"bsd"}, + +{ +name:"SIGPROF", +number:27, +action:"terminate", +description:"Timeout or timer", +standard:"bsd"}, + +{ +name:"SIGWINCH", +number:28, +action:"ignore", +description:"Terminal window size changed", +standard:"bsd"}, + +{ +name:"SIGIO", +number:29, +action:"terminate", +description:"I/O is available", +standard:"other"}, + +{ +name:"SIGPOLL", +number:29, +action:"terminate", +description:"Watched event", +standard:"other"}, + +{ +name:"SIGINFO", +number:29, +action:"ignore", +description:"Request for process information", +standard:"other"}, + +{ +name:"SIGPWR", +number:30, +action:"terminate", +description:"Device running out of power", +standard:"systemv"}, + +{ +name:"SIGSYS", +number:31, +action:"core", +description:"Invalid system call", +standard:"other"}, +{ +name:"SIGUNUSED", +number:31, +action:"terminate", +description:"Invalid system call", +standard:"other"}];exports.SIGNALS=SIGNALS; +//# sourceMappingURL=core.js.map /***/ }), -/* 236 */ +/* 251 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; +Object.defineProperty(exports,"__esModule",{value:true});exports.SIGRTMAX=exports.getRealtimeSignals=void 0; +const getRealtimeSignals=function(){ +const length=SIGRTMAX-SIGRTMIN+1; +return Array.from({length},getRealtimeSignal); +};exports.getRealtimeSignals=getRealtimeSignals; -const path = __webpack_require__(4); -const childProcess = __webpack_require__(237); -const crossSpawn = __webpack_require__(238); -const stripFinalNewline = __webpack_require__(251); -const npmRunPath = __webpack_require__(252); -const onetime = __webpack_require__(253); -const makeError = __webpack_require__(255); -const normalizeStdio = __webpack_require__(260); -const {spawnedKill, spawnedCancel, setupTimeout, setExitHandler} = __webpack_require__(261); -const {handleInput, getSpawnedResult, makeAllStream, validateInputSync} = __webpack_require__(262); -const {mergePromise, getSpawnedPromise} = __webpack_require__(269); -const {joinCommand, parseCommand} = __webpack_require__(270); +const getRealtimeSignal=function(value,index){ +return{ +name:`SIGRT${index+1}`, +number:SIGRTMIN+index, +action:"terminate", +description:"Application-specific signal (realtime)", +standard:"posix"}; -const DEFAULT_MAX_BUFFER = 1000 * 1000 * 100; +}; -const getEnv = ({env: envOption, extendEnv, preferLocal, localDir, execPath}) => { - const env = extendEnv ? {...process.env, ...envOption} : envOption; +const SIGRTMIN=34; +const SIGRTMAX=64;exports.SIGRTMAX=SIGRTMAX; +//# sourceMappingURL=realtime.js.map - if (preferLocal) { - return npmRunPath.env({env, cwd: localDir, execPath}); - } +/***/ }), +/* 252 */ +/***/ (function(module, exports, __webpack_require__) { - return env; -}; +"use strict"; -const handleArgs = (file, args, options = {}) => { - const parsed = crossSpawn._parse(file, args, options); - file = parsed.command; - args = parsed.args; - options = parsed.options; +const aliases = ['stdin', 'stdout', 'stderr']; - options = { - maxBuffer: DEFAULT_MAX_BUFFER, - buffer: true, - stripFinalNewline: true, - extendEnv: true, - preferLocal: false, - localDir: options.cwd || process.cwd(), - execPath: process.execPath, - encoding: 'utf8', - reject: true, - cleanup: true, - all: false, - windowsHide: true, - ...options - }; +const hasAlias = opts => aliases.some(alias => opts[alias] !== undefined); - options.env = getEnv(options); +const normalizeStdio = opts => { + if (!opts) { + return; + } - options.stdio = normalizeStdio(options); + const {stdio} = opts; - if (process.platform === 'win32' && path.basename(file, '.exe') === 'cmd') { - // #116 - args.unshift('/q'); + if (stdio === undefined) { + return aliases.map(alias => opts[alias]); } - return {file, args, options, parsed}; -}; + if (hasAlias(opts)) { + throw new Error(`It's not possible to provide \`stdio\` in combination with one of ${aliases.map(alias => `\`${alias}\``).join(', ')}`); + } -const handleOutput = (options, value, error) => { - if (typeof value !== 'string' && !Buffer.isBuffer(value)) { - // When `execa.sync()` errors, we normalize it to '' to mimic `execa()` - return error === undefined ? undefined : ''; + if (typeof stdio === 'string') { + return stdio; } - if (options.stripFinalNewline) { - return stripFinalNewline(value); + if (!Array.isArray(stdio)) { + throw new TypeError(`Expected \`stdio\` to be of type \`string\` or \`Array\`, got \`${typeof stdio}\``); } - return value; + const length = Math.max(stdio.length, aliases.length); + return Array.from({length}, (value, index) => stdio[index]); }; -const execa = (file, args, options) => { - const parsed = handleArgs(file, args, options); - const command = joinCommand(file, args); +module.exports = normalizeStdio; - let spawned; - try { - spawned = childProcess.spawn(parsed.file, parsed.args, parsed.options); - } catch (error) { - // Ensure the returned error is always both a promise and a child process - const dummySpawned = new childProcess.ChildProcess(); - const errorPromise = Promise.reject(makeError({ - error, - stdout: '', - stderr: '', - all: '', - command, - parsed, - timedOut: false, - isCanceled: false, - killed: false - })); - return mergePromise(dummySpawned, errorPromise); - } +// `ipc` is pushed unless it is already present +module.exports.node = opts => { + const stdio = normalizeStdio(opts); - const spawnedPromise = getSpawnedPromise(spawned); - const timedPromise = setupTimeout(spawned, parsed.options, spawnedPromise); - const processDone = setExitHandler(spawned, parsed.options, timedPromise); + if (stdio === 'ipc') { + return 'ipc'; + } - const context = {isCanceled: false}; + if (stdio === undefined || typeof stdio === 'string') { + return [stdio, stdio, stdio, 'ipc']; + } - spawned.kill = spawnedKill.bind(null, spawned.kill.bind(spawned)); - spawned.cancel = spawnedCancel.bind(null, spawned, context); + if (stdio.includes('ipc')) { + return stdio; + } - const handlePromise = async () => { - const [{error, exitCode, signal, timedOut}, stdoutResult, stderrResult, allResult] = await getSpawnedResult(spawned, parsed.options, processDone); - const stdout = handleOutput(parsed.options, stdoutResult); - const stderr = handleOutput(parsed.options, stderrResult); - const all = handleOutput(parsed.options, allResult); + return [...stdio, 'ipc']; +}; - if (error || exitCode !== 0 || signal !== null) { - const returnedError = makeError({ - error, - exitCode, - signal, - stdout, - stderr, - all, - command, - parsed, - timedOut, - isCanceled: context.isCanceled, - killed: spawned.killed - }); - if (!parsed.options.reject) { - return returnedError; - } +/***/ }), +/* 253 */ +/***/ (function(module, exports, __webpack_require__) { - throw returnedError; - } +"use strict"; - return { - command, - exitCode: 0, - stdout, - stderr, - all, - failed: false, - timedOut: false, - isCanceled: false, - killed: false - }; - }; +const os = __webpack_require__(121); +const onExit = __webpack_require__(218); - const handlePromiseOnce = onetime(handlePromise); +const DEFAULT_FORCE_KILL_TIMEOUT = 1000 * 5; - crossSpawn._enoent.hookChildProcess(spawned, parsed.parsed); +// Monkey-patches `childProcess.kill()` to add `forceKillAfterTimeout` behavior +const spawnedKill = (kill, signal = 'SIGTERM', options = {}) => { + const killResult = kill(signal); + setKillTimeout(kill, signal, options, killResult); + return killResult; +}; - handleInput(spawned, parsed.options.input); +const setKillTimeout = (kill, signal, options, killResult) => { + if (!shouldForceKill(signal, options, killResult)) { + return; + } - spawned.all = makeAllStream(spawned, parsed.options); + const timeout = getForceKillAfterTimeout(options); + const t = setTimeout(() => { + kill('SIGKILL'); + }, timeout); - return mergePromise(spawned, handlePromiseOnce); + // Guarded because there's no `.unref()` when `execa` is used in the renderer + // process in Electron. This cannot be tested since we don't run tests in + // Electron. + // istanbul ignore else + if (t.unref) { + t.unref(); + } }; -module.exports = execa; - -module.exports.sync = (file, args, options) => { - const parsed = handleArgs(file, args, options); - const command = joinCommand(file, args); +const shouldForceKill = (signal, {forceKillAfterTimeout}, killResult) => { + return isSigterm(signal) && forceKillAfterTimeout !== false && killResult; +}; - validateInputSync(parsed.options); +const isSigterm = signal => { + return signal === os.constants.signals.SIGTERM || + (typeof signal === 'string' && signal.toUpperCase() === 'SIGTERM'); +}; - let result; - try { - result = childProcess.spawnSync(parsed.file, parsed.args, parsed.options); - } catch (error) { - throw makeError({ - error, - stdout: '', - stderr: '', - all: '', - command, - parsed, - timedOut: false, - isCanceled: false, - killed: false - }); +const getForceKillAfterTimeout = ({forceKillAfterTimeout = true}) => { + if (forceKillAfterTimeout === true) { + return DEFAULT_FORCE_KILL_TIMEOUT; } - const stdout = handleOutput(parsed.options, result.stdout, result.error); - const stderr = handleOutput(parsed.options, result.stderr, result.error); + if (!Number.isFinite(forceKillAfterTimeout) || forceKillAfterTimeout < 0) { + throw new TypeError(`Expected the \`forceKillAfterTimeout\` option to be a non-negative integer, got \`${forceKillAfterTimeout}\` (${typeof forceKillAfterTimeout})`); + } - if (result.error || result.status !== 0 || result.signal !== null) { - const error = makeError({ - stdout, - stderr, - error: result.error, - signal: result.signal, - exitCode: result.status, - command, - parsed, - timedOut: result.error && result.error.code === 'ETIMEDOUT', - isCanceled: false, - killed: result.signal !== null - }); + return forceKillAfterTimeout; +}; - if (!parsed.options.reject) { - return error; - } +// `childProcess.cancel()` +const spawnedCancel = (spawned, context) => { + const killResult = spawned.kill(); - throw error; + if (killResult) { + context.isCanceled = true; } - - return { - command, - exitCode: 0, - stdout, - stderr, - failed: false, - timedOut: false, - isCanceled: false, - killed: false - }; }; -module.exports.command = (command, options) => { - const [file, ...args] = parseCommand(command); - return execa(file, args, options); +const timeoutKill = (spawned, signal, reject) => { + spawned.kill(signal); + reject(Object.assign(new Error('Timed out'), {timedOut: true, signal})); }; -module.exports.commandSync = (command, options) => { - const [file, ...args] = parseCommand(command); - return execa.sync(file, args, options); -}; +// `timeout` option handling +const setupTimeout = (spawned, {timeout, killSignal = 'SIGTERM'}, spawnedPromise) => { + if (timeout === 0 || timeout === undefined) { + return spawnedPromise; + } -module.exports.node = (scriptPath, args, options = {}) => { - if (args && !Array.isArray(args) && typeof args === 'object') { - options = args; - args = []; + if (!Number.isFinite(timeout) || timeout < 0) { + throw new TypeError(`Expected the \`timeout\` option to be a non-negative integer, got \`${timeout}\` (${typeof timeout})`); } - const stdio = normalizeStdio.node(options); + let timeoutId; + const timeoutPromise = new Promise((resolve, reject) => { + timeoutId = setTimeout(() => { + timeoutKill(spawned, killSignal, reject); + }, timeout); + }); - const {nodePath = process.execPath, nodeOptions = process.execArgv} = options; + const safeSpawnedPromise = spawnedPromise.finally(() => { + clearTimeout(timeoutId); + }); - return execa( - nodePath, - [ - ...nodeOptions, - scriptPath, - ...(Array.isArray(args) ? args : []) - ], - { - ...options, - stdin: undefined, - stdout: undefined, - stderr: undefined, - stdio, - shell: false - } - ); + return Promise.race([timeoutPromise, safeSpawnedPromise]); }; +// `cleanup` option handling +const setExitHandler = async (spawned, {cleanup, detached}, timedPromise) => { + if (!cleanup || detached) { + return timedPromise; + } -/***/ }), -/* 237 */ -/***/ (function(module, exports) { + const removeExitHandler = onExit(() => { + spawned.kill(); + }); + + return timedPromise.finally(() => { + removeExitHandler(); + }); +}; + +module.exports = { + spawnedKill, + spawnedCancel, + setupTimeout, + setExitHandler +}; -module.exports = require("child_process"); /***/ }), -/* 238 */ +/* 254 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; +const isStream = __webpack_require__(255); +const getStream = __webpack_require__(256); +const mergeStream = __webpack_require__(260); -const cp = __webpack_require__(237); -const parse = __webpack_require__(239); -const enoent = __webpack_require__(250); +// `input` option +const handleInput = (spawned, input) => { + // Checking for stdin is workaround for https://github.com/nodejs/node/issues/26852 + // TODO: Remove `|| spawned.stdin === undefined` once we drop support for Node.js <=12.2.0 + if (input === undefined || spawned.stdin === undefined) { + return; + } -function spawn(command, args, options) { - // Parse the arguments - const parsed = parse(command, args, options); + if (isStream(input)) { + input.pipe(spawned.stdin); + } else { + spawned.stdin.end(input); + } +}; - // Spawn the child process - const spawned = cp.spawn(parsed.command, parsed.args, parsed.options); +// `all` interleaves `stdout` and `stderr` +const makeAllStream = (spawned, {all}) => { + if (!all || (!spawned.stdout && !spawned.stderr)) { + return; + } - // Hook into child process "exit" event to emit an error if the command - // does not exists, see: https://github.com/IndigoUnited/node-cross-spawn/issues/16 - enoent.hookChildProcess(spawned, parsed); + const mixed = mergeStream(); - return spawned; -} + if (spawned.stdout) { + mixed.add(spawned.stdout); + } -function spawnSync(command, args, options) { - // Parse the arguments - const parsed = parse(command, args, options); + if (spawned.stderr) { + mixed.add(spawned.stderr); + } - // Spawn the child process - const result = cp.spawnSync(parsed.command, parsed.args, parsed.options); + return mixed; +}; - // Analyze if the command does not exist, see: https://github.com/IndigoUnited/node-cross-spawn/issues/16 - result.error = result.error || enoent.verifyENOENTSync(result.status, parsed); +// On failure, `result.stdout|stderr|all` should contain the currently buffered stream +const getBufferedData = async (stream, streamPromise) => { + if (!stream) { + return; + } - return result; -} + stream.destroy(); -module.exports = spawn; -module.exports.spawn = spawn; -module.exports.sync = spawnSync; + try { + return await streamPromise; + } catch (error) { + return error.bufferedData; + } +}; + +const getStreamPromise = (stream, {encoding, buffer, maxBuffer}) => { + if (!stream || !buffer) { + return; + } + + if (encoding) { + return getStream(stream, {encoding, maxBuffer}); + } + + return getStream.buffer(stream, {maxBuffer}); +}; + +// Retrieve result of child process: exit code, signal, error, streams (stdout/stderr/all) +const getSpawnedResult = async ({stdout, stderr, all}, {encoding, buffer, maxBuffer}, processDone) => { + const stdoutPromise = getStreamPromise(stdout, {encoding, buffer, maxBuffer}); + const stderrPromise = getStreamPromise(stderr, {encoding, buffer, maxBuffer}); + const allPromise = getStreamPromise(all, {encoding, buffer, maxBuffer: maxBuffer * 2}); + + try { + return await Promise.all([processDone, stdoutPromise, stderrPromise, allPromise]); + } catch (error) { + return Promise.all([ + {error, signal: error.signal, timedOut: error.timedOut}, + getBufferedData(stdout, stdoutPromise), + getBufferedData(stderr, stderrPromise), + getBufferedData(all, allPromise) + ]); + } +}; + +const validateInputSync = ({input}) => { + if (isStream(input)) { + throw new TypeError('The `input` option cannot be a stream in sync mode'); + } +}; + +module.exports = { + handleInput, + makeAllStream, + getSpawnedResult, + validateInputSync +}; -module.exports._parse = parse; -module.exports._enoent = enoent; /***/ }), -/* 239 */ +/* 255 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const path = __webpack_require__(4); -const resolveCommand = __webpack_require__(240); -const escape = __webpack_require__(246); -const readShebang = __webpack_require__(247); +const isStream = stream => + stream !== null && + typeof stream === 'object' && + typeof stream.pipe === 'function'; -const isWin = process.platform === 'win32'; -const isExecutableRegExp = /\.(?:com|exe)$/i; -const isCmdShimRegExp = /node_modules[\\/].bin[\\/][^\\/]+\.cmd$/i; +isStream.writable = stream => + isStream(stream) && + stream.writable !== false && + typeof stream._write === 'function' && + typeof stream._writableState === 'object'; -function detectShebang(parsed) { - parsed.file = resolveCommand(parsed); +isStream.readable = stream => + isStream(stream) && + stream.readable !== false && + typeof stream._read === 'function' && + typeof stream._readableState === 'object'; - const shebang = parsed.file && readShebang(parsed.file); +isStream.duplex = stream => + isStream.writable(stream) && + isStream.readable(stream); - if (shebang) { - parsed.args.unshift(parsed.file); - parsed.command = shebang; +isStream.transform = stream => + isStream.duplex(stream) && + typeof stream._transform === 'function' && + typeof stream._transformState === 'object'; - return resolveCommand(parsed); - } +module.exports = isStream; - return parsed.file; -} -function parseNonShell(parsed) { - if (!isWin) { - return parsed; - } +/***/ }), +/* 256 */ +/***/ (function(module, exports, __webpack_require__) { - // Detect & add support for shebangs - const commandFile = detectShebang(parsed); +"use strict"; - // We don't need a shell if the command filename is an executable - const needsShell = !isExecutableRegExp.test(commandFile); +const pump = __webpack_require__(257); +const bufferStream = __webpack_require__(259); - // If a shell is required, use cmd.exe and take care of escaping everything correctly - // Note that `forceShell` is an hidden option used only in tests - if (parsed.options.forceShell || needsShell) { - // Need to double escape meta chars if the command is a cmd-shim located in `node_modules/.bin/` - // The cmd-shim simply calls execute the package bin file with NodeJS, proxying any argument - // Because the escape of metachars with ^ gets interpreted when the cmd.exe is first called, - // we need to double escape them - const needsDoubleEscapeMetaChars = isCmdShimRegExp.test(commandFile); +class MaxBufferError extends Error { + constructor() { + super('maxBuffer exceeded'); + this.name = 'MaxBufferError'; + } +} - // Normalize posix paths into OS compatible paths (e.g.: foo/bar -> foo\bar) - // This is necessary otherwise it will always fail with ENOENT in those cases - parsed.command = path.normalize(parsed.command); +async function getStream(inputStream, options) { + if (!inputStream) { + return Promise.reject(new Error('Expected a stream')); + } - // Escape command & arguments - parsed.command = escape.command(parsed.command); - parsed.args = parsed.args.map((arg) => escape.argument(arg, needsDoubleEscapeMetaChars)); + options = { + maxBuffer: Infinity, + ...options + }; - const shellCommand = [parsed.command].concat(parsed.args).join(' '); + const {maxBuffer} = options; - parsed.args = ['/d', '/s', '/c', `"${shellCommand}"`]; - parsed.command = process.env.comspec || 'cmd.exe'; - parsed.options.windowsVerbatimArguments = true; // Tell node's spawn that the arguments are already escaped - } + let stream; + await new Promise((resolve, reject) => { + const rejectPromise = error => { + if (error) { // A null check + error.bufferedData = stream.getBufferedValue(); + } - return parsed; -} + reject(error); + }; -function parse(command, args, options) { - // Normalize arguments, similar to nodejs - if (args && !Array.isArray(args)) { - options = args; - args = null; - } + stream = pump(inputStream, bufferStream(options), error => { + if (error) { + rejectPromise(error); + return; + } - args = args ? args.slice(0) : []; // Clone array to avoid changing the original - options = Object.assign({}, options); // Clone object to avoid changing the original + resolve(); + }); - // Build our parsed object - const parsed = { - command, - args, - options, - file: undefined, - original: { - command, - args, - }, - }; + stream.on('data', () => { + if (stream.getBufferedLength() > maxBuffer) { + rejectPromise(new MaxBufferError()); + } + }); + }); - // Delegate further parsing to shell or non-shell - return options.shell ? parsed : parseNonShell(parsed); + return stream.getBufferedValue(); } -module.exports = parse; +module.exports = getStream; +// TODO: Remove this for the next major release +module.exports.default = getStream; +module.exports.buffer = (stream, options) => getStream(stream, {...options, encoding: 'buffer'}); +module.exports.array = (stream, options) => getStream(stream, {...options, array: true}); +module.exports.MaxBufferError = MaxBufferError; /***/ }), -/* 240 */ +/* 257 */ /***/ (function(module, exports, __webpack_require__) { -"use strict"; +var once = __webpack_require__(162) +var eos = __webpack_require__(258) +var fs = __webpack_require__(134) // we only need fs to get the ReadStream and WriteStream prototypes +var noop = function () {} +var ancient = /^v?\.0/.test(process.version) -const path = __webpack_require__(4); -const which = __webpack_require__(241); -const pathKey = __webpack_require__(245)(); +var isFn = function (fn) { + return typeof fn === 'function' +} -function resolveCommandAttempt(parsed, withoutPathExt) { - const cwd = process.cwd(); - const hasCustomCwd = parsed.options.cwd != null; - // Worker threads do not have process.chdir() - const shouldSwitchCwd = hasCustomCwd && process.chdir !== undefined; +var isFS = function (stream) { + if (!ancient) return false // newer node version do not need to care about fs is a special way + if (!fs) return false // browser + return (stream instanceof (fs.ReadStream || noop) || stream instanceof (fs.WriteStream || noop)) && isFn(stream.close) +} - // If a custom `cwd` was specified, we need to change the process cwd - // because `which` will do stat calls but does not support a custom cwd - if (shouldSwitchCwd) { - try { - process.chdir(parsed.options.cwd); - } catch (err) { - /* Empty */ - } - } +var isRequest = function (stream) { + return stream.setHeader && isFn(stream.abort) +} - let resolved; +var destroyer = function (stream, reading, writing, callback) { + callback = once(callback) - try { - resolved = which.sync(parsed.command, { - path: (parsed.options.env || process.env)[pathKey], - pathExt: withoutPathExt ? path.delimiter : undefined, - }); - } catch (e) { - /* Empty */ - } finally { - if (shouldSwitchCwd) { - process.chdir(cwd); - } - } + var closed = false + stream.on('close', function () { + closed = true + }) - // If we successfully resolved, ensure that an absolute path is returned - // Note that when a custom `cwd` was used, we need to resolve to an absolute path based on it - if (resolved) { - resolved = path.resolve(hasCustomCwd ? parsed.options.cwd : '', resolved); - } + eos(stream, {readable: reading, writable: writing}, function (err) { + if (err) return callback(err) + closed = true + callback() + }) - return resolved; + var destroyed = false + return function (err) { + if (closed) return + if (destroyed) return + destroyed = true + + if (isFS(stream)) return stream.close(noop) // use close for fs streams to avoid fd leaks + if (isRequest(stream)) return stream.abort() // request.destroy just do .end - .abort is what we want + + if (isFn(stream.destroy)) return stream.destroy() + + callback(err || new Error('stream was destroyed')) + } } -function resolveCommand(parsed) { - return resolveCommandAttempt(parsed) || resolveCommandAttempt(parsed, true); +var call = function (fn) { + fn() } -module.exports = resolveCommand; +var pipe = function (from, to) { + return from.pipe(to) +} + +var pump = function () { + var streams = Array.prototype.slice.call(arguments) + var callback = isFn(streams[streams.length - 1] || noop) && streams.pop() || noop + if (Array.isArray(streams[0])) streams = streams[0] + if (streams.length < 2) throw new Error('pump requires two streams per minimum') -/***/ }), -/* 241 */ -/***/ (function(module, exports, __webpack_require__) { + var error + var destroys = streams.map(function (stream, i) { + var reading = i < streams.length - 1 + var writing = i > 0 + return destroyer(stream, reading, writing, function (err) { + if (!error) error = err + if (err) destroys.forEach(call) + if (reading) return + destroys.forEach(call) + callback(error) + }) + }) -const isWindows = process.platform === 'win32' || - process.env.OSTYPE === 'cygwin' || - process.env.OSTYPE === 'msys' + return streams.reduce(pipe) +} -const path = __webpack_require__(4) -const COLON = isWindows ? ';' : ':' -const isexe = __webpack_require__(242) +module.exports = pump -const getNotFoundError = (cmd) => - Object.assign(new Error(`not found: ${cmd}`), { code: 'ENOENT' }) -const getPathInfo = (cmd, opt) => { - const colon = opt.colon || COLON +/***/ }), +/* 258 */ +/***/ (function(module, exports, __webpack_require__) { - // If it has a slash, then we don't bother searching the pathenv. - // just check the file itself, and that's it. - const pathEnv = cmd.match(/\//) || isWindows && cmd.match(/\\/) ? [''] - : ( - [ - // windows always checks the cwd first - ...(isWindows ? [process.cwd()] : []), - ...(opt.path || process.env.PATH || - /* istanbul ignore next: very unusual */ '').split(colon), - ] - ) - const pathExtExe = isWindows - ? opt.pathExt || process.env.PATHEXT || '.EXE;.CMD;.BAT;.COM' - : '' - const pathExt = isWindows ? pathExtExe.split(colon) : [''] +var once = __webpack_require__(162); - if (isWindows) { - if (cmd.indexOf('.') !== -1 && pathExt[0] !== '') - pathExt.unshift('') - } +var noop = function() {}; - return { - pathEnv, - pathExt, - pathExtExe, - } -} +var isRequest = function(stream) { + return stream.setHeader && typeof stream.abort === 'function'; +}; -const which = (cmd, opt, cb) => { - if (typeof opt === 'function') { - cb = opt - opt = {} - } - if (!opt) - opt = {} +var isChildProcess = function(stream) { + return stream.stdio && Array.isArray(stream.stdio) && stream.stdio.length === 3 +}; - const { pathEnv, pathExt, pathExtExe } = getPathInfo(cmd, opt) - const found = [] +var eos = function(stream, opts, callback) { + if (typeof opts === 'function') return eos(stream, null, opts); + if (!opts) opts = {}; - const step = i => new Promise((resolve, reject) => { - if (i === pathEnv.length) - return opt.all && found.length ? resolve(found) - : reject(getNotFoundError(cmd)) + callback = once(callback || noop); - const ppRaw = pathEnv[i] - const pathPart = /^".*"$/.test(ppRaw) ? ppRaw.slice(1, -1) : ppRaw + var ws = stream._writableState; + var rs = stream._readableState; + var readable = opts.readable || (opts.readable !== false && stream.readable); + var writable = opts.writable || (opts.writable !== false && stream.writable); + var cancelled = false; - const pCmd = path.join(pathPart, cmd) - const p = !pathPart && /^\.[\\\/]/.test(cmd) ? cmd.slice(0, 2) + pCmd - : pCmd + var onlegacyfinish = function() { + if (!stream.writable) onfinish(); + }; - resolve(subStep(p, i, 0)) - }) + var onfinish = function() { + writable = false; + if (!readable) callback.call(stream); + }; - const subStep = (p, i, ii) => new Promise((resolve, reject) => { - if (ii === pathExt.length) - return resolve(step(i + 1)) - const ext = pathExt[ii] - isexe(p + ext, { pathExt: pathExtExe }, (er, is) => { - if (!er && is) { - if (opt.all) - found.push(p + ext) - else - return resolve(p + ext) - } - return resolve(subStep(p, i, ii + 1)) - }) - }) + var onend = function() { + readable = false; + if (!writable) callback.call(stream); + }; - return cb ? step(0).then(res => cb(null, res), cb) : step(0) -} + var onexit = function(exitCode) { + callback.call(stream, exitCode ? new Error('exited with error code: ' + exitCode) : null); + }; -const whichSync = (cmd, opt) => { - opt = opt || {} + var onerror = function(err) { + callback.call(stream, err); + }; - const { pathEnv, pathExt, pathExtExe } = getPathInfo(cmd, opt) - const found = [] + var onclose = function() { + process.nextTick(onclosenexttick); + }; - for (let i = 0; i < pathEnv.length; i ++) { - const ppRaw = pathEnv[i] - const pathPart = /^".*"$/.test(ppRaw) ? ppRaw.slice(1, -1) : ppRaw + var onclosenexttick = function() { + if (cancelled) return; + if (readable && !(rs && (rs.ended && !rs.destroyed))) return callback.call(stream, new Error('premature close')); + if (writable && !(ws && (ws.ended && !ws.destroyed))) return callback.call(stream, new Error('premature close')); + }; - const pCmd = path.join(pathPart, cmd) - const p = !pathPart && /^\.[\\\/]/.test(cmd) ? cmd.slice(0, 2) + pCmd - : pCmd + var onrequest = function() { + stream.req.on('finish', onfinish); + }; - for (let j = 0; j < pathExt.length; j ++) { - const cur = p + pathExt[j] - try { - const is = isexe.sync(cur, { pathExt: pathExtExe }) - if (is) { - if (opt.all) - found.push(cur) - else - return cur - } - } catch (ex) {} - } - } + if (isRequest(stream)) { + stream.on('complete', onfinish); + stream.on('abort', onclose); + if (stream.req) onrequest(); + else stream.on('request', onrequest); + } else if (writable && !ws) { // legacy streams + stream.on('end', onlegacyfinish); + stream.on('close', onlegacyfinish); + } - if (opt.all && found.length) - return found + if (isChildProcess(stream)) stream.on('exit', onexit); - if (opt.nothrow) - return null + stream.on('end', onend); + stream.on('finish', onfinish); + if (opts.error !== false) stream.on('error', onerror); + stream.on('close', onclose); - throw getNotFoundError(cmd) -} + return function() { + cancelled = true; + stream.removeListener('complete', onfinish); + stream.removeListener('abort', onclose); + stream.removeListener('request', onrequest); + if (stream.req) stream.req.removeListener('finish', onfinish); + stream.removeListener('end', onlegacyfinish); + stream.removeListener('close', onlegacyfinish); + stream.removeListener('finish', onfinish); + stream.removeListener('exit', onexit); + stream.removeListener('end', onend); + stream.removeListener('error', onerror); + stream.removeListener('close', onclose); + }; +}; -module.exports = which -which.sync = whichSync +module.exports = eos; /***/ }), -/* 242 */ +/* 259 */ /***/ (function(module, exports, __webpack_require__) { -var fs = __webpack_require__(133) -var core -if (process.platform === 'win32' || global.TESTING_WINDOWS) { - core = __webpack_require__(243) -} else { - core = __webpack_require__(244) -} +"use strict"; -module.exports = isexe -isexe.sync = sync +const {PassThrough: PassThroughStream} = __webpack_require__(138); -function isexe (path, options, cb) { - if (typeof options === 'function') { - cb = options - options = {} - } +module.exports = options => { + options = {...options}; - if (!cb) { - if (typeof Promise !== 'function') { - throw new TypeError('callback not provided') - } + const {array} = options; + let {encoding} = options; + const isBuffer = encoding === 'buffer'; + let objectMode = false; - return new Promise(function (resolve, reject) { - isexe(path, options || {}, function (er, is) { - if (er) { - reject(er) - } else { - resolve(is) - } - }) - }) - } + if (array) { + objectMode = !(encoding || isBuffer); + } else { + encoding = encoding || 'utf8'; + } - core(path, options || {}, function (er, is) { - // ignore EACCES because that just means we aren't allowed to run it - if (er) { - if (er.code === 'EACCES' || options && options.ignoreErrors) { - er = null - is = false - } - } - cb(er, is) - }) -} + if (isBuffer) { + encoding = null; + } -function sync (path, options) { - // my kingdom for a filtered catch - try { - return core.sync(path, options || {}) - } catch (er) { - if (options && options.ignoreErrors || er.code === 'EACCES') { - return false - } else { - throw er - } - } -} - - -/***/ }), -/* 243 */ -/***/ (function(module, exports, __webpack_require__) { + const stream = new PassThroughStream({objectMode}); -module.exports = isexe -isexe.sync = sync + if (encoding) { + stream.setEncoding(encoding); + } -var fs = __webpack_require__(133) + let length = 0; + const chunks = []; -function checkPathExt (path, options) { - var pathext = options.pathExt !== undefined ? - options.pathExt : process.env.PATHEXT + stream.on('data', chunk => { + chunks.push(chunk); - if (!pathext) { - return true - } + if (objectMode) { + length = chunks.length; + } else { + length += chunk.length; + } + }); - pathext = pathext.split(';') - if (pathext.indexOf('') !== -1) { - return true - } - for (var i = 0; i < pathext.length; i++) { - var p = pathext[i].toLowerCase() - if (p && path.substr(-p.length).toLowerCase() === p) { - return true - } - } - return false -} + stream.getBufferedValue = () => { + if (array) { + return chunks; + } -function checkStat (stat, path, options) { - if (!stat.isSymbolicLink() && !stat.isFile()) { - return false - } - return checkPathExt(path, options) -} + return isBuffer ? Buffer.concat(chunks, length) : chunks.join(''); + }; -function isexe (path, options, cb) { - fs.stat(path, function (er, stat) { - cb(er, er ? false : checkStat(stat, path, options)) - }) -} + stream.getBufferedLength = () => length; -function sync (path, options) { - return checkStat(fs.statSync(path), path, options) -} + return stream; +}; /***/ }), -/* 244 */ +/* 260 */ /***/ (function(module, exports, __webpack_require__) { -module.exports = isexe -isexe.sync = sync +"use strict"; -var fs = __webpack_require__(133) -function isexe (path, options, cb) { - fs.stat(path, function (er, stat) { - cb(er, er ? false : checkStat(stat, options)) - }) -} +const { PassThrough } = __webpack_require__(138); -function sync (path, options) { - return checkStat(fs.statSync(path), options) -} +module.exports = function (/*streams...*/) { + var sources = [] + var output = new PassThrough({objectMode: true}) -function checkStat (stat, options) { - return stat.isFile() && checkMode(stat, options) -} + output.setMaxListeners(0) -function checkMode (stat, options) { - var mod = stat.mode - var uid = stat.uid - var gid = stat.gid + output.add = add + output.isEmpty = isEmpty - var myUid = options.uid !== undefined ? - options.uid : process.getuid && process.getuid() - var myGid = options.gid !== undefined ? - options.gid : process.getgid && process.getgid() + output.on('unpipe', remove) - var u = parseInt('100', 8) - var g = parseInt('010', 8) - var o = parseInt('001', 8) - var ug = u | g + Array.prototype.slice.call(arguments).forEach(add) - var ret = (mod & o) || - (mod & g) && gid === myGid || - (mod & u) && uid === myUid || - (mod & ug) && myUid === 0 + return output - return ret + function add (source) { + if (Array.isArray(source)) { + source.forEach(add) + return this + } + + sources.push(source); + source.once('end', remove.bind(null, source)) + source.once('error', output.emit.bind(output, 'error')) + source.pipe(output, {end: false}) + return this + } + + function isEmpty () { + return sources.length == 0; + } + + function remove (source) { + sources = sources.filter(function (it) { return it !== source }) + if (!sources.length && output.readable) { output.end() } + } } /***/ }), -/* 245 */ +/* 261 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const pathKey = (options = {}) => { - const environment = options.env || process.env; - const platform = options.platform || process.platform; +const nativePromisePrototype = (async () => {})().constructor.prototype; +const descriptors = ['then', 'catch', 'finally'].map(property => [ + property, + Reflect.getOwnPropertyDescriptor(nativePromisePrototype, property) +]); - if (platform !== 'win32') { - return 'PATH'; +// The return value is a mixin of `childProcess` and `Promise` +const mergePromise = (spawned, promise) => { + for (const [property, descriptor] of descriptors) { + // Starting the main `promise` is deferred to avoid consuming streams + const value = typeof promise === 'function' ? + (...args) => Reflect.apply(descriptor.value, promise(), args) : + descriptor.value.bind(promise); + + Reflect.defineProperty(spawned, property, {...descriptor, value}); } - return Object.keys(environment).find(key => key.toUpperCase() === 'PATH') || 'Path'; + return spawned; +}; + +// Use promises instead of `child_process` events +const getSpawnedPromise = spawned => { + return new Promise((resolve, reject) => { + spawned.on('exit', (exitCode, signal) => { + resolve({exitCode, signal}); + }); + + spawned.on('error', error => { + reject(error); + }); + + if (spawned.stdin) { + spawned.stdin.on('error', error => { + reject(error); + }); + } + }); +}; + +module.exports = { + mergePromise, + getSpawnedPromise }; -module.exports = pathKey; -// TODO: Remove this for the next major release -module.exports.default = pathKey; /***/ }), -/* 246 */ +/* 262 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; +const SPACES_REGEXP = / +/g; -// See http://www.robvanderwoude.com/escapechars.php -const metaCharsRegExp = /([()\][%!^"`<>&|;, *?])/g; - -function escapeCommand(arg) { - // Escape meta chars - arg = arg.replace(metaCharsRegExp, '^$1'); +const joinCommand = (file, args = []) => { + if (!Array.isArray(args)) { + return file; + } - return arg; -} + return [file, ...args].join(' '); +}; -function escapeArgument(arg, doubleEscapeMetaChars) { - // Convert to string - arg = `${arg}`; +// Allow spaces to be escaped by a backslash if not meant as a delimiter +const handleEscaping = (tokens, token, index) => { + if (index === 0) { + return [token]; + } - // Algorithm below is based on https://qntm.org/cmd + const previousToken = tokens[tokens.length - 1]; - // Sequence of backslashes followed by a double quote: - // double up all the backslashes and escape the double quote - arg = arg.replace(/(\\*)"/g, '$1$1\\"'); + if (previousToken.endsWith('\\')) { + return [...tokens.slice(0, -1), `${previousToken.slice(0, -1)} ${token}`]; + } - // Sequence of backslashes followed by the end of the string - // (which will become a double quote later): - // double up all the backslashes - arg = arg.replace(/(\\*)$/, '$1$1'); + return [...tokens, token]; +}; - // All other backslashes occur literally +// Handle `execa.command()` +const parseCommand = command => { + return command + .trim() + .split(SPACES_REGEXP) + .reduce(handleEscaping, []); +}; - // Quote the whole thing: - arg = `"${arg}"`; +module.exports = { + joinCommand, + parseCommand +}; - // Escape meta chars - arg = arg.replace(metaCharsRegExp, '^$1'); - // Double escape meta chars if necessary - if (doubleEscapeMetaChars) { - arg = arg.replace(metaCharsRegExp, '^$1'); - } +/***/ }), +/* 263 */ +/***/ (function(module, exports, __webpack_require__) { - return arg; -} +// Copyright IBM Corp. 2014,2018. All Rights Reserved. +// Node module: strong-log-transformer +// This file is licensed under the Apache License 2.0. +// License text available at https://opensource.org/licenses/Apache-2.0 -module.exports.command = escapeCommand; -module.exports.argument = escapeArgument; +module.exports = __webpack_require__(264); +module.exports.cli = __webpack_require__(268); /***/ }), -/* 247 */ +/* 264 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; +// Copyright IBM Corp. 2014,2018. All Rights Reserved. +// Node module: strong-log-transformer +// This file is licensed under the Apache License 2.0. +// License text available at https://opensource.org/licenses/Apache-2.0 -const fs = __webpack_require__(133); -const shebangCommand = __webpack_require__(248); -function readShebang(command) { - // Read the first 150 bytes from the file - const size = 150; - const buffer = Buffer.alloc(size); +var stream = __webpack_require__(138); +var util = __webpack_require__(112); +var fs = __webpack_require__(134); - let fd; +var through = __webpack_require__(265); +var duplexer = __webpack_require__(266); +var StringDecoder = __webpack_require__(267).StringDecoder; - try { - fd = fs.openSync(command, 'r'); - fs.readSync(fd, buffer, 0, size, 0); - fs.closeSync(fd); - } catch (e) { /* Empty */ } +module.exports = Logger; - // Attempt to extract shebang (null is returned if not a shebang) - return shebangCommand(buffer.toString()); -} +Logger.DEFAULTS = { + format: 'text', + tag: '', + mergeMultiline: false, + timeStamp: false, +}; -module.exports = readShebang; +var formatters = { + text: textFormatter, + json: jsonFormatter, +} +function Logger(options) { + var defaults = JSON.parse(JSON.stringify(Logger.DEFAULTS)); + options = util._extend(defaults, options || {}); + var catcher = deLiner(); + var emitter = catcher; + var transforms = [ + objectifier(), + ]; -/***/ }), -/* 248 */ -/***/ (function(module, exports, __webpack_require__) { + if (options.tag) { + transforms.push(staticTagger(options.tag)); + } -"use strict"; + if (options.mergeMultiline) { + transforms.push(lineMerger()); + } -const shebangRegex = __webpack_require__(249); + // TODO + // if (options.pidStamp) { + // transforms.push(pidStamper(options.pid)); + // } -module.exports = (string = '') => { - const match = string.match(shebangRegex); + // TODO + // if (options.workerStamp) { + // transforms.push(workerStamper(options.worker)); + // } - if (!match) { - return null; - } + transforms.push(formatters[options.format](options)); - const [path, argument] = match[0].replace(/#! ?/, '').split(' '); - const binary = path.split('/').pop(); + // restore line endings that were removed by line splitting + transforms.push(reLiner()); - if (binary === 'env') { - return argument; - } + for (var t in transforms) { + emitter = emitter.pipe(transforms[t]); + } - return argument ? `${binary} ${argument}` : binary; -}; + return duplexer(catcher, emitter); +} +function deLiner() { + var decoder = new StringDecoder('utf8'); + var last = ''; -/***/ }), -/* 249 */ -/***/ (function(module, exports, __webpack_require__) { + return new stream.Transform({ + transform(chunk, _enc, callback) { + last += decoder.write(chunk); + var list = last.split(/\r\n|[\n\v\f\r\x85\u2028\u2029]/g); + last = list.pop(); + for (var i = 0; i < list.length; i++) { + // swallow empty lines + if (list[i]) { + this.push(list[i]); + } + } + callback(); + }, + flush(callback) { + // incomplete UTF8 sequences become UTF8 replacement characters + last += decoder.end(); + if (last) { + this.push(last); + } + callback(); + }, + }); +} -"use strict"; +function reLiner() { + return through(appendNewline); -module.exports = /^#!(.*)/; + function appendNewline(line) { + this.emit('data', line + '\n'); + } +} +function objectifier() { + return through(objectify, null, {autoDestroy: false}); -/***/ }), -/* 250 */ -/***/ (function(module, exports, __webpack_require__) { + function objectify(line) { + this.emit('data', { + msg: line, + time: Date.now(), + }); + } +} -"use strict"; +function staticTagger(tag) { + return through(tagger); + function tagger(logEvent) { + logEvent.tag = tag; + this.emit('data', logEvent); + } +} -const isWin = process.platform === 'win32'; +function textFormatter(options) { + return through(textify); -function notFoundError(original, syscall) { - return Object.assign(new Error(`${syscall} ${original.command} ENOENT`), { - code: 'ENOENT', - errno: 'ENOENT', - syscall: `${syscall} ${original.command}`, - path: original.command, - spawnargs: original.args, - }); -} + function textify(logEvent) { + var line = util.format('%s%s', textifyTags(logEvent.tag), + logEvent.msg.toString()); + if (options.timeStamp) { + line = util.format('%s %s', new Date(logEvent.time).toISOString(), line); + } + this.emit('data', line.replace(/\n/g, '\\n')); + } -function hookChildProcess(cp, parsed) { - if (!isWin) { - return; + function textifyTags(tags) { + var str = ''; + if (typeof tags === 'string') { + str = tags + ' '; + } else if (typeof tags === 'object') { + for (var t in tags) { + str += t + ':' + tags[t] + ' '; + } } + return str; + } +} - const originalEmit = cp.emit; +function jsonFormatter(options) { + return through(jsonify); - cp.emit = function (name, arg1) { - // If emitting "exit" event and exit code is 1, we need to check if - // the command exists and emit an "error" instead - // See https://github.com/IndigoUnited/node-cross-spawn/issues/16 - if (name === 'exit') { - const err = verifyENOENT(arg1, parsed, 'spawn'); + function jsonify(logEvent) { + if (options.timeStamp) { + logEvent.time = new Date(logEvent.time).toISOString(); + } else { + delete logEvent.time; + } + logEvent.msg = logEvent.msg.toString(); + this.emit('data', JSON.stringify(logEvent)); + } +} - if (err) { - return originalEmit.call(cp, 'error', err); - } - } +function lineMerger(host) { + var previousLine = null; + var flushTimer = null; + var stream = through(lineMergerWrite, lineMergerEnd); + var flush = _flush.bind(stream); - return originalEmit.apply(cp, arguments); // eslint-disable-line prefer-rest-params - }; -} + return stream; -function verifyENOENT(status, parsed) { - if (isWin && status === 1 && !parsed.file) { - return notFoundError(parsed.original, 'spawn'); + function lineMergerWrite(line) { + if (/^\s+/.test(line.msg)) { + if (previousLine) { + previousLine.msg += '\n' + line.msg; + } else { + previousLine = line; + } + } else { + flush(); + previousLine = line; } + // rolling timeout + clearTimeout(flushTimer); + flushTimer = setTimeout(flush.bind(this), 10); + } - return null; -} - -function verifyENOENTSync(status, parsed) { - if (isWin && status === 1 && !parsed.file) { - return notFoundError(parsed.original, 'spawnSync'); + function _flush() { + if (previousLine) { + this.emit('data', previousLine); + previousLine = null; } + } - return null; + function lineMergerEnd() { + flush.call(this); + this.emit('end'); + } } -module.exports = { - hookChildProcess, - verifyENOENT, - verifyENOENTSync, - notFoundError, -}; - /***/ }), -/* 251 */ +/* 265 */ /***/ (function(module, exports, __webpack_require__) { -"use strict"; +var Stream = __webpack_require__(138) +// through +// +// a stream that does nothing but re-emit the input. +// useful for aggregating a series of changing but not ending streams into one stream) -module.exports = input => { - const LF = typeof input === 'string' ? '\n' : '\n'.charCodeAt(); - const CR = typeof input === 'string' ? '\r' : '\r'.charCodeAt(); +exports = module.exports = through +through.through = through - if (input[input.length - 1] === LF) { - input = input.slice(0, input.length - 1); - } - - if (input[input.length - 1] === CR) { - input = input.slice(0, input.length - 1); - } - - return input; -}; +//create a readable writable stream. +function through (write, end, opts) { + write = write || function (data) { this.queue(data) } + end = end || function () { this.queue(null) } -/***/ }), -/* 252 */ -/***/ (function(module, exports, __webpack_require__) { + var ended = false, destroyed = false, buffer = [], _ended = false + var stream = new Stream() + stream.readable = stream.writable = true + stream.paused = false -"use strict"; +// stream.autoPause = !(opts && opts.autoPause === false) + stream.autoDestroy = !(opts && opts.autoDestroy === false) -const path = __webpack_require__(4); -const pathKey = __webpack_require__(245); + stream.write = function (data) { + write.call(this, data) + return !stream.paused + } -const npmRunPath = options => { - options = { - cwd: process.cwd(), - path: process.env[pathKey()], - execPath: process.execPath, - ...options - }; + function drain() { + while(buffer.length && !stream.paused) { + var data = buffer.shift() + if(null === data) + return stream.emit('end') + else + stream.emit('data', data) + } + } - let previous; - let cwdPath = path.resolve(options.cwd); - const result = []; + stream.queue = stream.push = function (data) { +// console.error(ended) + if(_ended) return stream + if(data === null) _ended = true + buffer.push(data) + drain() + return stream + } - while (previous !== cwdPath) { - result.push(path.join(cwdPath, 'node_modules/.bin')); - previous = cwdPath; - cwdPath = path.resolve(cwdPath, '..'); - } + //this will be registered as the first 'end' listener + //must call destroy next tick, to make sure we're after any + //stream piped from here. + //this is only a problem if end is not emitted synchronously. + //a nicer way to do this is to make sure this is the last listener for 'end' - // Ensure the running `node` binary is used - const execPathDir = path.resolve(options.cwd, options.execPath, '..'); - result.push(execPathDir); + stream.on('end', function () { + stream.readable = false + if(!stream.writable && stream.autoDestroy) + process.nextTick(function () { + stream.destroy() + }) + }) - return result.concat(options.path).join(path.delimiter); -}; + function _end () { + stream.writable = false + end.call(stream) + if(!stream.readable && stream.autoDestroy) + stream.destroy() + } -module.exports = npmRunPath; -// TODO: Remove this for the next major release -module.exports.default = npmRunPath; + stream.end = function (data) { + if(ended) return + ended = true + if(arguments.length) stream.write(data) + _end() // will emit or queue + return stream + } -module.exports.env = options => { - options = { - env: process.env, - ...options - }; + stream.destroy = function () { + if(destroyed) return + destroyed = true + ended = true + buffer.length = 0 + stream.writable = stream.readable = false + stream.emit('close') + return stream + } - const env = {...options.env}; - const path = pathKey({env}); + stream.pause = function () { + if(stream.paused) return + stream.paused = true + return stream + } - options.path = env[path]; - env[path] = module.exports(options); + stream.resume = function () { + if(stream.paused) { + stream.paused = false + stream.emit('resume') + } + drain() + //may have become paused again, + //as drain emits 'data'. + if(!stream.paused) + stream.emit('drain') + return stream + } + return stream +} - return env; -}; /***/ }), -/* 253 */ +/* 266 */ /***/ (function(module, exports, __webpack_require__) { -"use strict"; - -const mimicFn = __webpack_require__(254); +var Stream = __webpack_require__(138) +var writeMethods = ["write", "end", "destroy"] +var readMethods = ["resume", "pause"] +var readEvents = ["data", "close"] +var slice = Array.prototype.slice -const calledFunctions = new WeakMap(); +module.exports = duplex -const oneTime = (fn, options = {}) => { - if (typeof fn !== 'function') { - throw new TypeError('Expected a function'); - } +function forEach (arr, fn) { + if (arr.forEach) { + return arr.forEach(fn) + } - let ret; - let isCalled = false; - let callCount = 0; - const functionName = fn.displayName || fn.name || ''; + for (var i = 0; i < arr.length; i++) { + fn(arr[i], i) + } +} - const onetime = function (...args) { - calledFunctions.set(onetime, ++callCount); +function duplex(writer, reader) { + var stream = new Stream() + var ended = false - if (isCalled) { - if (options.throw === true) { - throw new Error(`Function \`${functionName}\` can only be called once`); - } + forEach(writeMethods, proxyWriter) - return ret; - } + forEach(readMethods, proxyReader) - isCalled = true; - ret = fn.apply(this, args); - fn = null; + forEach(readEvents, proxyStream) - return ret; - }; + reader.on("end", handleEnd) - mimicFn(onetime, fn); - calledFunctions.set(onetime, callCount); + writer.on("drain", function() { + stream.emit("drain") + }) - return onetime; -}; + writer.on("error", reemit) + reader.on("error", reemit) -module.exports = oneTime; -// TODO: Remove this for the next major release -module.exports.default = oneTime; + stream.writable = writer.writable + stream.readable = reader.readable -module.exports.callCount = fn => { - if (!calledFunctions.has(fn)) { - throw new Error(`The given function \`${fn.name}\` is not wrapped by the \`onetime\` package`); - } + return stream - return calledFunctions.get(fn); -}; + function proxyWriter(methodName) { + stream[methodName] = method + function method() { + return writer[methodName].apply(writer, arguments) + } + } -/***/ }), -/* 254 */ -/***/ (function(module, exports, __webpack_require__) { + function proxyReader(methodName) { + stream[methodName] = method -"use strict"; + function method() { + stream.emit(methodName) + var func = reader[methodName] + if (func) { + return func.apply(reader, arguments) + } + reader.emit(methodName) + } + } + function proxyStream(methodName) { + reader.on(methodName, reemit) -const mimicFn = (to, from) => { - for (const prop of Reflect.ownKeys(from)) { - Object.defineProperty(to, prop, Object.getOwnPropertyDescriptor(from, prop)); - } + function reemit() { + var args = slice.call(arguments) + args.unshift(methodName) + stream.emit.apply(stream, args) + } + } - return to; -}; + function handleEnd() { + if (ended) { + return + } + ended = true + var args = slice.call(arguments) + args.unshift("end") + stream.emit.apply(stream, args) + } -module.exports = mimicFn; -// TODO: Remove this for the next major release -module.exports.default = mimicFn; + function reemit(err) { + stream.emit("error", err) + } +} /***/ }), -/* 255 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - -const {signalsByName} = __webpack_require__(256); - -const getErrorPrefix = ({timedOut, timeout, errorCode, signal, signalDescription, exitCode, isCanceled}) => { - if (timedOut) { - return `timed out after ${timeout} milliseconds`; - } - - if (isCanceled) { - return 'was canceled'; - } - - if (errorCode !== undefined) { - return `failed with ${errorCode}`; - } - - if (signal !== undefined) { - return `was killed with ${signal} (${signalDescription})`; - } - - if (exitCode !== undefined) { - return `failed with exit code ${exitCode}`; - } - - return 'failed'; -}; - -const makeError = ({ - stdout, - stderr, - all, - error, - signal, - exitCode, - command, - timedOut, - isCanceled, - killed, - parsed: {options: {timeout}} -}) => { - // `signal` and `exitCode` emitted on `spawned.on('exit')` event can be `null`. - // We normalize them to `undefined` - exitCode = exitCode === null ? undefined : exitCode; - signal = signal === null ? undefined : signal; - const signalDescription = signal === undefined ? undefined : signalsByName[signal].description; - - const errorCode = error && error.code; - - const prefix = getErrorPrefix({timedOut, timeout, errorCode, signal, signalDescription, exitCode, isCanceled}); - const execaMessage = `Command ${prefix}: ${command}`; - const isError = Object.prototype.toString.call(error) === '[object Error]'; - const shortMessage = isError ? `${execaMessage}\n${error.message}` : execaMessage; - const message = [shortMessage, stderr, stdout].filter(Boolean).join('\n'); - - if (isError) { - error.originalMessage = error.message; - error.message = message; - } else { - error = new Error(message); - } - - error.shortMessage = shortMessage; - error.command = command; - error.exitCode = exitCode; - error.signal = signal; - error.signalDescription = signalDescription; - error.stdout = stdout; - error.stderr = stderr; - - if (all !== undefined) { - error.all = all; - } - - if ('bufferedData' in error) { - delete error.bufferedData; - } - - error.failed = true; - error.timedOut = Boolean(timedOut); - error.isCanceled = isCanceled; - error.killed = killed && !timedOut; - - return error; -}; - -module.exports = makeError; +/* 267 */ +/***/ (function(module, exports) { +module.exports = require("string_decoder"); /***/ }), -/* 256 */ +/* 268 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -Object.defineProperty(exports,"__esModule",{value:true});exports.signalsByNumber=exports.signalsByName=void 0;var _os=__webpack_require__(120); - -var _signals=__webpack_require__(257); -var _realtime=__webpack_require__(259); - - - -const getSignalsByName=function(){ -const signals=(0,_signals.getSignals)(); -return signals.reduce(getSignalByName,{}); -}; - -const getSignalByName=function( -signalByNameMemo, -{name,number,description,supported,action,forced,standard}) -{ -return{ -...signalByNameMemo, -[name]:{name,number,description,supported,action,forced,standard}}; - -}; - -const signalsByName=getSignalsByName();exports.signalsByName=signalsByName; - +// Copyright IBM Corp. 2014,2018. All Rights Reserved. +// Node module: strong-log-transformer +// This file is licensed under the Apache License 2.0. +// License text available at https://opensource.org/licenses/Apache-2.0 -const getSignalsByNumber=function(){ -const signals=(0,_signals.getSignals)(); -const length=_realtime.SIGRTMAX+1; -const signalsA=Array.from({length},(value,number)=> -getSignalByNumber(number,signals)); +var minimist = __webpack_require__(269); +var path = __webpack_require__(4); -return Object.assign({},...signalsA); -}; +var Logger = __webpack_require__(264); +var pkg = __webpack_require__(270); -const getSignalByNumber=function(number,signals){ -const signal=findSignalByNumber(number,signals); +module.exports = cli; -if(signal===undefined){ -return{}; +function cli(args) { + var opts = minimist(args.slice(2)); + var $0 = path.basename(args[1]); + var p = console.log.bind(console); + if (opts.v || opts.version) { + version($0, p); + } else if (opts.h || opts.help) { + usage($0, p); + } else if (args.length < 3) { + process.stdin.pipe(Logger()).pipe(process.stdout); + } else { + process.stdin.pipe(Logger(opts)).pipe(process.stdout); + } } -const{name,description,supported,action,forced,standard}=signal; -return{ -[number]:{ -name, -number, -description, -supported, -action, -forced, -standard}}; - - -}; - +function version($0, p) { + p('%s v%s', pkg.name, pkg.version); +} +function usage($0, p) { + var PADDING = ' '; + var opt, def; + p('Usage: %s [options]', $0); + p(''); + p('%s', pkg.description); + p(''); + p('OPTIONS:'); + for (opt in Logger.DEFAULTS) { + def = Logger.DEFAULTS[opt]; + if (typeof def === 'boolean') + boolOpt(opt, Logger.DEFAULTS[opt]); + else + stdOpt(opt, Logger.DEFAULTS[opt]); + } + p(''); -const findSignalByNumber=function(number,signals){ -const signal=signals.find(({name})=>_os.constants.signals[name]===number); + function boolOpt(name, def) { + name = name + PADDING.slice(0, 20-name.length); + p(' --%s default: %s', name, def); + } -if(signal!==undefined){ -return signal; + function stdOpt(name, def) { + var value = name.toUpperCase() + + PADDING.slice(0, 19 - name.length*2); + p(' --%s %s default: %j', name, value, def); + } } -return signals.find(signalA=>signalA.number===number); -}; - -const signalsByNumber=getSignalsByNumber();exports.signalsByNumber=signalsByNumber; -//# sourceMappingURL=main.js.map /***/ }), -/* 257 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; -Object.defineProperty(exports,"__esModule",{value:true});exports.getSignals=void 0;var _os=__webpack_require__(120); - -var _core=__webpack_require__(258); -var _realtime=__webpack_require__(259); - +/* 269 */ +/***/ (function(module, exports) { +module.exports = function (args, opts) { + if (!opts) opts = {}; + + var flags = { bools : {}, strings : {}, unknownFn: null }; -const getSignals=function(){ -const realtimeSignals=(0,_realtime.getRealtimeSignals)(); -const signals=[..._core.SIGNALS,...realtimeSignals].map(normalizeSignal); -return signals; -};exports.getSignals=getSignals; + if (typeof opts['unknown'] === 'function') { + flags.unknownFn = opts['unknown']; + } + if (typeof opts['boolean'] === 'boolean' && opts['boolean']) { + flags.allBools = true; + } else { + [].concat(opts['boolean']).filter(Boolean).forEach(function (key) { + flags.bools[key] = true; + }); + } + + var aliases = {}; + Object.keys(opts.alias || {}).forEach(function (key) { + aliases[key] = [].concat(opts.alias[key]); + aliases[key].forEach(function (x) { + aliases[x] = [key].concat(aliases[key].filter(function (y) { + return x !== y; + })); + }); + }); + [].concat(opts.string).filter(Boolean).forEach(function (key) { + flags.strings[key] = true; + if (aliases[key]) { + flags.strings[aliases[key]] = true; + } + }); + var defaults = opts['default'] || {}; + + var argv = { _ : [] }; + Object.keys(flags.bools).forEach(function (key) { + setArg(key, defaults[key] === undefined ? false : defaults[key]); + }); + + var notFlags = []; + if (args.indexOf('--') !== -1) { + notFlags = args.slice(args.indexOf('--')+1); + args = args.slice(0, args.indexOf('--')); + } + function argDefined(key, arg) { + return (flags.allBools && /^--[^=]+$/.test(arg)) || + flags.strings[key] || flags.bools[key] || aliases[key]; + } + function setArg (key, val, arg) { + if (arg && flags.unknownFn && !argDefined(key, arg)) { + if (flags.unknownFn(arg) === false) return; + } -const normalizeSignal=function({ -name, -number:defaultNumber, -description, -action, -forced=false, -standard}) -{ -const{ -signals:{[name]:constantSignal}}= -_os.constants; -const supported=constantSignal!==undefined; -const number=supported?constantSignal:defaultNumber; -return{name,number,description,supported,action,forced,standard}; -}; -//# sourceMappingURL=signals.js.map + var value = !flags.strings[key] && isNumber(val) + ? Number(val) : val + ; + setKey(argv, key.split('.'), value); + + (aliases[key] || []).forEach(function (x) { + setKey(argv, x.split('.'), value); + }); + } -/***/ }), -/* 258 */ -/***/ (function(module, exports, __webpack_require__) { + function setKey (obj, keys, value) { + var o = obj; + for (var i = 0; i < keys.length-1; i++) { + var key = keys[i]; + if (key === '__proto__') return; + if (o[key] === undefined) o[key] = {}; + if (o[key] === Object.prototype || o[key] === Number.prototype + || o[key] === String.prototype) o[key] = {}; + if (o[key] === Array.prototype) o[key] = []; + o = o[key]; + } -"use strict"; -Object.defineProperty(exports,"__esModule",{value:true});exports.SIGNALS=void 0; + var key = keys[keys.length - 1]; + if (key === '__proto__') return; + if (o === Object.prototype || o === Number.prototype + || o === String.prototype) o = {}; + if (o === Array.prototype) o = []; + if (o[key] === undefined || flags.bools[key] || typeof o[key] === 'boolean') { + o[key] = value; + } + else if (Array.isArray(o[key])) { + o[key].push(value); + } + else { + o[key] = [ o[key], value ]; + } + } + + function aliasIsBoolean(key) { + return aliases[key].some(function (x) { + return flags.bools[x]; + }); + } -const SIGNALS=[ -{ -name:"SIGHUP", -number:1, -action:"terminate", -description:"Terminal closed", -standard:"posix"}, + for (var i = 0; i < args.length; i++) { + var arg = args[i]; + + if (/^--.+=/.test(arg)) { + // Using [\s\S] instead of . because js doesn't support the + // 'dotall' regex modifier. See: + // http://stackoverflow.com/a/1068308/13216 + var m = arg.match(/^--([^=]+)=([\s\S]*)$/); + var key = m[1]; + var value = m[2]; + if (flags.bools[key]) { + value = value !== 'false'; + } + setArg(key, value, arg); + } + else if (/^--no-.+/.test(arg)) { + var key = arg.match(/^--no-(.+)/)[1]; + setArg(key, false, arg); + } + else if (/^--.+/.test(arg)) { + var key = arg.match(/^--(.+)/)[1]; + var next = args[i + 1]; + if (next !== undefined && !/^-/.test(next) + && !flags.bools[key] + && !flags.allBools + && (aliases[key] ? !aliasIsBoolean(key) : true)) { + setArg(key, next, arg); + i++; + } + else if (/^(true|false)$/.test(next)) { + setArg(key, next === 'true', arg); + i++; + } + else { + setArg(key, flags.strings[key] ? '' : true, arg); + } + } + else if (/^-[^-]+/.test(arg)) { + var letters = arg.slice(1,-1).split(''); + + var broken = false; + for (var j = 0; j < letters.length; j++) { + var next = arg.slice(j+2); + + if (next === '-') { + setArg(letters[j], next, arg) + continue; + } + + if (/[A-Za-z]/.test(letters[j]) && /=/.test(next)) { + setArg(letters[j], next.split('=')[1], arg); + broken = true; + break; + } + + if (/[A-Za-z]/.test(letters[j]) + && /-?\d+(\.\d*)?(e-?\d+)?$/.test(next)) { + setArg(letters[j], next, arg); + broken = true; + break; + } + + if (letters[j+1] && letters[j+1].match(/\W/)) { + setArg(letters[j], arg.slice(j+2), arg); + broken = true; + break; + } + else { + setArg(letters[j], flags.strings[letters[j]] ? '' : true, arg); + } + } + + var key = arg.slice(-1)[0]; + if (!broken && key !== '-') { + if (args[i+1] && !/^(-|--)[^-]/.test(args[i+1]) + && !flags.bools[key] + && (aliases[key] ? !aliasIsBoolean(key) : true)) { + setArg(key, args[i+1], arg); + i++; + } + else if (args[i+1] && /^(true|false)$/.test(args[i+1])) { + setArg(key, args[i+1] === 'true', arg); + i++; + } + else { + setArg(key, flags.strings[key] ? '' : true, arg); + } + } + } + else { + if (!flags.unknownFn || flags.unknownFn(arg) !== false) { + argv._.push( + flags.strings['_'] || !isNumber(arg) ? arg : Number(arg) + ); + } + if (opts.stopEarly) { + argv._.push.apply(argv._, args.slice(i + 1)); + break; + } + } + } + + Object.keys(defaults).forEach(function (key) { + if (!hasKey(argv, key.split('.'))) { + setKey(argv, key.split('.'), defaults[key]); + + (aliases[key] || []).forEach(function (x) { + setKey(argv, x.split('.'), defaults[key]); + }); + } + }); + + if (opts['--']) { + argv['--'] = new Array(); + notFlags.forEach(function(key) { + argv['--'].push(key); + }); + } + else { + notFlags.forEach(function(key) { + argv._.push(key); + }); + } -{ -name:"SIGINT", -number:2, -action:"terminate", -description:"User interruption with CTRL-C", -standard:"ansi"}, + return argv; +}; -{ -name:"SIGQUIT", -number:3, -action:"core", -description:"User interruption with CTRL-\\", -standard:"posix"}, +function hasKey (obj, keys) { + var o = obj; + keys.slice(0,-1).forEach(function (key) { + o = (o[key] || {}); + }); -{ -name:"SIGILL", -number:4, -action:"core", -description:"Invalid machine instruction", -standard:"ansi"}, + var key = keys[keys.length - 1]; + return key in o; +} -{ -name:"SIGTRAP", -number:5, -action:"core", -description:"Debugger breakpoint", -standard:"posix"}, +function isNumber (x) { + if (typeof x === 'number') return true; + if (/^0x[0-9a-f]+$/i.test(x)) return true; + return /^[-+]?(?:\d+(?:\.\d*)?|\.\d+)(e[-+]?\d+)?$/.test(x); +} -{ -name:"SIGABRT", -number:6, -action:"core", -description:"Aborted", -standard:"ansi"}, -{ -name:"SIGIOT", -number:6, -action:"core", -description:"Aborted", -standard:"bsd"}, -{ -name:"SIGBUS", -number:7, -action:"core", -description: -"Bus error due to misaligned, non-existing address or paging error", -standard:"bsd"}, +/***/ }), +/* 270 */ +/***/ (function(module) { -{ -name:"SIGEMT", -number:7, -action:"terminate", -description:"Command should be emulated but is not implemented", -standard:"other"}, +module.exports = JSON.parse("{\"name\":\"strong-log-transformer\",\"version\":\"2.1.0\",\"description\":\"Stream transformer that prefixes lines with timestamps and other things.\",\"author\":\"Ryan Graham \",\"license\":\"Apache-2.0\",\"repository\":{\"type\":\"git\",\"url\":\"git://github.com/strongloop/strong-log-transformer\"},\"keywords\":[\"logging\",\"streams\"],\"bugs\":{\"url\":\"https://github.com/strongloop/strong-log-transformer/issues\"},\"homepage\":\"https://github.com/strongloop/strong-log-transformer\",\"directories\":{\"test\":\"test\"},\"bin\":{\"sl-log-transformer\":\"bin/sl-log-transformer.js\"},\"main\":\"index.js\",\"scripts\":{\"test\":\"tap --100 test/test-*\"},\"dependencies\":{\"duplexer\":\"^0.1.1\",\"minimist\":\"^1.2.0\",\"through\":\"^2.3.4\"},\"devDependencies\":{\"tap\":\"^12.0.1\"},\"engines\":{\"node\":\">=4\"}}"); -{ -name:"SIGFPE", -number:8, -action:"core", -description:"Floating point arithmetic error", -standard:"ansi"}, +/***/ }), +/* 271 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { -{ -name:"SIGKILL", -number:9, -action:"terminate", -description:"Forced termination", -standard:"posix", -forced:true}, +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "workspacePackagePaths", function() { return workspacePackagePaths; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "copyWorkspacePackages", function() { return copyWorkspacePackages; }); +/* harmony import */ var glob__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(147); +/* harmony import */ var glob__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(glob__WEBPACK_IMPORTED_MODULE_0__); +/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(4); +/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_1__); +/* harmony import */ var util__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(112); +/* harmony import */ var util__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(util__WEBPACK_IMPORTED_MODULE_2__); +/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(272); +/* harmony import */ var _fs__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(131); +/* harmony import */ var _package_json__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(165); +/* harmony import */ var _projects__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(146); +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ -{ -name:"SIGUSR1", -number:10, -action:"terminate", -description:"Application-specific signal", -standard:"posix"}, -{ -name:"SIGSEGV", -number:11, -action:"core", -description:"Segmentation fault", -standard:"ansi"}, -{ -name:"SIGUSR2", -number:12, -action:"terminate", -description:"Application-specific signal", -standard:"posix"}, -{ -name:"SIGPIPE", -number:13, -action:"terminate", -description:"Broken pipe or socket", -standard:"posix"}, -{ -name:"SIGALRM", -number:14, -action:"terminate", -description:"Timeout or timer", -standard:"posix"}, -{ -name:"SIGTERM", -number:15, -action:"terminate", -description:"Termination", -standard:"ansi"}, -{ -name:"SIGSTKFLT", -number:16, -action:"terminate", -description:"Stack is empty or overflowed", -standard:"other"}, +const glob = Object(util__WEBPACK_IMPORTED_MODULE_2__["promisify"])(glob__WEBPACK_IMPORTED_MODULE_0___default.a); +async function workspacePackagePaths(rootPath) { + const rootPkgJson = await Object(_package_json__WEBPACK_IMPORTED_MODULE_5__["readPackageJson"])(rootPath); -{ -name:"SIGCHLD", -number:17, -action:"ignore", -description:"Child process terminated, paused or unpaused", -standard:"posix"}, + if (!rootPkgJson.workspaces) { + return []; + } -{ -name:"SIGCLD", -number:17, -action:"ignore", -description:"Child process terminated, paused or unpaused", -standard:"other"}, + const workspacesPathsPatterns = rootPkgJson.workspaces.packages; + let workspaceProjectsPaths = []; -{ -name:"SIGCONT", -number:18, -action:"unpause", -description:"Unpaused", -standard:"posix", -forced:true}, + for (const pattern of workspacesPathsPatterns) { + workspaceProjectsPaths = workspaceProjectsPaths.concat(await packagesFromGlobPattern({ + pattern, + rootPath + })); + } // Filter out exclude glob patterns -{ -name:"SIGSTOP", -number:19, -action:"pause", -description:"Paused", -standard:"posix", -forced:true}, -{ -name:"SIGTSTP", -number:20, -action:"pause", -description:"Paused using CTRL-Z or \"suspend\"", -standard:"posix"}, + for (const pattern of workspacesPathsPatterns) { + if (pattern.startsWith('!')) { + const pathToRemove = path__WEBPACK_IMPORTED_MODULE_1___default.a.join(rootPath, pattern.slice(1), 'package.json'); + workspaceProjectsPaths = workspaceProjectsPaths.filter(p => p !== pathToRemove); + } + } -{ -name:"SIGTTIN", -number:21, -action:"pause", -description:"Background process cannot read terminal input", -standard:"posix"}, + return workspaceProjectsPaths; +} +async function copyWorkspacePackages(rootPath) { + const projectPaths = Object(_config__WEBPACK_IMPORTED_MODULE_3__["getProjectPaths"])({ + rootPath + }); + const projects = await Object(_projects__WEBPACK_IMPORTED_MODULE_6__["getProjects"])(rootPath, projectPaths); -{ -name:"SIGBREAK", -number:21, -action:"terminate", -description:"User interruption with CTRL-BREAK", -standard:"other"}, + for (const project of projects.values()) { + const dest = path__WEBPACK_IMPORTED_MODULE_1___default.a.resolve(rootPath, 'node_modules', project.name); -{ -name:"SIGTTOU", -number:22, -action:"pause", -description:"Background process cannot write to terminal output", -standard:"posix"}, + if ((await Object(_fs__WEBPACK_IMPORTED_MODULE_4__["isSymlink"])(dest)) === false) { + continue; + } // Remove the symlink -{ -name:"SIGURG", -number:23, -action:"ignore", -description:"Socket received out-of-band data", -standard:"bsd"}, -{ -name:"SIGXCPU", -number:24, -action:"core", -description:"Process timed out", -standard:"bsd"}, + await Object(_fs__WEBPACK_IMPORTED_MODULE_4__["unlink"])(dest); // Copy in the package -{ -name:"SIGXFSZ", -number:25, -action:"core", -description:"File too big", -standard:"bsd"}, + await Object(_fs__WEBPACK_IMPORTED_MODULE_4__["copyDirectory"])(project.path, dest); + } +} -{ -name:"SIGVTALRM", -number:26, -action:"terminate", -description:"Timeout or timer", -standard:"bsd"}, +function packagesFromGlobPattern({ + pattern, + rootPath +}) { + const globOptions = { + cwd: rootPath, + // Should throw in case of unusual errors when reading the file system + strict: true, + // Always returns absolute paths for matched files + absolute: true, + // Do not match ** against multiple filenames + // (This is only specified because we currently don't have a need for it.) + noglobstar: true + }; + return glob(path__WEBPACK_IMPORTED_MODULE_1___default.a.join(pattern, 'package.json'), globOptions); +} -{ -name:"SIGPROF", -number:27, -action:"terminate", -description:"Timeout or timer", -standard:"bsd"}, +/***/ }), +/* 272 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { -{ -name:"SIGWINCH", -number:28, -action:"ignore", -description:"Terminal window size changed", -standard:"bsd"}, +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getProjectPaths", function() { return getProjectPaths; }); +/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(4); +/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_0__); +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ -{ -name:"SIGIO", -number:29, -action:"terminate", -description:"I/O is available", -standard:"other"}, -{ -name:"SIGPOLL", -number:29, -action:"terminate", -description:"Watched event", -standard:"other"}, - -{ -name:"SIGINFO", -number:29, -action:"ignore", -description:"Request for process information", -standard:"other"}, - -{ -name:"SIGPWR", -number:30, -action:"terminate", -description:"Device running out of power", -standard:"systemv"}, - -{ -name:"SIGSYS", -number:31, -action:"core", -description:"Invalid system call", -standard:"other"}, - -{ -name:"SIGUNUSED", -number:31, -action:"terminate", -description:"Invalid system call", -standard:"other"}];exports.SIGNALS=SIGNALS; -//# sourceMappingURL=core.js.map - -/***/ }), -/* 259 */ -/***/ (function(module, exports, __webpack_require__) { +/** + * Returns all the paths where plugins are located + */ +function getProjectPaths({ + rootPath, + ossOnly, + skipKibanaPlugins +}) { + const projectPaths = [rootPath, Object(path__WEBPACK_IMPORTED_MODULE_0__["resolve"])(rootPath, 'packages/*')]; // This is needed in order to install the dependencies for the declared + // plugin functional used in the selenium functional tests. + // As we are now using the webpack dll for the client vendors dependencies + // when we run the plugin functional tests against the distributable + // dependencies used by such plugins like @eui, react and react-dom can't + // be loaded from the dll as the context is different from the one declared + // into the webpack dll reference plugin. + // In anyway, have a plugin declaring their own dependencies is the + // correct and the expect behavior. -"use strict"; -Object.defineProperty(exports,"__esModule",{value:true});exports.SIGRTMAX=exports.getRealtimeSignals=void 0; -const getRealtimeSignals=function(){ -const length=SIGRTMAX-SIGRTMIN+1; -return Array.from({length},getRealtimeSignal); -};exports.getRealtimeSignals=getRealtimeSignals; + projectPaths.push(Object(path__WEBPACK_IMPORTED_MODULE_0__["resolve"])(rootPath, 'test/plugin_functional/plugins/*')); + projectPaths.push(Object(path__WEBPACK_IMPORTED_MODULE_0__["resolve"])(rootPath, 'test/interpreter_functional/plugins/*')); + projectPaths.push(Object(path__WEBPACK_IMPORTED_MODULE_0__["resolve"])(rootPath, 'examples/*')); -const getRealtimeSignal=function(value,index){ -return{ -name:`SIGRT${index+1}`, -number:SIGRTMIN+index, -action:"terminate", -description:"Application-specific signal (realtime)", -standard:"posix"}; + if (!ossOnly) { + projectPaths.push(Object(path__WEBPACK_IMPORTED_MODULE_0__["resolve"])(rootPath, 'x-pack')); + projectPaths.push(Object(path__WEBPACK_IMPORTED_MODULE_0__["resolve"])(rootPath, 'x-pack/plugins/*')); + projectPaths.push(Object(path__WEBPACK_IMPORTED_MODULE_0__["resolve"])(rootPath, 'x-pack/legacy/plugins/*')); + projectPaths.push(Object(path__WEBPACK_IMPORTED_MODULE_0__["resolve"])(rootPath, 'x-pack/test/functional_with_es_ssl/fixtures/plugins/*')); + } -}; + if (!skipKibanaPlugins) { + projectPaths.push(Object(path__WEBPACK_IMPORTED_MODULE_0__["resolve"])(rootPath, '../kibana-extra/*')); + projectPaths.push(Object(path__WEBPACK_IMPORTED_MODULE_0__["resolve"])(rootPath, '../kibana-extra/*/packages/*')); + projectPaths.push(Object(path__WEBPACK_IMPORTED_MODULE_0__["resolve"])(rootPath, '../kibana-extra/*/plugins/*')); + projectPaths.push(Object(path__WEBPACK_IMPORTED_MODULE_0__["resolve"])(rootPath, 'plugins/*')); + projectPaths.push(Object(path__WEBPACK_IMPORTED_MODULE_0__["resolve"])(rootPath, 'plugins/*/packages/*')); + projectPaths.push(Object(path__WEBPACK_IMPORTED_MODULE_0__["resolve"])(rootPath, 'plugins/*/plugins/*')); + } -const SIGRTMIN=34; -const SIGRTMAX=64;exports.SIGRTMAX=SIGRTMAX; -//# sourceMappingURL=realtime.js.map + return projectPaths; +} /***/ }), -/* 260 */ -/***/ (function(module, exports, __webpack_require__) { +/* 273 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getAllChecksums", function() { return getAllChecksums; }); +/* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(134); +/* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(fs__WEBPACK_IMPORTED_MODULE_0__); +/* harmony import */ var crypto__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(274); +/* harmony import */ var crypto__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(crypto__WEBPACK_IMPORTED_MODULE_1__); +/* harmony import */ var util__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(112); +/* harmony import */ var util__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(util__WEBPACK_IMPORTED_MODULE_2__); +/* harmony import */ var execa__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(228); +/* harmony import */ var execa__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(execa__WEBPACK_IMPORTED_MODULE_3__); +/* harmony import */ var _yarn_lock__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(275); +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ -const aliases = ['stdin', 'stdout', 'stderr']; - -const hasAlias = opts => aliases.some(alias => opts[alias] !== undefined); - -const normalizeStdio = opts => { - if (!opts) { - return; - } - - const {stdio} = opts; - if (stdio === undefined) { - return aliases.map(alias => opts[alias]); - } - if (hasAlias(opts)) { - throw new Error(`It's not possible to provide \`stdio\` in combination with one of ${aliases.map(alias => `\`${alias}\``).join(', ')}`); - } - if (typeof stdio === 'string') { - return stdio; - } - if (!Array.isArray(stdio)) { - throw new TypeError(`Expected \`stdio\` to be of type \`string\` or \`Array\`, got \`${typeof stdio}\``); - } +const statAsync = Object(util__WEBPACK_IMPORTED_MODULE_2__["promisify"])(fs__WEBPACK_IMPORTED_MODULE_0___default.a.stat); - const length = Math.max(stdio.length, aliases.length); - return Array.from({length}, (value, index) => stdio[index]); -}; +const projectBySpecificitySorter = (a, b) => b.path.length - a.path.length; +/** Get the changed files for a set of projects */ -module.exports = normalizeStdio; -// `ipc` is pushed unless it is already present -module.exports.node = opts => { - const stdio = normalizeStdio(opts); +async function getChangesForProjects(projects, kbn, log) { + log.verbose('getting changed files'); + const { + stdout + } = await execa__WEBPACK_IMPORTED_MODULE_3___default()('git', ['ls-files', '-dmto', '--exclude-standard', '--', ...Array.from(projects.values()).filter(p => kbn.isPartOfRepo(p)).map(p => p.path)], { + cwd: kbn.getAbsolute() + }); + const output = stdout.trim(); + const unassignedChanges = new Map(); - if (stdio === 'ipc') { - return 'ipc'; - } + if (output) { + for (const line of output.split('\n')) { + const [tag, ...pathParts] = line.trim().split(' '); + const path = pathParts.join(' '); - if (stdio === undefined || typeof stdio === 'string') { - return [stdio, stdio, stdio, 'ipc']; - } + switch (tag) { + case 'M': + case 'C': + // for some reason ls-files returns deleted files as both deleted + // and modified, so make sure not to overwrite changes already + // tracked as "deleted" + if (unassignedChanges.get(path) !== 'deleted') { + unassignedChanges.set(path, 'modified'); + } - if (stdio.includes('ipc')) { - return stdio; - } + break; - return [...stdio, 'ipc']; -}; + case 'R': + unassignedChanges.set(path, 'deleted'); + break; + case '?': + unassignedChanges.set(path, 'untracked'); + break; -/***/ }), -/* 261 */ -/***/ (function(module, exports, __webpack_require__) { + case 'H': + case 'S': + case 'K': + default: + log.warning(`unexpected modification status "${tag}" for ${path}, please report this!`); + unassignedChanges.set(path, 'invalid'); + break; + } + } + } -"use strict"; + const sortedRelevantProjects = Array.from(projects.values()).sort(projectBySpecificitySorter); + const changesByProject = new Map(); -const os = __webpack_require__(120); -const onExit = __webpack_require__(217); + for (const project of sortedRelevantProjects) { + if (kbn.isOutsideRepo(project)) { + changesByProject.set(project, undefined); + continue; + } -const DEFAULT_FORCE_KILL_TIMEOUT = 1000 * 5; + const ownChanges = new Map(); + const prefix = kbn.getRelative(project.path); -// Monkey-patches `childProcess.kill()` to add `forceKillAfterTimeout` behavior -const spawnedKill = (kill, signal = 'SIGTERM', options = {}) => { - const killResult = kill(signal); - setKillTimeout(kill, signal, options, killResult); - return killResult; -}; + for (const [path, type] of unassignedChanges) { + if (path.startsWith(prefix)) { + ownChanges.set(path, type); + unassignedChanges.delete(path); + } + } -const setKillTimeout = (kill, signal, options, killResult) => { - if (!shouldForceKill(signal, options, killResult)) { - return; - } + log.verbose(`[${project.name}] found ${ownChanges.size} changes`); + changesByProject.set(project, ownChanges); + } - const timeout = getForceKillAfterTimeout(options); - const t = setTimeout(() => { - kill('SIGKILL'); - }, timeout); + if (unassignedChanges.size) { + throw new Error(`unable to assign all change paths to a project: ${JSON.stringify(Array.from(unassignedChanges.entries()))}`); + } - // Guarded because there's no `.unref()` when `execa` is used in the renderer - // process in Electron. This cannot be tested since we don't run tests in - // Electron. - // istanbul ignore else - if (t.unref) { - t.unref(); - } -}; + return changesByProject; +} +/** Get the latest commit sha for a project */ -const shouldForceKill = (signal, {forceKillAfterTimeout}, killResult) => { - return isSigterm(signal) && forceKillAfterTimeout !== false && killResult; -}; -const isSigterm = signal => { - return signal === os.constants.signals.SIGTERM || - (typeof signal === 'string' && signal.toUpperCase() === 'SIGTERM'); -}; +async function getLatestSha(project, kbn) { + if (kbn.isOutsideRepo(project)) { + return; + } -const getForceKillAfterTimeout = ({forceKillAfterTimeout = true}) => { - if (forceKillAfterTimeout === true) { - return DEFAULT_FORCE_KILL_TIMEOUT; - } + const { + stdout + } = await execa__WEBPACK_IMPORTED_MODULE_3___default()('git', ['log', '-n', '1', '--pretty=format:%H', '--', project.path], { + cwd: kbn.getAbsolute() + }); + return stdout.trim() || undefined; +} +/** + * Get the checksum for a specific project in the workspace + */ - if (!Number.isInteger(forceKillAfterTimeout) || forceKillAfterTimeout < 0) { - throw new TypeError(`Expected the \`forceKillAfterTimeout\` option to be a non-negative integer, got \`${forceKillAfterTimeout}\` (${typeof forceKillAfterTimeout})`); - } - return forceKillAfterTimeout; -}; +async function getChecksum(project, changes, yarnLock, kbn, log) { + const sha = await getLatestSha(project, kbn); -// `childProcess.cancel()` -const spawnedCancel = (spawned, context) => { - const killResult = spawned.kill(); + if (sha) { + log.verbose(`[${project.name}] local sha:`, sha); + } - if (killResult) { - context.isCanceled = true; - } -}; + if (!changes || Array.from(changes.values()).includes('invalid')) { + log.warning(`[${project.name}] unable to determine local changes, caching disabled`); + return; + } -const timeoutKill = (spawned, signal, reject) => { - spawned.kill(signal); - reject(Object.assign(new Error('Timed out'), {timedOut: true, signal})); -}; + const changesSummary = await Promise.all(Array.from(changes).sort((a, b) => a[0].localeCompare(b[0])).map(async ([path, type]) => { + if (type === 'deleted') { + return `${path}:deleted`; + } -// `timeout` option handling -const setupTimeout = (spawned, {timeout, killSignal = 'SIGTERM'}, spawnedPromise) => { - if (timeout === 0 || timeout === undefined) { - return spawnedPromise; - } + const stats = await statAsync(kbn.getAbsolute(path)); + log.verbose(`[${project.name}] modified time ${stats.mtimeMs} for ${path}`); + return `${path}:${stats.mtimeMs}`; + })); + const depMap = Object(_yarn_lock__WEBPACK_IMPORTED_MODULE_4__["resolveDepsForProject"])({ + project, + yarnLock, + kbn, + log, + includeDependentProject: false, + productionDepsOnly: false + }); - if (!Number.isInteger(timeout) || timeout < 0) { - throw new TypeError(`Expected the \`timeout\` option to be a non-negative integer, got \`${timeout}\` (${typeof timeout})`); - } + if (!depMap) { + return; + } - let timeoutId; - const timeoutPromise = new Promise((resolve, reject) => { - timeoutId = setTimeout(() => { - timeoutKill(spawned, killSignal, reject); - }, timeout); - }); + const deps = Array.from(depMap.values()).map(({ + name, + version + }) => `${name}@${version}`).sort((a, b) => a.localeCompare(b)); + log.verbose(`[${project.name}] resolved %d deps`, deps.length); + const checksum = JSON.stringify({ + sha, + changes: changesSummary, + deps + }, null, 2); - const safeSpawnedPromise = spawnedPromise.finally(() => { - clearTimeout(timeoutId); - }); + if (process.env.BOOTSTRAP_CACHE_DEBUG_CHECKSUM) { + return checksum; + } - return Promise.race([timeoutPromise, safeSpawnedPromise]); -}; + const hash = crypto__WEBPACK_IMPORTED_MODULE_1___default.a.createHash('sha1'); + hash.update(checksum); + return hash.digest('hex'); +} +/** + * Calculate checksums for all projects in the workspace based on + * - last git commit to project directory + * - un-committed changes + * - resolved dependencies from yarn.lock referenced by project package.json + */ -// `cleanup` option handling -const setExitHandler = async (spawned, {cleanup, detached}, timedPromise) => { - if (!cleanup || detached) { - return timedPromise; - } - const removeExitHandler = onExit(() => { - spawned.kill(); - }); +async function getAllChecksums(kbn, log, yarnLock) { + const projects = kbn.getAllProjects(); + const changesByProject = await getChangesForProjects(projects, kbn, log); + /** map of [project.name, cacheKey] */ - return timedPromise.finally(() => { - removeExitHandler(); - }); -}; + const cacheKeys = new Map(); + await Promise.all(Array.from(projects.values()).map(async project => { + cacheKeys.set(project.name, await getChecksum(project, changesByProject.get(project), yarnLock, kbn, log)); + })); + return cacheKeys; +} -module.exports = { - spawnedKill, - spawnedCancel, - setupTimeout, - setExitHandler -}; +/***/ }), +/* 274 */ +/***/ (function(module, exports) { +module.exports = require("crypto"); /***/ }), -/* 262 */ -/***/ (function(module, exports, __webpack_require__) { +/* 275 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "readYarnLock", function() { return readYarnLock; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "resolveDepsForProject", function() { return resolveDepsForProject; }); +/* harmony import */ var _yarnpkg_lockfile__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(276); +/* harmony import */ var _yarnpkg_lockfile__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_yarnpkg_lockfile__WEBPACK_IMPORTED_MODULE_0__); +/* harmony import */ var _utils_fs__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(131); +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +// @ts-expect-error published types are worthless -const isStream = __webpack_require__(263); -const getStream = __webpack_require__(264); -const mergeStream = __webpack_require__(268); -// `input` option -const handleInput = (spawned, input) => { - // Checking for stdin is workaround for https://github.com/nodejs/node/issues/26852 - // TODO: Remove `|| spawned.stdin === undefined` once we drop support for Node.js <=12.2.0 - if (input === undefined || spawned.stdin === undefined) { - return; - } +async function readYarnLock(kbn) { + try { + const contents = await Object(_utils_fs__WEBPACK_IMPORTED_MODULE_1__["readFile"])(kbn.getAbsolute('yarn.lock'), 'utf8'); + const yarnLock = Object(_yarnpkg_lockfile__WEBPACK_IMPORTED_MODULE_0__["parse"])(contents); - if (isStream(input)) { - input.pipe(spawned.stdin); - } else { - spawned.stdin.end(input); - } -}; + if (yarnLock.type === 'success') { + return yarnLock.object; + } -// `all` interleaves `stdout` and `stderr` -const makeAllStream = (spawned, {all}) => { - if (!all || (!spawned.stdout && !spawned.stderr)) { - return; - } + throw new Error('unable to read yarn.lock file, please run `yarn kbn bootstrap`'); + } catch (error) { + if (error.code !== 'ENOENT') { + throw error; + } + } - const mixed = mergeStream(); + return {}; +} +/** + * Get a list of the absolute dependencies of this project, as resolved + * in the yarn.lock file, does not include other projects in the workspace + * or their dependencies + */ - if (spawned.stdout) { - mixed.add(spawned.stdout); - } +function resolveDepsForProject({ + project: rootProject, + yarnLock, + kbn, + log, + productionDepsOnly, + includeDependentProject +}) { + /** map of [name@range, { name, version }] */ + const resolved = new Map(); + const seenProjects = new Set(); + const projectQueue = [rootProject]; + const depQueue = []; - if (spawned.stderr) { - mixed.add(spawned.stderr); - } + while (projectQueue.length) { + const project = projectQueue.shift(); - return mixed; -}; + if (seenProjects.has(project)) { + continue; + } -// On failure, `result.stdout|stderr|all` should contain the currently buffered stream -const getBufferedData = async (stream, streamPromise) => { - if (!stream) { - return; - } + seenProjects.add(project); + const projectDeps = Object.entries(productionDepsOnly ? project.productionDependencies : project.allDependencies); - stream.destroy(); + for (const [name, versionRange] of projectDeps) { + depQueue.push([name, versionRange]); + } - try { - return await streamPromise; - } catch (error) { - return error.bufferedData; - } -}; + while (depQueue.length) { + const [name, versionRange] = depQueue.shift(); + const req = `${name}@${versionRange}`; -const getStreamPromise = (stream, {encoding, buffer, maxBuffer}) => { - if (!stream || !buffer) { - return; - } + if (resolved.has(req)) { + continue; + } - if (encoding) { - return getStream(stream, {encoding, maxBuffer}); - } + if (includeDependentProject && kbn.hasProject(name)) { + projectQueue.push(kbn.getProject(name)); + } - return getStream.buffer(stream, {maxBuffer}); -}; + if (!kbn.hasProject(name)) { + const pkg = yarnLock[req]; -// Retrieve result of child process: exit code, signal, error, streams (stdout/stderr/all) -const getSpawnedResult = async ({stdout, stderr, all}, {encoding, buffer, maxBuffer}, processDone) => { - const stdoutPromise = getStreamPromise(stdout, {encoding, buffer, maxBuffer}); - const stderrPromise = getStreamPromise(stderr, {encoding, buffer, maxBuffer}); - const allPromise = getStreamPromise(all, {encoding, buffer, maxBuffer: maxBuffer * 2}); + if (!pkg) { + log.warning('yarn.lock file is out of date, please run `yarn kbn bootstrap` to re-enable caching'); + return; + } - try { - return await Promise.all([processDone, stdoutPromise, stderrPromise, allPromise]); - } catch (error) { - return Promise.all([ - {error, signal: error.signal, timedOut: error.timedOut}, - getBufferedData(stdout, stdoutPromise), - getBufferedData(stderr, stderrPromise), - getBufferedData(all, allPromise) - ]); - } -}; + resolved.set(req, { + name, + version: pkg.version + }); + const allDepsEntries = [...Object.entries(pkg.dependencies || {}), ...Object.entries(pkg.optionalDependencies || {})]; -const validateInputSync = ({input}) => { - if (isStream(input)) { - throw new TypeError('The `input` option cannot be a stream in sync mode'); - } -}; + for (const [childName, childVersionRange] of allDepsEntries) { + depQueue.push([childName, childVersionRange]); + } + } + } + } -module.exports = { - handleInput, - makeAllStream, - getSpawnedResult, - validateInputSync -}; + return resolved; +} + +/***/ }), +/* 276 */ +/***/ (function(module, exports, __webpack_require__) { +module.exports = +/******/ (function(modules) { // webpackBootstrap +/******/ // The module cache +/******/ var installedModules = {}; +/******/ +/******/ // The require function +/******/ function __webpack_require__(moduleId) { +/******/ +/******/ // Check if module is in cache +/******/ if(installedModules[moduleId]) { +/******/ return installedModules[moduleId].exports; +/******/ } +/******/ // Create a new module (and put it into the cache) +/******/ var module = installedModules[moduleId] = { +/******/ i: moduleId, +/******/ l: false, +/******/ exports: {} +/******/ }; +/******/ +/******/ // Execute the module function +/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); +/******/ +/******/ // Flag the module as loaded +/******/ module.l = true; +/******/ +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } +/******/ +/******/ +/******/ // expose the modules object (__webpack_modules__) +/******/ __webpack_require__.m = modules; +/******/ +/******/ // expose the module cache +/******/ __webpack_require__.c = installedModules; +/******/ +/******/ // identity function for calling harmony imports with the correct context +/******/ __webpack_require__.i = function(value) { return value; }; +/******/ +/******/ // define getter function for harmony exports +/******/ __webpack_require__.d = function(exports, name, getter) { +/******/ if(!__webpack_require__.o(exports, name)) { +/******/ Object.defineProperty(exports, name, { +/******/ configurable: false, +/******/ enumerable: true, +/******/ get: getter +/******/ }); +/******/ } +/******/ }; +/******/ +/******/ // getDefaultExport function for compatibility with non-harmony modules +/******/ __webpack_require__.n = function(module) { +/******/ var getter = module && module.__esModule ? +/******/ function getDefault() { return module['default']; } : +/******/ function getModuleExports() { return module; }; +/******/ __webpack_require__.d(getter, 'a', getter); +/******/ return getter; +/******/ }; +/******/ +/******/ // Object.prototype.hasOwnProperty.call +/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; +/******/ +/******/ // __webpack_public_path__ +/******/ __webpack_require__.p = ""; +/******/ +/******/ // Load entry module and return exports +/******/ return __webpack_require__(__webpack_require__.s = 14); +/******/ }) +/************************************************************************/ +/******/ ([ +/* 0 */ +/***/ (function(module, exports) { +module.exports = __webpack_require__(4); /***/ }), -/* 263 */ +/* 1 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const isStream = stream => - stream !== null && - typeof stream === 'object' && - typeof stream.pipe === 'function'; +exports.__esModule = true; -isStream.writable = stream => - isStream(stream) && - stream.writable !== false && - typeof stream._write === 'function' && - typeof stream._writableState === 'object'; +var _promise = __webpack_require__(173); -isStream.readable = stream => - isStream(stream) && - stream.readable !== false && - typeof stream._read === 'function' && - typeof stream._readableState === 'object'; +var _promise2 = _interopRequireDefault(_promise); -isStream.duplex = stream => - isStream.writable(stream) && - isStream.readable(stream); +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } -isStream.transform = stream => - isStream.duplex(stream) && - typeof stream._transform === 'function' && - typeof stream._transformState === 'object'; +exports.default = function (fn) { + return function () { + var gen = fn.apply(this, arguments); + return new _promise2.default(function (resolve, reject) { + function step(key, arg) { + try { + var info = gen[key](arg); + var value = info.value; + } catch (error) { + reject(error); + return; + } -module.exports = isStream; + if (info.done) { + resolve(value); + } else { + return _promise2.default.resolve(value).then(function (value) { + step("next", value); + }, function (err) { + step("throw", err); + }); + } + } + return step("next"); + }); + }; +}; /***/ }), -/* 264 */ -/***/ (function(module, exports, __webpack_require__) { +/* 2 */ +/***/ (function(module, exports) { -"use strict"; +module.exports = __webpack_require__(112); -const pump = __webpack_require__(265); -const bufferStream = __webpack_require__(267); +/***/ }), +/* 3 */ +/***/ (function(module, exports) { -class MaxBufferError extends Error { - constructor() { - super('maxBuffer exceeded'); - this.name = 'MaxBufferError'; - } -} +module.exports = __webpack_require__(134); -async function getStream(inputStream, options) { - if (!inputStream) { - return Promise.reject(new Error('Expected a stream')); - } +/***/ }), +/* 4 */ +/***/ (function(module, exports, __webpack_require__) { - options = { - maxBuffer: Infinity, - ...options - }; +"use strict"; - const {maxBuffer} = options; - let stream; - await new Promise((resolve, reject) => { - const rejectPromise = error => { - if (error) { // A null check - error.bufferedData = stream.getBufferedValue(); - } +Object.defineProperty(exports, "__esModule", { + value: true +}); +class MessageError extends Error { + constructor(msg, code) { + super(msg); + this.code = code; + } - reject(error); - }; +} - stream = pump(inputStream, bufferStream(options), error => { - if (error) { - rejectPromise(error); - return; - } +exports.MessageError = MessageError; +class ProcessSpawnError extends MessageError { + constructor(msg, code, process) { + super(msg, code); + this.process = process; + } - resolve(); - }); +} - stream.on('data', () => { - if (stream.getBufferedLength() > maxBuffer) { - rejectPromise(new MaxBufferError()); - } - }); - }); +exports.ProcessSpawnError = ProcessSpawnError; +class SecurityError extends MessageError {} - return stream.getBufferedValue(); -} +exports.SecurityError = SecurityError; +class ProcessTermError extends MessageError {} -module.exports = getStream; -// TODO: Remove this for the next major release -module.exports.default = getStream; -module.exports.buffer = (stream, options) => getStream(stream, {...options, encoding: 'buffer'}); -module.exports.array = (stream, options) => getStream(stream, {...options, array: true}); -module.exports.MaxBufferError = MaxBufferError; +exports.ProcessTermError = ProcessTermError; +class ResponseError extends Error { + constructor(msg, responseCode) { + super(msg); + this.responseCode = responseCode; + } +} +exports.ResponseError = ResponseError; /***/ }), -/* 265 */ +/* 5 */ /***/ (function(module, exports, __webpack_require__) { -var once = __webpack_require__(161) -var eos = __webpack_require__(266) -var fs = __webpack_require__(133) // we only need fs to get the ReadStream and WriteStream prototypes +"use strict"; -var noop = function () {} -var ancient = /^v?\.0/.test(process.version) -var isFn = function (fn) { - return typeof fn === 'function' -} +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.getFirstSuitableFolder = exports.readFirstAvailableStream = exports.makeTempDir = exports.hardlinksWork = exports.writeFilePreservingEol = exports.getFileSizeOnDisk = exports.walk = exports.symlink = exports.find = exports.readJsonAndFile = exports.readJson = exports.readFileAny = exports.hardlinkBulk = exports.copyBulk = exports.unlink = exports.glob = exports.link = exports.chmod = exports.lstat = exports.exists = exports.mkdirp = exports.stat = exports.access = exports.rename = exports.readdir = exports.realpath = exports.readlink = exports.writeFile = exports.open = exports.readFileBuffer = exports.lockQueue = exports.constants = undefined; -var isFS = function (stream) { - if (!ancient) return false // newer node version do not need to care about fs is a special way - if (!fs) return false // browser - return (stream instanceof (fs.ReadStream || noop) || stream instanceof (fs.WriteStream || noop)) && isFn(stream.close) -} +var _asyncToGenerator2; -var isRequest = function (stream) { - return stream.setHeader && isFn(stream.abort) +function _load_asyncToGenerator() { + return _asyncToGenerator2 = _interopRequireDefault(__webpack_require__(1)); } -var destroyer = function (stream, reading, writing, callback) { - callback = once(callback) - - var closed = false - stream.on('close', function () { - closed = true - }) +let buildActionsForCopy = (() => { + var _ref = (0, (_asyncToGenerator2 || _load_asyncToGenerator()).default)(function* (queue, events, possibleExtraneous, reporter) { - eos(stream, {readable: reading, writable: writing}, function (err) { - if (err) return callback(err) - closed = true - callback() - }) + // + let build = (() => { + var _ref5 = (0, (_asyncToGenerator2 || _load_asyncToGenerator()).default)(function* (data) { + const src = data.src, + dest = data.dest, + type = data.type; - var destroyed = false - return function (err) { - if (closed) return - if (destroyed) return - destroyed = true + const onFresh = data.onFresh || noop; + const onDone = data.onDone || noop; - if (isFS(stream)) return stream.close(noop) // use close for fs streams to avoid fd leaks - if (isRequest(stream)) return stream.abort() // request.destroy just do .end - .abort is what we want + // TODO https://github.com/yarnpkg/yarn/issues/3751 + // related to bundled dependencies handling + if (files.has(dest.toLowerCase())) { + reporter.verbose(`The case-insensitive file ${dest} shouldn't be copied twice in one bulk copy`); + } else { + files.add(dest.toLowerCase()); + } - if (isFn(stream.destroy)) return stream.destroy() + if (type === 'symlink') { + yield mkdirp((_path || _load_path()).default.dirname(dest)); + onFresh(); + actions.symlink.push({ + dest, + linkname: src + }); + onDone(); + return; + } - callback(err || new Error('stream was destroyed')) - } -} + if (events.ignoreBasenames.indexOf((_path || _load_path()).default.basename(src)) >= 0) { + // ignored file + return; + } -var call = function (fn) { - fn() -} + const srcStat = yield lstat(src); + let srcFiles; -var pipe = function (from, to) { - return from.pipe(to) -} + if (srcStat.isDirectory()) { + srcFiles = yield readdir(src); + } -var pump = function () { - var streams = Array.prototype.slice.call(arguments) - var callback = isFn(streams[streams.length - 1] || noop) && streams.pop() || noop + let destStat; + try { + // try accessing the destination + destStat = yield lstat(dest); + } catch (e) { + // proceed if destination doesn't exist, otherwise error + if (e.code !== 'ENOENT') { + throw e; + } + } - if (Array.isArray(streams[0])) streams = streams[0] - if (streams.length < 2) throw new Error('pump requires two streams per minimum') + // if destination exists + if (destStat) { + const bothSymlinks = srcStat.isSymbolicLink() && destStat.isSymbolicLink(); + const bothFolders = srcStat.isDirectory() && destStat.isDirectory(); + const bothFiles = srcStat.isFile() && destStat.isFile(); - var error - var destroys = streams.map(function (stream, i) { - var reading = i < streams.length - 1 - var writing = i > 0 - return destroyer(stream, reading, writing, function (err) { - if (!error) error = err - if (err) destroys.forEach(call) - if (reading) return - destroys.forEach(call) - callback(error) - }) - }) + // EINVAL access errors sometimes happen which shouldn't because node shouldn't be giving + // us modes that aren't valid. investigate this, it's generally safe to proceed. - return streams.reduce(pipe) -} + /* if (srcStat.mode !== destStat.mode) { + try { + await access(dest, srcStat.mode); + } catch (err) {} + } */ -module.exports = pump + if (bothFiles && artifactFiles.has(dest)) { + // this file gets changed during build, likely by a custom install script. Don't bother checking it. + onDone(); + reporter.verbose(reporter.lang('verboseFileSkipArtifact', src)); + return; + } + if (bothFiles && srcStat.size === destStat.size && (0, (_fsNormalized || _load_fsNormalized()).fileDatesEqual)(srcStat.mtime, destStat.mtime)) { + // we can safely assume this is the same file + onDone(); + reporter.verbose(reporter.lang('verboseFileSkip', src, dest, srcStat.size, +srcStat.mtime)); + return; + } -/***/ }), -/* 266 */ -/***/ (function(module, exports, __webpack_require__) { + if (bothSymlinks) { + const srcReallink = yield readlink(src); + if (srcReallink === (yield readlink(dest))) { + // if both symlinks are the same then we can continue on + onDone(); + reporter.verbose(reporter.lang('verboseFileSkipSymlink', src, dest, srcReallink)); + return; + } + } -var once = __webpack_require__(161); + if (bothFolders) { + // mark files that aren't in this folder as possibly extraneous + const destFiles = yield readdir(dest); + invariant(srcFiles, 'src files not initialised'); -var noop = function() {}; + for (var _iterator4 = destFiles, _isArray4 = Array.isArray(_iterator4), _i4 = 0, _iterator4 = _isArray4 ? _iterator4 : _iterator4[Symbol.iterator]();;) { + var _ref6; -var isRequest = function(stream) { - return stream.setHeader && typeof stream.abort === 'function'; -}; + if (_isArray4) { + if (_i4 >= _iterator4.length) break; + _ref6 = _iterator4[_i4++]; + } else { + _i4 = _iterator4.next(); + if (_i4.done) break; + _ref6 = _i4.value; + } -var isChildProcess = function(stream) { - return stream.stdio && Array.isArray(stream.stdio) && stream.stdio.length === 3 -}; + const file = _ref6; -var eos = function(stream, opts, callback) { - if (typeof opts === 'function') return eos(stream, null, opts); - if (!opts) opts = {}; + if (srcFiles.indexOf(file) < 0) { + const loc = (_path || _load_path()).default.join(dest, file); + possibleExtraneous.add(loc); - callback = once(callback || noop); + if ((yield lstat(loc)).isDirectory()) { + for (var _iterator5 = yield readdir(loc), _isArray5 = Array.isArray(_iterator5), _i5 = 0, _iterator5 = _isArray5 ? _iterator5 : _iterator5[Symbol.iterator]();;) { + var _ref7; - var ws = stream._writableState; - var rs = stream._readableState; - var readable = opts.readable || (opts.readable !== false && stream.readable); - var writable = opts.writable || (opts.writable !== false && stream.writable); - var cancelled = false; + if (_isArray5) { + if (_i5 >= _iterator5.length) break; + _ref7 = _iterator5[_i5++]; + } else { + _i5 = _iterator5.next(); + if (_i5.done) break; + _ref7 = _i5.value; + } - var onlegacyfinish = function() { - if (!stream.writable) onfinish(); - }; + const file = _ref7; - var onfinish = function() { - writable = false; - if (!readable) callback.call(stream); - }; + possibleExtraneous.add((_path || _load_path()).default.join(loc, file)); + } + } + } + } + } + } - var onend = function() { - readable = false; - if (!writable) callback.call(stream); - }; + if (destStat && destStat.isSymbolicLink()) { + yield (0, (_fsNormalized || _load_fsNormalized()).unlink)(dest); + destStat = null; + } - var onexit = function(exitCode) { - callback.call(stream, exitCode ? new Error('exited with error code: ' + exitCode) : null); - }; + if (srcStat.isSymbolicLink()) { + onFresh(); + const linkname = yield readlink(src); + actions.symlink.push({ + dest, + linkname + }); + onDone(); + } else if (srcStat.isDirectory()) { + if (!destStat) { + reporter.verbose(reporter.lang('verboseFileFolder', dest)); + yield mkdirp(dest); + } - var onerror = function(err) { - callback.call(stream, err); - }; + const destParts = dest.split((_path || _load_path()).default.sep); + while (destParts.length) { + files.add(destParts.join((_path || _load_path()).default.sep).toLowerCase()); + destParts.pop(); + } - var onclose = function() { - process.nextTick(onclosenexttick); - }; + // push all files to queue + invariant(srcFiles, 'src files not initialised'); + let remaining = srcFiles.length; + if (!remaining) { + onDone(); + } + for (var _iterator6 = srcFiles, _isArray6 = Array.isArray(_iterator6), _i6 = 0, _iterator6 = _isArray6 ? _iterator6 : _iterator6[Symbol.iterator]();;) { + var _ref8; - var onclosenexttick = function() { - if (cancelled) return; - if (readable && !(rs && (rs.ended && !rs.destroyed))) return callback.call(stream, new Error('premature close')); - if (writable && !(ws && (ws.ended && !ws.destroyed))) return callback.call(stream, new Error('premature close')); - }; + if (_isArray6) { + if (_i6 >= _iterator6.length) break; + _ref8 = _iterator6[_i6++]; + } else { + _i6 = _iterator6.next(); + if (_i6.done) break; + _ref8 = _i6.value; + } - var onrequest = function() { - stream.req.on('finish', onfinish); - }; + const file = _ref8; - if (isRequest(stream)) { - stream.on('complete', onfinish); - stream.on('abort', onclose); - if (stream.req) onrequest(); - else stream.on('request', onrequest); - } else if (writable && !ws) { // legacy streams - stream.on('end', onlegacyfinish); - stream.on('close', onlegacyfinish); - } + queue.push({ + dest: (_path || _load_path()).default.join(dest, file), + onFresh, + onDone: function (_onDone) { + function onDone() { + return _onDone.apply(this, arguments); + } - if (isChildProcess(stream)) stream.on('exit', onexit); + onDone.toString = function () { + return _onDone.toString(); + }; - stream.on('end', onend); - stream.on('finish', onfinish); - if (opts.error !== false) stream.on('error', onerror); - stream.on('close', onclose); + return onDone; + }(function () { + if (--remaining === 0) { + onDone(); + } + }), + src: (_path || _load_path()).default.join(src, file) + }); + } + } else if (srcStat.isFile()) { + onFresh(); + actions.file.push({ + src, + dest, + atime: srcStat.atime, + mtime: srcStat.mtime, + mode: srcStat.mode + }); + onDone(); + } else { + throw new Error(`unsure how to copy this: ${src}`); + } + }); - return function() { - cancelled = true; - stream.removeListener('complete', onfinish); - stream.removeListener('abort', onclose); - stream.removeListener('request', onrequest); - if (stream.req) stream.req.removeListener('finish', onfinish); - stream.removeListener('end', onlegacyfinish); - stream.removeListener('close', onlegacyfinish); - stream.removeListener('finish', onfinish); - stream.removeListener('exit', onexit); - stream.removeListener('end', onend); - stream.removeListener('error', onerror); - stream.removeListener('close', onclose); - }; -}; + return function build(_x5) { + return _ref5.apply(this, arguments); + }; + })(); -module.exports = eos; + const artifactFiles = new Set(events.artifactFiles || []); + const files = new Set(); + // initialise events + for (var _iterator = queue, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : _iterator[Symbol.iterator]();;) { + var _ref2; -/***/ }), -/* 267 */ -/***/ (function(module, exports, __webpack_require__) { + if (_isArray) { + if (_i >= _iterator.length) break; + _ref2 = _iterator[_i++]; + } else { + _i = _iterator.next(); + if (_i.done) break; + _ref2 = _i.value; + } -"use strict"; + const item = _ref2; -const {PassThrough: PassThroughStream} = __webpack_require__(137); + const onDone = item.onDone; + item.onDone = function () { + events.onProgress(item.dest); + if (onDone) { + onDone(); + } + }; + } + events.onStart(queue.length); -module.exports = options => { - options = {...options}; + // start building actions + const actions = { + file: [], + symlink: [], + link: [] + }; - const {array} = options; - let {encoding} = options; - const isBuffer = encoding === 'buffer'; - let objectMode = false; + // custom concurrency logic as we're always executing stacks of CONCURRENT_QUEUE_ITEMS queue items + // at a time due to the requirement to push items onto the queue + while (queue.length) { + const items = queue.splice(0, CONCURRENT_QUEUE_ITEMS); + yield Promise.all(items.map(build)); + } - if (array) { - objectMode = !(encoding || isBuffer); - } else { - encoding = encoding || 'utf8'; - } + // simulate the existence of some files to prevent considering them extraneous + for (var _iterator2 = artifactFiles, _isArray2 = Array.isArray(_iterator2), _i2 = 0, _iterator2 = _isArray2 ? _iterator2 : _iterator2[Symbol.iterator]();;) { + var _ref3; - if (isBuffer) { - encoding = null; - } + if (_isArray2) { + if (_i2 >= _iterator2.length) break; + _ref3 = _iterator2[_i2++]; + } else { + _i2 = _iterator2.next(); + if (_i2.done) break; + _ref3 = _i2.value; + } - const stream = new PassThroughStream({objectMode}); + const file = _ref3; - if (encoding) { - stream.setEncoding(encoding); - } + if (possibleExtraneous.has(file)) { + reporter.verbose(reporter.lang('verboseFilePhantomExtraneous', file)); + possibleExtraneous.delete(file); + } + } - let length = 0; - const chunks = []; + for (var _iterator3 = possibleExtraneous, _isArray3 = Array.isArray(_iterator3), _i3 = 0, _iterator3 = _isArray3 ? _iterator3 : _iterator3[Symbol.iterator]();;) { + var _ref4; - stream.on('data', chunk => { - chunks.push(chunk); + if (_isArray3) { + if (_i3 >= _iterator3.length) break; + _ref4 = _iterator3[_i3++]; + } else { + _i3 = _iterator3.next(); + if (_i3.done) break; + _ref4 = _i3.value; + } - if (objectMode) { - length = chunks.length; - } else { - length += chunk.length; - } - }); + const loc = _ref4; - stream.getBufferedValue = () => { - if (array) { - return chunks; - } + if (files.has(loc.toLowerCase())) { + possibleExtraneous.delete(loc); + } + } - return isBuffer ? Buffer.concat(chunks, length) : chunks.join(''); - }; + return actions; + }); - stream.getBufferedLength = () => length; + return function buildActionsForCopy(_x, _x2, _x3, _x4) { + return _ref.apply(this, arguments); + }; +})(); - return stream; -}; +let buildActionsForHardlink = (() => { + var _ref9 = (0, (_asyncToGenerator2 || _load_asyncToGenerator()).default)(function* (queue, events, possibleExtraneous, reporter) { + // + let build = (() => { + var _ref13 = (0, (_asyncToGenerator2 || _load_asyncToGenerator()).default)(function* (data) { + const src = data.src, + dest = data.dest; -/***/ }), -/* 268 */ -/***/ (function(module, exports, __webpack_require__) { + const onFresh = data.onFresh || noop; + const onDone = data.onDone || noop; + if (files.has(dest.toLowerCase())) { + // Fixes issue https://github.com/yarnpkg/yarn/issues/2734 + // When bulk hardlinking we have A -> B structure that we want to hardlink to A1 -> B1, + // package-linker passes that modules A1 and B1 need to be hardlinked, + // the recursive linking algorithm of A1 ends up scheduling files in B1 to be linked twice which will case + // an exception. + onDone(); + return; + } + files.add(dest.toLowerCase()); -"use strict"; + if (events.ignoreBasenames.indexOf((_path || _load_path()).default.basename(src)) >= 0) { + // ignored file + return; + } + const srcStat = yield lstat(src); + let srcFiles; -const { PassThrough } = __webpack_require__(137); + if (srcStat.isDirectory()) { + srcFiles = yield readdir(src); + } -module.exports = function (/*streams...*/) { - var sources = [] - var output = new PassThrough({objectMode: true}) + const destExists = yield exists(dest); + if (destExists) { + const destStat = yield lstat(dest); - output.setMaxListeners(0) + const bothSymlinks = srcStat.isSymbolicLink() && destStat.isSymbolicLink(); + const bothFolders = srcStat.isDirectory() && destStat.isDirectory(); + const bothFiles = srcStat.isFile() && destStat.isFile(); - output.add = add - output.isEmpty = isEmpty + if (srcStat.mode !== destStat.mode) { + try { + yield access(dest, srcStat.mode); + } catch (err) { + // EINVAL access errors sometimes happen which shouldn't because node shouldn't be giving + // us modes that aren't valid. investigate this, it's generally safe to proceed. + reporter.verbose(err); + } + } - output.on('unpipe', remove) + if (bothFiles && artifactFiles.has(dest)) { + // this file gets changed during build, likely by a custom install script. Don't bother checking it. + onDone(); + reporter.verbose(reporter.lang('verboseFileSkipArtifact', src)); + return; + } - Array.prototype.slice.call(arguments).forEach(add) + // correct hardlink + if (bothFiles && srcStat.ino !== null && srcStat.ino === destStat.ino) { + onDone(); + reporter.verbose(reporter.lang('verboseFileSkip', src, dest, srcStat.ino)); + return; + } - return output + if (bothSymlinks) { + const srcReallink = yield readlink(src); + if (srcReallink === (yield readlink(dest))) { + // if both symlinks are the same then we can continue on + onDone(); + reporter.verbose(reporter.lang('verboseFileSkipSymlink', src, dest, srcReallink)); + return; + } + } - function add (source) { - if (Array.isArray(source)) { - source.forEach(add) - return this - } + if (bothFolders) { + // mark files that aren't in this folder as possibly extraneous + const destFiles = yield readdir(dest); + invariant(srcFiles, 'src files not initialised'); - sources.push(source); - source.once('end', remove.bind(null, source)) - source.once('error', output.emit.bind(output, 'error')) - source.pipe(output, {end: false}) - return this - } + for (var _iterator10 = destFiles, _isArray10 = Array.isArray(_iterator10), _i10 = 0, _iterator10 = _isArray10 ? _iterator10 : _iterator10[Symbol.iterator]();;) { + var _ref14; - function isEmpty () { - return sources.length == 0; - } + if (_isArray10) { + if (_i10 >= _iterator10.length) break; + _ref14 = _iterator10[_i10++]; + } else { + _i10 = _iterator10.next(); + if (_i10.done) break; + _ref14 = _i10.value; + } - function remove (source) { - sources = sources.filter(function (it) { return it !== source }) - if (!sources.length && output.readable) { output.end() } - } -} + const file = _ref14; + if (srcFiles.indexOf(file) < 0) { + const loc = (_path || _load_path()).default.join(dest, file); + possibleExtraneous.add(loc); -/***/ }), -/* 269 */ -/***/ (function(module, exports, __webpack_require__) { + if ((yield lstat(loc)).isDirectory()) { + for (var _iterator11 = yield readdir(loc), _isArray11 = Array.isArray(_iterator11), _i11 = 0, _iterator11 = _isArray11 ? _iterator11 : _iterator11[Symbol.iterator]();;) { + var _ref15; -"use strict"; + if (_isArray11) { + if (_i11 >= _iterator11.length) break; + _ref15 = _iterator11[_i11++]; + } else { + _i11 = _iterator11.next(); + if (_i11.done) break; + _ref15 = _i11.value; + } + const file = _ref15; -const nativePromisePrototype = (async () => {})().constructor.prototype; -const descriptors = ['then', 'catch', 'finally'].map(property => [ - property, - Reflect.getOwnPropertyDescriptor(nativePromisePrototype, property) -]); + possibleExtraneous.add((_path || _load_path()).default.join(loc, file)); + } + } + } + } + } + } -// The return value is a mixin of `childProcess` and `Promise` -const mergePromise = (spawned, promise) => { - for (const [property, descriptor] of descriptors) { - // Starting the main `promise` is deferred to avoid consuming streams - const value = typeof promise === 'function' ? - (...args) => Reflect.apply(descriptor.value, promise(), args) : - descriptor.value.bind(promise); + if (srcStat.isSymbolicLink()) { + onFresh(); + const linkname = yield readlink(src); + actions.symlink.push({ + dest, + linkname + }); + onDone(); + } else if (srcStat.isDirectory()) { + reporter.verbose(reporter.lang('verboseFileFolder', dest)); + yield mkdirp(dest); - Reflect.defineProperty(spawned, property, {...descriptor, value}); - } + const destParts = dest.split((_path || _load_path()).default.sep); + while (destParts.length) { + files.add(destParts.join((_path || _load_path()).default.sep).toLowerCase()); + destParts.pop(); + } - return spawned; -}; + // push all files to queue + invariant(srcFiles, 'src files not initialised'); + let remaining = srcFiles.length; + if (!remaining) { + onDone(); + } + for (var _iterator12 = srcFiles, _isArray12 = Array.isArray(_iterator12), _i12 = 0, _iterator12 = _isArray12 ? _iterator12 : _iterator12[Symbol.iterator]();;) { + var _ref16; -// Use promises instead of `child_process` events -const getSpawnedPromise = spawned => { - return new Promise((resolve, reject) => { - spawned.on('exit', (exitCode, signal) => { - resolve({exitCode, signal}); - }); + if (_isArray12) { + if (_i12 >= _iterator12.length) break; + _ref16 = _iterator12[_i12++]; + } else { + _i12 = _iterator12.next(); + if (_i12.done) break; + _ref16 = _i12.value; + } - spawned.on('error', error => { - reject(error); - }); + const file = _ref16; - if (spawned.stdin) { - spawned.stdin.on('error', error => { - reject(error); - }); - } - }); -}; + queue.push({ + onFresh, + src: (_path || _load_path()).default.join(src, file), + dest: (_path || _load_path()).default.join(dest, file), + onDone: function (_onDone2) { + function onDone() { + return _onDone2.apply(this, arguments); + } -module.exports = { - mergePromise, - getSpawnedPromise -}; + onDone.toString = function () { + return _onDone2.toString(); + }; + return onDone; + }(function () { + if (--remaining === 0) { + onDone(); + } + }) + }); + } + } else if (srcStat.isFile()) { + onFresh(); + actions.link.push({ + src, + dest, + removeDest: destExists + }); + onDone(); + } else { + throw new Error(`unsure how to copy this: ${src}`); + } + }); + return function build(_x10) { + return _ref13.apply(this, arguments); + }; + })(); -/***/ }), -/* 270 */ -/***/ (function(module, exports, __webpack_require__) { + const artifactFiles = new Set(events.artifactFiles || []); + const files = new Set(); -"use strict"; + // initialise events + for (var _iterator7 = queue, _isArray7 = Array.isArray(_iterator7), _i7 = 0, _iterator7 = _isArray7 ? _iterator7 : _iterator7[Symbol.iterator]();;) { + var _ref10; -const SPACES_REGEXP = / +/g; + if (_isArray7) { + if (_i7 >= _iterator7.length) break; + _ref10 = _iterator7[_i7++]; + } else { + _i7 = _iterator7.next(); + if (_i7.done) break; + _ref10 = _i7.value; + } -const joinCommand = (file, args = []) => { - if (!Array.isArray(args)) { - return file; - } + const item = _ref10; - return [file, ...args].join(' '); -}; + const onDone = item.onDone || noop; + item.onDone = function () { + events.onProgress(item.dest); + onDone(); + }; + } + events.onStart(queue.length); -// Allow spaces to be escaped by a backslash if not meant as a delimiter -const handleEscaping = (tokens, token, index) => { - if (index === 0) { - return [token]; - } + // start building actions + const actions = { + file: [], + symlink: [], + link: [] + }; - const previousToken = tokens[tokens.length - 1]; + // custom concurrency logic as we're always executing stacks of CONCURRENT_QUEUE_ITEMS queue items + // at a time due to the requirement to push items onto the queue + while (queue.length) { + const items = queue.splice(0, CONCURRENT_QUEUE_ITEMS); + yield Promise.all(items.map(build)); + } - if (previousToken.endsWith('\\')) { - return [...tokens.slice(0, -1), `${previousToken.slice(0, -1)} ${token}`]; - } + // simulate the existence of some files to prevent considering them extraneous + for (var _iterator8 = artifactFiles, _isArray8 = Array.isArray(_iterator8), _i8 = 0, _iterator8 = _isArray8 ? _iterator8 : _iterator8[Symbol.iterator]();;) { + var _ref11; - return [...tokens, token]; -}; + if (_isArray8) { + if (_i8 >= _iterator8.length) break; + _ref11 = _iterator8[_i8++]; + } else { + _i8 = _iterator8.next(); + if (_i8.done) break; + _ref11 = _i8.value; + } -// Handle `execa.command()` -const parseCommand = command => { - return command - .trim() - .split(SPACES_REGEXP) - .reduce(handleEscaping, []); -}; + const file = _ref11; -module.exports = { - joinCommand, - parseCommand -}; + if (possibleExtraneous.has(file)) { + reporter.verbose(reporter.lang('verboseFilePhantomExtraneous', file)); + possibleExtraneous.delete(file); + } + } + for (var _iterator9 = possibleExtraneous, _isArray9 = Array.isArray(_iterator9), _i9 = 0, _iterator9 = _isArray9 ? _iterator9 : _iterator9[Symbol.iterator]();;) { + var _ref12; -/***/ }), -/* 271 */ -/***/ (function(module, exports, __webpack_require__) { + if (_isArray9) { + if (_i9 >= _iterator9.length) break; + _ref12 = _iterator9[_i9++]; + } else { + _i9 = _iterator9.next(); + if (_i9.done) break; + _ref12 = _i9.value; + } -// Copyright IBM Corp. 2014,2018. All Rights Reserved. -// Node module: strong-log-transformer -// This file is licensed under the Apache License 2.0. -// License text available at https://opensource.org/licenses/Apache-2.0 + const loc = _ref12; -module.exports = __webpack_require__(272); -module.exports.cli = __webpack_require__(276); + if (files.has(loc.toLowerCase())) { + possibleExtraneous.delete(loc); + } + } + return actions; + }); -/***/ }), -/* 272 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; -// Copyright IBM Corp. 2014,2018. All Rights Reserved. -// Node module: strong-log-transformer -// This file is licensed under the Apache License 2.0. -// License text available at https://opensource.org/licenses/Apache-2.0 + return function buildActionsForHardlink(_x6, _x7, _x8, _x9) { + return _ref9.apply(this, arguments); + }; +})(); +let copyBulk = exports.copyBulk = (() => { + var _ref17 = (0, (_asyncToGenerator2 || _load_asyncToGenerator()).default)(function* (queue, reporter, _events) { + const events = { + onStart: _events && _events.onStart || noop, + onProgress: _events && _events.onProgress || noop, + possibleExtraneous: _events ? _events.possibleExtraneous : new Set(), + ignoreBasenames: _events && _events.ignoreBasenames || [], + artifactFiles: _events && _events.artifactFiles || [] + }; + const actions = yield buildActionsForCopy(queue, events, events.possibleExtraneous, reporter); + events.onStart(actions.file.length + actions.symlink.length + actions.link.length); -var stream = __webpack_require__(137); -var util = __webpack_require__(111); -var fs = __webpack_require__(133); + const fileActions = actions.file; -var through = __webpack_require__(273); -var duplexer = __webpack_require__(274); -var StringDecoder = __webpack_require__(275).StringDecoder; + const currentlyWriting = new Map(); -module.exports = Logger; + yield (_promise || _load_promise()).queue(fileActions, (() => { + var _ref18 = (0, (_asyncToGenerator2 || _load_asyncToGenerator()).default)(function* (data) { + let writePromise; + while (writePromise = currentlyWriting.get(data.dest)) { + yield writePromise; + } -Logger.DEFAULTS = { - format: 'text', - tag: '', - mergeMultiline: false, - timeStamp: false, -}; + reporter.verbose(reporter.lang('verboseFileCopy', data.src, data.dest)); + const copier = (0, (_fsNormalized || _load_fsNormalized()).copyFile)(data, function () { + return currentlyWriting.delete(data.dest); + }); + currentlyWriting.set(data.dest, copier); + events.onProgress(data.dest); + return copier; + }); -var formatters = { - text: textFormatter, - json: jsonFormatter, -} + return function (_x14) { + return _ref18.apply(this, arguments); + }; + })(), CONCURRENT_QUEUE_ITEMS); -function Logger(options) { - var defaults = JSON.parse(JSON.stringify(Logger.DEFAULTS)); - options = util._extend(defaults, options || {}); - var catcher = deLiner(); - var emitter = catcher; - var transforms = [ - objectifier(), - ]; + // we need to copy symlinks last as they could reference files we were copying + const symlinkActions = actions.symlink; + yield (_promise || _load_promise()).queue(symlinkActions, function (data) { + const linkname = (_path || _load_path()).default.resolve((_path || _load_path()).default.dirname(data.dest), data.linkname); + reporter.verbose(reporter.lang('verboseFileSymlink', data.dest, linkname)); + return symlink(linkname, data.dest); + }); + }); - if (options.tag) { - transforms.push(staticTagger(options.tag)); - } + return function copyBulk(_x11, _x12, _x13) { + return _ref17.apply(this, arguments); + }; +})(); - if (options.mergeMultiline) { - transforms.push(lineMerger()); - } +let hardlinkBulk = exports.hardlinkBulk = (() => { + var _ref19 = (0, (_asyncToGenerator2 || _load_asyncToGenerator()).default)(function* (queue, reporter, _events) { + const events = { + onStart: _events && _events.onStart || noop, + onProgress: _events && _events.onProgress || noop, + possibleExtraneous: _events ? _events.possibleExtraneous : new Set(), + artifactFiles: _events && _events.artifactFiles || [], + ignoreBasenames: [] + }; - // TODO - // if (options.pidStamp) { - // transforms.push(pidStamper(options.pid)); - // } + const actions = yield buildActionsForHardlink(queue, events, events.possibleExtraneous, reporter); + events.onStart(actions.file.length + actions.symlink.length + actions.link.length); - // TODO - // if (options.workerStamp) { - // transforms.push(workerStamper(options.worker)); - // } + const fileActions = actions.link; - transforms.push(formatters[options.format](options)); + yield (_promise || _load_promise()).queue(fileActions, (() => { + var _ref20 = (0, (_asyncToGenerator2 || _load_asyncToGenerator()).default)(function* (data) { + reporter.verbose(reporter.lang('verboseFileLink', data.src, data.dest)); + if (data.removeDest) { + yield (0, (_fsNormalized || _load_fsNormalized()).unlink)(data.dest); + } + yield link(data.src, data.dest); + }); - // restore line endings that were removed by line splitting - transforms.push(reLiner()); + return function (_x18) { + return _ref20.apply(this, arguments); + }; + })(), CONCURRENT_QUEUE_ITEMS); - for (var t in transforms) { - emitter = emitter.pipe(transforms[t]); - } + // we need to copy symlinks last as they could reference files we were copying + const symlinkActions = actions.symlink; + yield (_promise || _load_promise()).queue(symlinkActions, function (data) { + const linkname = (_path || _load_path()).default.resolve((_path || _load_path()).default.dirname(data.dest), data.linkname); + reporter.verbose(reporter.lang('verboseFileSymlink', data.dest, linkname)); + return symlink(linkname, data.dest); + }); + }); - return duplexer(catcher, emitter); -} + return function hardlinkBulk(_x15, _x16, _x17) { + return _ref19.apply(this, arguments); + }; +})(); -function deLiner() { - var decoder = new StringDecoder('utf8'); - var last = ''; +let readFileAny = exports.readFileAny = (() => { + var _ref21 = (0, (_asyncToGenerator2 || _load_asyncToGenerator()).default)(function* (files) { + for (var _iterator13 = files, _isArray13 = Array.isArray(_iterator13), _i13 = 0, _iterator13 = _isArray13 ? _iterator13 : _iterator13[Symbol.iterator]();;) { + var _ref22; - return new stream.Transform({ - transform(chunk, _enc, callback) { - last += decoder.write(chunk); - var list = last.split(/\r\n|[\n\v\f\r\x85\u2028\u2029]/g); - last = list.pop(); - for (var i = 0; i < list.length; i++) { - // swallow empty lines - if (list[i]) { - this.push(list[i]); - } + if (_isArray13) { + if (_i13 >= _iterator13.length) break; + _ref22 = _iterator13[_i13++]; + } else { + _i13 = _iterator13.next(); + if (_i13.done) break; + _ref22 = _i13.value; } - callback(); - }, - flush(callback) { - // incomplete UTF8 sequences become UTF8 replacement characters - last += decoder.end(); - if (last) { - this.push(last); + + const file = _ref22; + + if (yield exists(file)) { + return readFile(file); } - callback(); - }, + } + return null; }); -} -function reLiner() { - return through(appendNewline); + return function readFileAny(_x19) { + return _ref21.apply(this, arguments); + }; +})(); - function appendNewline(line) { - this.emit('data', line + '\n'); - } -} +let readJson = exports.readJson = (() => { + var _ref23 = (0, (_asyncToGenerator2 || _load_asyncToGenerator()).default)(function* (loc) { + return (yield readJsonAndFile(loc)).object; + }); -function objectifier() { - return through(objectify, null, {autoDestroy: false}); + return function readJson(_x20) { + return _ref23.apply(this, arguments); + }; +})(); - function objectify(line) { - this.emit('data', { - msg: line, - time: Date.now(), - }); - } -} +let readJsonAndFile = exports.readJsonAndFile = (() => { + var _ref24 = (0, (_asyncToGenerator2 || _load_asyncToGenerator()).default)(function* (loc) { + const file = yield readFile(loc); + try { + return { + object: (0, (_map || _load_map()).default)(JSON.parse(stripBOM(file))), + content: file + }; + } catch (err) { + err.message = `${loc}: ${err.message}`; + throw err; + } + }); -function staticTagger(tag) { - return through(tagger); + return function readJsonAndFile(_x21) { + return _ref24.apply(this, arguments); + }; +})(); - function tagger(logEvent) { - logEvent.tag = tag; - this.emit('data', logEvent); - } -} +let find = exports.find = (() => { + var _ref25 = (0, (_asyncToGenerator2 || _load_asyncToGenerator()).default)(function* (filename, dir) { + const parts = dir.split((_path || _load_path()).default.sep); -function textFormatter(options) { - return through(textify); + while (parts.length) { + const loc = parts.concat(filename).join((_path || _load_path()).default.sep); - function textify(logEvent) { - var line = util.format('%s%s', textifyTags(logEvent.tag), - logEvent.msg.toString()); - if (options.timeStamp) { - line = util.format('%s %s', new Date(logEvent.time).toISOString(), line); + if (yield exists(loc)) { + return loc; + } else { + parts.pop(); + } } - this.emit('data', line.replace(/\n/g, '\\n')); - } - function textifyTags(tags) { - var str = ''; - if (typeof tags === 'string') { - str = tags + ' '; - } else if (typeof tags === 'object') { - for (var t in tags) { - str += t + ':' + tags[t] + ' '; + return false; + }); + + return function find(_x22, _x23) { + return _ref25.apply(this, arguments); + }; +})(); + +let symlink = exports.symlink = (() => { + var _ref26 = (0, (_asyncToGenerator2 || _load_asyncToGenerator()).default)(function* (src, dest) { + try { + const stats = yield lstat(dest); + if (stats.isSymbolicLink()) { + const resolved = yield realpath(dest); + if (resolved === src) { + return; + } + } + } catch (err) { + if (err.code !== 'ENOENT') { + throw err; } } - return str; - } -} - -function jsonFormatter(options) { - return through(jsonify); + // We use rimraf for unlink which never throws an ENOENT on missing target + yield (0, (_fsNormalized || _load_fsNormalized()).unlink)(dest); - function jsonify(logEvent) { - if (options.timeStamp) { - logEvent.time = new Date(logEvent.time).toISOString(); + if (process.platform === 'win32') { + // use directory junctions if possible on win32, this requires absolute paths + yield fsSymlink(src, dest, 'junction'); } else { - delete logEvent.time; + // use relative paths otherwise which will be retained if the directory is moved + let relative; + try { + relative = (_path || _load_path()).default.relative((_fs || _load_fs()).default.realpathSync((_path || _load_path()).default.dirname(dest)), (_fs || _load_fs()).default.realpathSync(src)); + } catch (err) { + if (err.code !== 'ENOENT') { + throw err; + } + relative = (_path || _load_path()).default.relative((_path || _load_path()).default.dirname(dest), src); + } + // When path.relative returns an empty string for the current directory, we should instead use + // '.', which is a valid fs.symlink target. + yield fsSymlink(relative || '.', dest); } - logEvent.msg = logEvent.msg.toString(); - this.emit('data', JSON.stringify(logEvent)); - } -} + }); -function lineMerger(host) { - var previousLine = null; - var flushTimer = null; - var stream = through(lineMergerWrite, lineMergerEnd); - var flush = _flush.bind(stream); + return function symlink(_x24, _x25) { + return _ref26.apply(this, arguments); + }; +})(); - return stream; +let walk = exports.walk = (() => { + var _ref27 = (0, (_asyncToGenerator2 || _load_asyncToGenerator()).default)(function* (dir, relativeDir, ignoreBasenames = new Set()) { + let files = []; - function lineMergerWrite(line) { - if (/^\s+/.test(line.msg)) { - if (previousLine) { - previousLine.msg += '\n' + line.msg; + let filenames = yield readdir(dir); + if (ignoreBasenames.size) { + filenames = filenames.filter(function (name) { + return !ignoreBasenames.has(name); + }); + } + + for (var _iterator14 = filenames, _isArray14 = Array.isArray(_iterator14), _i14 = 0, _iterator14 = _isArray14 ? _iterator14 : _iterator14[Symbol.iterator]();;) { + var _ref28; + + if (_isArray14) { + if (_i14 >= _iterator14.length) break; + _ref28 = _iterator14[_i14++]; } else { - previousLine = line; + _i14 = _iterator14.next(); + if (_i14.done) break; + _ref28 = _i14.value; } - } else { - flush(); - previousLine = line; - } - // rolling timeout - clearTimeout(flushTimer); - flushTimer = setTimeout(flush.bind(this), 10); - } - function _flush() { - if (previousLine) { - this.emit('data', previousLine); - previousLine = null; - } - } + const name = _ref28; - function lineMergerEnd() { - flush.call(this); - this.emit('end'); - } -} + const relative = relativeDir ? (_path || _load_path()).default.join(relativeDir, name) : name; + const loc = (_path || _load_path()).default.join(dir, name); + const stat = yield lstat(loc); + files.push({ + relative, + basename: name, + absolute: loc, + mtime: +stat.mtime + }); -/***/ }), -/* 273 */ -/***/ (function(module, exports, __webpack_require__) { + if (stat.isDirectory()) { + files = files.concat((yield walk(loc, relative, ignoreBasenames))); + } + } -var Stream = __webpack_require__(137) + return files; + }); -// through -// -// a stream that does nothing but re-emit the input. -// useful for aggregating a series of changing but not ending streams into one stream) + return function walk(_x26, _x27) { + return _ref27.apply(this, arguments); + }; +})(); -exports = module.exports = through -through.through = through +let getFileSizeOnDisk = exports.getFileSizeOnDisk = (() => { + var _ref29 = (0, (_asyncToGenerator2 || _load_asyncToGenerator()).default)(function* (loc) { + const stat = yield lstat(loc); + const size = stat.size, + blockSize = stat.blksize; -//create a readable writable stream. -function through (write, end, opts) { - write = write || function (data) { this.queue(data) } - end = end || function () { this.queue(null) } + return Math.ceil(size / blockSize) * blockSize; + }); - var ended = false, destroyed = false, buffer = [], _ended = false - var stream = new Stream() - stream.readable = stream.writable = true - stream.paused = false + return function getFileSizeOnDisk(_x28) { + return _ref29.apply(this, arguments); + }; +})(); -// stream.autoPause = !(opts && opts.autoPause === false) - stream.autoDestroy = !(opts && opts.autoDestroy === false) +let getEolFromFile = (() => { + var _ref30 = (0, (_asyncToGenerator2 || _load_asyncToGenerator()).default)(function* (path) { + if (!(yield exists(path))) { + return undefined; + } - stream.write = function (data) { - write.call(this, data) - return !stream.paused - } + const buffer = yield readFileBuffer(path); - function drain() { - while(buffer.length && !stream.paused) { - var data = buffer.shift() - if(null === data) - return stream.emit('end') - else - stream.emit('data', data) + for (let i = 0; i < buffer.length; ++i) { + if (buffer[i] === cr) { + return '\r\n'; + } + if (buffer[i] === lf) { + return '\n'; + } } - } + return undefined; + }); - stream.queue = stream.push = function (data) { -// console.error(ended) - if(_ended) return stream - if(data === null) _ended = true - buffer.push(data) - drain() - return stream - } + return function getEolFromFile(_x29) { + return _ref30.apply(this, arguments); + }; +})(); - //this will be registered as the first 'end' listener - //must call destroy next tick, to make sure we're after any - //stream piped from here. - //this is only a problem if end is not emitted synchronously. - //a nicer way to do this is to make sure this is the last listener for 'end' +let writeFilePreservingEol = exports.writeFilePreservingEol = (() => { + var _ref31 = (0, (_asyncToGenerator2 || _load_asyncToGenerator()).default)(function* (path, data) { + const eol = (yield getEolFromFile(path)) || (_os || _load_os()).default.EOL; + if (eol !== '\n') { + data = data.replace(/\n/g, eol); + } + yield writeFile(path, data); + }); - stream.on('end', function () { - stream.readable = false - if(!stream.writable && stream.autoDestroy) - process.nextTick(function () { - stream.destroy() - }) - }) + return function writeFilePreservingEol(_x30, _x31) { + return _ref31.apply(this, arguments); + }; +})(); - function _end () { - stream.writable = false - end.call(stream) - if(!stream.readable && stream.autoDestroy) - stream.destroy() - } +let hardlinksWork = exports.hardlinksWork = (() => { + var _ref32 = (0, (_asyncToGenerator2 || _load_asyncToGenerator()).default)(function* (dir) { + const filename = 'test-file' + Math.random(); + const file = (_path || _load_path()).default.join(dir, filename); + const fileLink = (_path || _load_path()).default.join(dir, filename + '-link'); + try { + yield writeFile(file, 'test'); + yield link(file, fileLink); + } catch (err) { + return false; + } finally { + yield (0, (_fsNormalized || _load_fsNormalized()).unlink)(file); + yield (0, (_fsNormalized || _load_fsNormalized()).unlink)(fileLink); + } + return true; + }); - stream.end = function (data) { - if(ended) return - ended = true - if(arguments.length) stream.write(data) - _end() // will emit or queue - return stream - } + return function hardlinksWork(_x32) { + return _ref32.apply(this, arguments); + }; +})(); - stream.destroy = function () { - if(destroyed) return - destroyed = true - ended = true - buffer.length = 0 - stream.writable = stream.readable = false - stream.emit('close') - return stream - } +// not a strict polyfill for Node's fs.mkdtemp - stream.pause = function () { - if(stream.paused) return - stream.paused = true - return stream - } - stream.resume = function () { - if(stream.paused) { - stream.paused = false - stream.emit('resume') +let makeTempDir = exports.makeTempDir = (() => { + var _ref33 = (0, (_asyncToGenerator2 || _load_asyncToGenerator()).default)(function* (prefix) { + const dir = (_path || _load_path()).default.join((_os || _load_os()).default.tmpdir(), `yarn-${prefix || ''}-${Date.now()}-${Math.random()}`); + yield (0, (_fsNormalized || _load_fsNormalized()).unlink)(dir); + yield mkdirp(dir); + return dir; + }); + + return function makeTempDir(_x33) { + return _ref33.apply(this, arguments); + }; +})(); + +let readFirstAvailableStream = exports.readFirstAvailableStream = (() => { + var _ref34 = (0, (_asyncToGenerator2 || _load_asyncToGenerator()).default)(function* (paths) { + for (var _iterator15 = paths, _isArray15 = Array.isArray(_iterator15), _i15 = 0, _iterator15 = _isArray15 ? _iterator15 : _iterator15[Symbol.iterator]();;) { + var _ref35; + + if (_isArray15) { + if (_i15 >= _iterator15.length) break; + _ref35 = _iterator15[_i15++]; + } else { + _i15 = _iterator15.next(); + if (_i15.done) break; + _ref35 = _i15.value; + } + + const path = _ref35; + + try { + const fd = yield open(path, 'r'); + return (_fs || _load_fs()).default.createReadStream(path, { fd }); + } catch (err) { + // Try the next one + } } - drain() - //may have become paused again, - //as drain emits 'data'. - if(!stream.paused) - stream.emit('drain') - return stream - } - return stream -} + return null; + }); + + return function readFirstAvailableStream(_x34) { + return _ref34.apply(this, arguments); + }; +})(); + +let getFirstSuitableFolder = exports.getFirstSuitableFolder = (() => { + var _ref36 = (0, (_asyncToGenerator2 || _load_asyncToGenerator()).default)(function* (paths, mode = constants.W_OK | constants.X_OK) { + const result = { + skipped: [], + folder: null + }; + for (var _iterator16 = paths, _isArray16 = Array.isArray(_iterator16), _i16 = 0, _iterator16 = _isArray16 ? _iterator16 : _iterator16[Symbol.iterator]();;) { + var _ref37; + if (_isArray16) { + if (_i16 >= _iterator16.length) break; + _ref37 = _iterator16[_i16++]; + } else { + _i16 = _iterator16.next(); + if (_i16.done) break; + _ref37 = _i16.value; + } -/***/ }), -/* 274 */ -/***/ (function(module, exports, __webpack_require__) { + const folder = _ref37; -var Stream = __webpack_require__(137) -var writeMethods = ["write", "end", "destroy"] -var readMethods = ["resume", "pause"] -var readEvents = ["data", "close"] -var slice = Array.prototype.slice + try { + yield mkdirp(folder); + yield access(folder, mode); -module.exports = duplex + result.folder = folder; -function forEach (arr, fn) { - if (arr.forEach) { - return arr.forEach(fn) + return result; + } catch (error) { + result.skipped.push({ + error, + folder + }); + } } + return result; + }); - for (var i = 0; i < arr.length; i++) { - fn(arr[i], i) - } + return function getFirstSuitableFolder(_x35) { + return _ref36.apply(this, arguments); + }; +})(); + +exports.copy = copy; +exports.readFile = readFile; +exports.readFileRaw = readFileRaw; +exports.normalizeOS = normalizeOS; + +var _fs; + +function _load_fs() { + return _fs = _interopRequireDefault(__webpack_require__(3)); } -function duplex(writer, reader) { - var stream = new Stream() - var ended = false +var _glob; - forEach(writeMethods, proxyWriter) +function _load_glob() { + return _glob = _interopRequireDefault(__webpack_require__(75)); +} - forEach(readMethods, proxyReader) +var _os; - forEach(readEvents, proxyStream) +function _load_os() { + return _os = _interopRequireDefault(__webpack_require__(36)); +} - reader.on("end", handleEnd) +var _path; - writer.on("drain", function() { - stream.emit("drain") - }) +function _load_path() { + return _path = _interopRequireDefault(__webpack_require__(0)); +} - writer.on("error", reemit) - reader.on("error", reemit) +var _blockingQueue; - stream.writable = writer.writable - stream.readable = reader.readable +function _load_blockingQueue() { + return _blockingQueue = _interopRequireDefault(__webpack_require__(84)); +} - return stream +var _promise; - function proxyWriter(methodName) { - stream[methodName] = method +function _load_promise() { + return _promise = _interopRequireWildcard(__webpack_require__(40)); +} - function method() { - return writer[methodName].apply(writer, arguments) - } - } +var _promise2; - function proxyReader(methodName) { - stream[methodName] = method +function _load_promise2() { + return _promise2 = __webpack_require__(40); +} - function method() { - stream.emit(methodName) - var func = reader[methodName] - if (func) { - return func.apply(reader, arguments) - } - reader.emit(methodName) - } - } +var _map; - function proxyStream(methodName) { - reader.on(methodName, reemit) +function _load_map() { + return _map = _interopRequireDefault(__webpack_require__(20)); +} - function reemit() { - var args = slice.call(arguments) - args.unshift(methodName) - stream.emit.apply(stream, args) - } - } +var _fsNormalized; - function handleEnd() { - if (ended) { - return - } - ended = true - var args = slice.call(arguments) - args.unshift("end") - stream.emit.apply(stream, args) - } +function _load_fsNormalized() { + return _fsNormalized = __webpack_require__(164); +} - function reemit(err) { - stream.emit("error", err) - } +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const constants = exports.constants = typeof (_fs || _load_fs()).default.constants !== 'undefined' ? (_fs || _load_fs()).default.constants : { + R_OK: (_fs || _load_fs()).default.R_OK, + W_OK: (_fs || _load_fs()).default.W_OK, + X_OK: (_fs || _load_fs()).default.X_OK +}; + +const lockQueue = exports.lockQueue = new (_blockingQueue || _load_blockingQueue()).default('fs lock'); + +const readFileBuffer = exports.readFileBuffer = (0, (_promise2 || _load_promise2()).promisify)((_fs || _load_fs()).default.readFile); +const open = exports.open = (0, (_promise2 || _load_promise2()).promisify)((_fs || _load_fs()).default.open); +const writeFile = exports.writeFile = (0, (_promise2 || _load_promise2()).promisify)((_fs || _load_fs()).default.writeFile); +const readlink = exports.readlink = (0, (_promise2 || _load_promise2()).promisify)((_fs || _load_fs()).default.readlink); +const realpath = exports.realpath = (0, (_promise2 || _load_promise2()).promisify)((_fs || _load_fs()).default.realpath); +const readdir = exports.readdir = (0, (_promise2 || _load_promise2()).promisify)((_fs || _load_fs()).default.readdir); +const rename = exports.rename = (0, (_promise2 || _load_promise2()).promisify)((_fs || _load_fs()).default.rename); +const access = exports.access = (0, (_promise2 || _load_promise2()).promisify)((_fs || _load_fs()).default.access); +const stat = exports.stat = (0, (_promise2 || _load_promise2()).promisify)((_fs || _load_fs()).default.stat); +const mkdirp = exports.mkdirp = (0, (_promise2 || _load_promise2()).promisify)(__webpack_require__(116)); +const exists = exports.exists = (0, (_promise2 || _load_promise2()).promisify)((_fs || _load_fs()).default.exists, true); +const lstat = exports.lstat = (0, (_promise2 || _load_promise2()).promisify)((_fs || _load_fs()).default.lstat); +const chmod = exports.chmod = (0, (_promise2 || _load_promise2()).promisify)((_fs || _load_fs()).default.chmod); +const link = exports.link = (0, (_promise2 || _load_promise2()).promisify)((_fs || _load_fs()).default.link); +const glob = exports.glob = (0, (_promise2 || _load_promise2()).promisify)((_glob || _load_glob()).default); +exports.unlink = (_fsNormalized || _load_fsNormalized()).unlink; + +// fs.copyFile uses the native file copying instructions on the system, performing much better +// than any JS-based solution and consumes fewer resources. Repeated testing to fine tune the +// concurrency level revealed 128 as the sweet spot on a quad-core, 16 CPU Intel system with SSD. + +const CONCURRENT_QUEUE_ITEMS = (_fs || _load_fs()).default.copyFile ? 128 : 4; + +const fsSymlink = (0, (_promise2 || _load_promise2()).promisify)((_fs || _load_fs()).default.symlink); +const invariant = __webpack_require__(7); +const stripBOM = __webpack_require__(122); + +const noop = () => {}; + +function copy(src, dest, reporter) { + return copyBulk([{ src, dest }], reporter); +} + +function _readFile(loc, encoding) { + return new Promise((resolve, reject) => { + (_fs || _load_fs()).default.readFile(loc, encoding, function (err, content) { + if (err) { + reject(err); + } else { + resolve(content); + } + }); + }); } +function readFile(loc) { + return _readFile(loc, 'utf8').then(normalizeOS); +} -/***/ }), -/* 275 */ -/***/ (function(module, exports) { +function readFileRaw(loc) { + return _readFile(loc, 'binary'); +} -module.exports = require("string_decoder"); +function normalizeOS(body) { + return body.replace(/\r\n/g, '\n'); +} + +const cr = '\r'.charCodeAt(0); +const lf = '\n'.charCodeAt(0); /***/ }), -/* 276 */ +/* 6 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -// Copyright IBM Corp. 2014,2018. All Rights Reserved. -// Node module: strong-log-transformer -// This file is licensed under the Apache License 2.0. -// License text available at https://opensource.org/licenses/Apache-2.0 +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.getPathKey = getPathKey; +const os = __webpack_require__(36); +const path = __webpack_require__(0); +const userHome = __webpack_require__(45).default; -var minimist = __webpack_require__(277); -var path = __webpack_require__(4); +var _require = __webpack_require__(171); -var Logger = __webpack_require__(272); -var pkg = __webpack_require__(278); +const getCacheDir = _require.getCacheDir, + getConfigDir = _require.getConfigDir, + getDataDir = _require.getDataDir; -module.exports = cli; +const isWebpackBundle = __webpack_require__(227); -function cli(args) { - var opts = minimist(args.slice(2)); - var $0 = path.basename(args[1]); - var p = console.log.bind(console); - if (opts.v || opts.version) { - version($0, p); - } else if (opts.h || opts.help) { - usage($0, p); - } else if (args.length < 3) { - process.stdin.pipe(Logger()).pipe(process.stdout); - } else { - process.stdin.pipe(Logger(opts)).pipe(process.stdout); +const DEPENDENCY_TYPES = exports.DEPENDENCY_TYPES = ['devDependencies', 'dependencies', 'optionalDependencies', 'peerDependencies']; +const RESOLUTIONS = exports.RESOLUTIONS = 'resolutions'; +const MANIFEST_FIELDS = exports.MANIFEST_FIELDS = [RESOLUTIONS, ...DEPENDENCY_TYPES]; + +const SUPPORTED_NODE_VERSIONS = exports.SUPPORTED_NODE_VERSIONS = '^4.8.0 || ^5.7.0 || ^6.2.2 || >=8.0.0'; + +const YARN_REGISTRY = exports.YARN_REGISTRY = 'https://registry.yarnpkg.com'; + +const YARN_DOCS = exports.YARN_DOCS = 'https://yarnpkg.com/en/docs/cli/'; +const YARN_INSTALLER_SH = exports.YARN_INSTALLER_SH = 'https://yarnpkg.com/install.sh'; +const YARN_INSTALLER_MSI = exports.YARN_INSTALLER_MSI = 'https://yarnpkg.com/latest.msi'; + +const SELF_UPDATE_VERSION_URL = exports.SELF_UPDATE_VERSION_URL = 'https://yarnpkg.com/latest-version'; + +// cache version, bump whenever we make backwards incompatible changes +const CACHE_VERSION = exports.CACHE_VERSION = 2; + +// lockfile version, bump whenever we make backwards incompatible changes +const LOCKFILE_VERSION = exports.LOCKFILE_VERSION = 1; + +// max amount of network requests to perform concurrently +const NETWORK_CONCURRENCY = exports.NETWORK_CONCURRENCY = 8; + +// HTTP timeout used when downloading packages +const NETWORK_TIMEOUT = exports.NETWORK_TIMEOUT = 30 * 1000; // in milliseconds + +// max amount of child processes to execute concurrently +const CHILD_CONCURRENCY = exports.CHILD_CONCURRENCY = 5; + +const REQUIRED_PACKAGE_KEYS = exports.REQUIRED_PACKAGE_KEYS = ['name', 'version', '_uid']; + +function getPreferredCacheDirectories() { + const preferredCacheDirectories = [getCacheDir()]; + + if (process.getuid) { + // $FlowFixMe: process.getuid exists, dammit + preferredCacheDirectories.push(path.join(os.tmpdir(), `.yarn-cache-${process.getuid()}`)); } -} -function version($0, p) { - p('%s v%s', pkg.name, pkg.version); + preferredCacheDirectories.push(path.join(os.tmpdir(), `.yarn-cache`)); + + return preferredCacheDirectories; } -function usage($0, p) { - var PADDING = ' '; - var opt, def; - p('Usage: %s [options]', $0); - p(''); - p('%s', pkg.description); - p(''); - p('OPTIONS:'); - for (opt in Logger.DEFAULTS) { - def = Logger.DEFAULTS[opt]; - if (typeof def === 'boolean') - boolOpt(opt, Logger.DEFAULTS[opt]); - else - stdOpt(opt, Logger.DEFAULTS[opt]); - } - p(''); +const PREFERRED_MODULE_CACHE_DIRECTORIES = exports.PREFERRED_MODULE_CACHE_DIRECTORIES = getPreferredCacheDirectories(); +const CONFIG_DIRECTORY = exports.CONFIG_DIRECTORY = getConfigDir(); +const DATA_DIRECTORY = exports.DATA_DIRECTORY = getDataDir(); +const LINK_REGISTRY_DIRECTORY = exports.LINK_REGISTRY_DIRECTORY = path.join(DATA_DIRECTORY, 'link'); +const GLOBAL_MODULE_DIRECTORY = exports.GLOBAL_MODULE_DIRECTORY = path.join(DATA_DIRECTORY, 'global'); - function boolOpt(name, def) { - name = name + PADDING.slice(0, 20-name.length); - p(' --%s default: %s', name, def); - } +const NODE_BIN_PATH = exports.NODE_BIN_PATH = process.execPath; +const YARN_BIN_PATH = exports.YARN_BIN_PATH = getYarnBinPath(); - function stdOpt(name, def) { - var value = name.toUpperCase() + - PADDING.slice(0, 19 - name.length*2); - p(' --%s %s default: %j', name, value, def); +// Webpack needs to be configured with node.__dirname/__filename = false +function getYarnBinPath() { + if (isWebpackBundle) { + return __filename; + } else { + return path.join(__dirname, '..', 'bin', 'yarn.js'); } } +const NODE_MODULES_FOLDER = exports.NODE_MODULES_FOLDER = 'node_modules'; +const NODE_PACKAGE_JSON = exports.NODE_PACKAGE_JSON = 'package.json'; -/***/ }), -/* 277 */ -/***/ (function(module, exports) { +const POSIX_GLOBAL_PREFIX = exports.POSIX_GLOBAL_PREFIX = `${process.env.DESTDIR || ''}/usr/local`; +const FALLBACK_GLOBAL_PREFIX = exports.FALLBACK_GLOBAL_PREFIX = path.join(userHome, '.yarn'); -module.exports = function (args, opts) { - if (!opts) opts = {}; - - var flags = { bools : {}, strings : {}, unknownFn: null }; +const META_FOLDER = exports.META_FOLDER = '.yarn-meta'; +const INTEGRITY_FILENAME = exports.INTEGRITY_FILENAME = '.yarn-integrity'; +const LOCKFILE_FILENAME = exports.LOCKFILE_FILENAME = 'yarn.lock'; +const METADATA_FILENAME = exports.METADATA_FILENAME = '.yarn-metadata.json'; +const TARBALL_FILENAME = exports.TARBALL_FILENAME = '.yarn-tarball.tgz'; +const CLEAN_FILENAME = exports.CLEAN_FILENAME = '.yarnclean'; - if (typeof opts['unknown'] === 'function') { - flags.unknownFn = opts['unknown']; - } +const NPM_LOCK_FILENAME = exports.NPM_LOCK_FILENAME = 'package-lock.json'; +const NPM_SHRINKWRAP_FILENAME = exports.NPM_SHRINKWRAP_FILENAME = 'npm-shrinkwrap.json'; - if (typeof opts['boolean'] === 'boolean' && opts['boolean']) { - flags.allBools = true; - } else { - [].concat(opts['boolean']).filter(Boolean).forEach(function (key) { - flags.bools[key] = true; - }); - } - - var aliases = {}; - Object.keys(opts.alias || {}).forEach(function (key) { - aliases[key] = [].concat(opts.alias[key]); - aliases[key].forEach(function (x) { - aliases[x] = [key].concat(aliases[key].filter(function (y) { - return x !== y; - })); - }); - }); +const DEFAULT_INDENT = exports.DEFAULT_INDENT = ' '; +const SINGLE_INSTANCE_PORT = exports.SINGLE_INSTANCE_PORT = 31997; +const SINGLE_INSTANCE_FILENAME = exports.SINGLE_INSTANCE_FILENAME = '.yarn-single-instance'; - [].concat(opts.string).filter(Boolean).forEach(function (key) { - flags.strings[key] = true; - if (aliases[key]) { - flags.strings[aliases[key]] = true; - } - }); +const ENV_PATH_KEY = exports.ENV_PATH_KEY = getPathKey(process.platform, process.env); - var defaults = opts['default'] || {}; - - var argv = { _ : [] }; - Object.keys(flags.bools).forEach(function (key) { - setArg(key, defaults[key] === undefined ? false : defaults[key]); - }); - - var notFlags = []; +function getPathKey(platform, env) { + let pathKey = 'PATH'; - if (args.indexOf('--') !== -1) { - notFlags = args.slice(args.indexOf('--')+1); - args = args.slice(0, args.indexOf('--')); - } + // windows calls its path "Path" usually, but this is not guaranteed. + if (platform === 'win32') { + pathKey = 'Path'; - function argDefined(key, arg) { - return (flags.allBools && /^--[^=]+$/.test(arg)) || - flags.strings[key] || flags.bools[key] || aliases[key]; + for (const key in env) { + if (key.toLowerCase() === 'path') { + pathKey = key; + } } + } - function setArg (key, val, arg) { - if (arg && flags.unknownFn && !argDefined(key, arg)) { - if (flags.unknownFn(arg) === false) return; - } + return pathKey; +} - var value = !flags.strings[key] && isNumber(val) - ? Number(val) : val - ; - setKey(argv, key.split('.'), value); - - (aliases[key] || []).forEach(function (x) { - setKey(argv, x.split('.'), value); - }); - } +const VERSION_COLOR_SCHEME = exports.VERSION_COLOR_SCHEME = { + major: 'red', + premajor: 'red', + minor: 'yellow', + preminor: 'yellow', + patch: 'green', + prepatch: 'green', + prerelease: 'red', + unchanged: 'white', + unknown: 'red' +}; - function setKey (obj, keys, value) { - var o = obj; - for (var i = 0; i < keys.length-1; i++) { - var key = keys[i]; - if (key === '__proto__') return; - if (o[key] === undefined) o[key] = {}; - if (o[key] === Object.prototype || o[key] === Number.prototype - || o[key] === String.prototype) o[key] = {}; - if (o[key] === Array.prototype) o[key] = []; - o = o[key]; - } +/***/ }), +/* 7 */ +/***/ (function(module, exports, __webpack_require__) { - var key = keys[keys.length - 1]; - if (key === '__proto__') return; - if (o === Object.prototype || o === Number.prototype - || o === String.prototype) o = {}; - if (o === Array.prototype) o = []; - if (o[key] === undefined || flags.bools[key] || typeof o[key] === 'boolean') { - o[key] = value; - } - else if (Array.isArray(o[key])) { - o[key].push(value); - } - else { - o[key] = [ o[key], value ]; - } - } - - function aliasIsBoolean(key) { - return aliases[key].some(function (x) { - return flags.bools[x]; - }); - } +"use strict"; +/** + * Copyright (c) 2013-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ - for (var i = 0; i < args.length; i++) { - var arg = args[i]; - - if (/^--.+=/.test(arg)) { - // Using [\s\S] instead of . because js doesn't support the - // 'dotall' regex modifier. See: - // http://stackoverflow.com/a/1068308/13216 - var m = arg.match(/^--([^=]+)=([\s\S]*)$/); - var key = m[1]; - var value = m[2]; - if (flags.bools[key]) { - value = value !== 'false'; - } - setArg(key, value, arg); - } - else if (/^--no-.+/.test(arg)) { - var key = arg.match(/^--no-(.+)/)[1]; - setArg(key, false, arg); - } - else if (/^--.+/.test(arg)) { - var key = arg.match(/^--(.+)/)[1]; - var next = args[i + 1]; - if (next !== undefined && !/^-/.test(next) - && !flags.bools[key] - && !flags.allBools - && (aliases[key] ? !aliasIsBoolean(key) : true)) { - setArg(key, next, arg); - i++; - } - else if (/^(true|false)$/.test(next)) { - setArg(key, next === 'true', arg); - i++; - } - else { - setArg(key, flags.strings[key] ? '' : true, arg); - } - } - else if (/^-[^-]+/.test(arg)) { - var letters = arg.slice(1,-1).split(''); - - var broken = false; - for (var j = 0; j < letters.length; j++) { - var next = arg.slice(j+2); - - if (next === '-') { - setArg(letters[j], next, arg) - continue; - } - - if (/[A-Za-z]/.test(letters[j]) && /=/.test(next)) { - setArg(letters[j], next.split('=')[1], arg); - broken = true; - break; - } - - if (/[A-Za-z]/.test(letters[j]) - && /-?\d+(\.\d*)?(e-?\d+)?$/.test(next)) { - setArg(letters[j], next, arg); - broken = true; - break; - } - - if (letters[j+1] && letters[j+1].match(/\W/)) { - setArg(letters[j], arg.slice(j+2), arg); - broken = true; - break; - } - else { - setArg(letters[j], flags.strings[letters[j]] ? '' : true, arg); - } - } - - var key = arg.slice(-1)[0]; - if (!broken && key !== '-') { - if (args[i+1] && !/^(-|--)[^-]/.test(args[i+1]) - && !flags.bools[key] - && (aliases[key] ? !aliasIsBoolean(key) : true)) { - setArg(key, args[i+1], arg); - i++; - } - else if (args[i+1] && /^(true|false)$/.test(args[i+1])) { - setArg(key, args[i+1] === 'true', arg); - i++; - } - else { - setArg(key, flags.strings[key] ? '' : true, arg); - } - } - } - else { - if (!flags.unknownFn || flags.unknownFn(arg) !== false) { - argv._.push( - flags.strings['_'] || !isNumber(arg) ? arg : Number(arg) - ); - } - if (opts.stopEarly) { - argv._.push.apply(argv._, args.slice(i + 1)); - break; - } - } - } - - Object.keys(defaults).forEach(function (key) { - if (!hasKey(argv, key.split('.'))) { - setKey(argv, key.split('.'), defaults[key]); - - (aliases[key] || []).forEach(function (x) { - setKey(argv, x.split('.'), defaults[key]); - }); - } - }); - - if (opts['--']) { - argv['--'] = new Array(); - notFlags.forEach(function(key) { - argv['--'].push(key); - }); + + +/** + * Use invariant() to assert state which your program assumes to be true. + * + * Provide sprintf-style format (only %s is supported) and arguments + * to provide information about what broke and what you were + * expecting. + * + * The invariant message will be stripped in production, but the invariant + * will remain to ensure logic does not differ in production. + */ + +var NODE_ENV = "none"; + +var invariant = function(condition, format, a, b, c, d, e, f) { + if (NODE_ENV !== 'production') { + if (format === undefined) { + throw new Error('invariant requires an error message argument'); } - else { - notFlags.forEach(function(key) { - argv._.push(key); - }); + } + + if (!condition) { + var error; + if (format === undefined) { + error = new Error( + 'Minified exception occurred; use the non-minified dev environment ' + + 'for the full error message and additional helpful warnings.' + ); + } else { + var args = [a, b, c, d, e, f]; + var argIndex = 0; + error = new Error( + format.replace(/%s/g, function() { return args[argIndex++]; }) + ); + error.name = 'Invariant Violation'; } - return argv; + error.framesToPop = 1; // we don't care about invariant's own frame + throw error; + } }; -function hasKey (obj, keys) { - var o = obj; - keys.slice(0,-1).forEach(function (key) { - o = (o[key] || {}); - }); - - var key = keys[keys.length - 1]; - return key in o; -} +module.exports = invariant; -function isNumber (x) { - if (typeof x === 'number') return true; - if (/^0x[0-9a-f]+$/i.test(x)) return true; - return /^[-+]?(?:\d+(?:\.\d*)?|\.\d+)(e[-+]?\d+)?$/.test(x); -} +/***/ }), +/* 8 */, +/* 9 */ +/***/ (function(module, exports) { +module.exports = __webpack_require__(274); /***/ }), -/* 278 */ -/***/ (function(module) { +/* 10 */, +/* 11 */ +/***/ (function(module, exports) { + +// https://github.com/zloirock/core-js/issues/86#issuecomment-115759028 +var global = module.exports = typeof window != 'undefined' && window.Math == Math + ? window : typeof self != 'undefined' && self.Math == Math ? self + // eslint-disable-next-line no-new-func + : Function('return this')(); +if (typeof __g == 'number') __g = global; // eslint-disable-line no-undef -module.exports = JSON.parse("{\"name\":\"strong-log-transformer\",\"version\":\"2.1.0\",\"description\":\"Stream transformer that prefixes lines with timestamps and other things.\",\"author\":\"Ryan Graham \",\"license\":\"Apache-2.0\",\"repository\":{\"type\":\"git\",\"url\":\"git://github.com/strongloop/strong-log-transformer\"},\"keywords\":[\"logging\",\"streams\"],\"bugs\":{\"url\":\"https://github.com/strongloop/strong-log-transformer/issues\"},\"homepage\":\"https://github.com/strongloop/strong-log-transformer\",\"directories\":{\"test\":\"test\"},\"bin\":{\"sl-log-transformer\":\"bin/sl-log-transformer.js\"},\"main\":\"index.js\",\"scripts\":{\"test\":\"tap --100 test/test-*\"},\"dependencies\":{\"duplexer\":\"^0.1.1\",\"minimist\":\"^1.2.0\",\"through\":\"^2.3.4\"},\"devDependencies\":{\"tap\":\"^12.0.1\"},\"engines\":{\"node\":\">=4\"}}"); /***/ }), -/* 279 */ -/***/ (function(module, __webpack_exports__, __webpack_require__) { +/* 12 */ +/***/ (function(module, exports, __webpack_require__) { "use strict"; -__webpack_require__.r(__webpack_exports__); -/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "workspacePackagePaths", function() { return workspacePackagePaths; }); -/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "copyWorkspacePackages", function() { return copyWorkspacePackages; }); -/* harmony import */ var glob__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(146); -/* harmony import */ var glob__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(glob__WEBPACK_IMPORTED_MODULE_0__); -/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(4); -/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_1__); -/* harmony import */ var util__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(111); -/* harmony import */ var util__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(util__WEBPACK_IMPORTED_MODULE_2__); -/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(280); -/* harmony import */ var _fs__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(130); -/* harmony import */ var _package_json__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(164); -/* harmony import */ var _projects__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(145); -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.sortAlpha = sortAlpha; +exports.entries = entries; +exports.removePrefix = removePrefix; +exports.removeSuffix = removeSuffix; +exports.addSuffix = addSuffix; +exports.hyphenate = hyphenate; +exports.camelCase = camelCase; +exports.compareSortedArrays = compareSortedArrays; +exports.sleep = sleep; +const _camelCase = __webpack_require__(176); + +function sortAlpha(a, b) { + // sort alphabetically in a deterministic way + const shortLen = Math.min(a.length, b.length); + for (let i = 0; i < shortLen; i++) { + const aChar = a.charCodeAt(i); + const bChar = b.charCodeAt(i); + if (aChar !== bChar) { + return aChar - bChar; + } + } + return a.length - b.length; +} +function entries(obj) { + const entries = []; + if (obj) { + for (const key in obj) { + entries.push([key, obj[key]]); + } + } + return entries; +} +function removePrefix(pattern, prefix) { + if (pattern.startsWith(prefix)) { + pattern = pattern.slice(prefix.length); + } + return pattern; +} +function removeSuffix(pattern, suffix) { + if (pattern.endsWith(suffix)) { + return pattern.slice(0, -suffix.length); + } -const glob = Object(util__WEBPACK_IMPORTED_MODULE_2__["promisify"])(glob__WEBPACK_IMPORTED_MODULE_0___default.a); -async function workspacePackagePaths(rootPath) { - const rootPkgJson = await Object(_package_json__WEBPACK_IMPORTED_MODULE_5__["readPackageJson"])(rootPath); + return pattern; +} - if (!rootPkgJson.workspaces) { - return []; +function addSuffix(pattern, suffix) { + if (!pattern.endsWith(suffix)) { + return pattern + suffix; } - const workspacesPathsPatterns = rootPkgJson.workspaces.packages; - let workspaceProjectsPaths = []; + return pattern; +} - for (const pattern of workspacesPathsPatterns) { - workspaceProjectsPaths = workspaceProjectsPaths.concat(await packagesFromGlobPattern({ - pattern, - rootPath - })); - } // Filter out exclude glob patterns +function hyphenate(str) { + return str.replace(/[A-Z]/g, match => { + return '-' + match.charAt(0).toLowerCase(); + }); +} +function camelCase(str) { + if (/[A-Z]/.test(str)) { + return null; + } else { + return _camelCase(str); + } +} - for (const pattern of workspacesPathsPatterns) { - if (pattern.startsWith('!')) { - const pathToRemove = path__WEBPACK_IMPORTED_MODULE_1___default.a.join(rootPath, pattern.slice(1), 'package.json'); - workspaceProjectsPaths = workspaceProjectsPaths.filter(p => p !== pathToRemove); +function compareSortedArrays(array1, array2) { + if (array1.length !== array2.length) { + return false; + } + for (let i = 0, len = array1.length; i < len; i++) { + if (array1[i] !== array2[i]) { + return false; } } - - return workspaceProjectsPaths; + return true; } -async function copyWorkspacePackages(rootPath) { - const projectPaths = Object(_config__WEBPACK_IMPORTED_MODULE_3__["getProjectPaths"])({ - rootPath - }); - const projects = await Object(_projects__WEBPACK_IMPORTED_MODULE_6__["getProjects"])(rootPath, projectPaths); - for (const project of projects.values()) { - const dest = path__WEBPACK_IMPORTED_MODULE_1___default.a.resolve(rootPath, 'node_modules', project.name); +function sleep(ms) { + return new Promise(resolve => { + setTimeout(resolve, ms); + }); +} - if ((await Object(_fs__WEBPACK_IMPORTED_MODULE_4__["isSymlink"])(dest)) === false) { - continue; - } // Remove the symlink +/***/ }), +/* 13 */ +/***/ (function(module, exports, __webpack_require__) { +var store = __webpack_require__(107)('wks'); +var uid = __webpack_require__(111); +var Symbol = __webpack_require__(11).Symbol; +var USE_SYMBOL = typeof Symbol == 'function'; - await Object(_fs__WEBPACK_IMPORTED_MODULE_4__["unlink"])(dest); // Copy in the package +var $exports = module.exports = function (name) { + return store[name] || (store[name] = + USE_SYMBOL && Symbol[name] || (USE_SYMBOL ? Symbol : uid)('Symbol.' + name)); +}; - await Object(_fs__WEBPACK_IMPORTED_MODULE_4__["copyDirectory"])(project.path, dest); - } -} +$exports.store = store; -function packagesFromGlobPattern({ - pattern, - rootPath -}) { - const globOptions = { - cwd: rootPath, - // Should throw in case of unusual errors when reading the file system - strict: true, - // Always returns absolute paths for matched files - absolute: true, - // Do not match ** against multiple filenames - // (This is only specified because we currently don't have a need for it.) - noglobstar: true - }; - return glob(path__WEBPACK_IMPORTED_MODULE_1___default.a.join(pattern, 'package.json'), globOptions); -} /***/ }), -/* 280 */ -/***/ (function(module, __webpack_exports__, __webpack_require__) { +/* 14 */ +/***/ (function(module, exports, __webpack_require__) { "use strict"; -__webpack_require__.r(__webpack_exports__); -/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getProjectPaths", function() { return getProjectPaths; }); -/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(4); -/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_0__); -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -/** - * Returns all the paths where plugins are located - */ -function getProjectPaths({ - rootPath, - ossOnly, - skipKibanaPlugins -}) { - const projectPaths = [rootPath, Object(path__WEBPACK_IMPORTED_MODULE_0__["resolve"])(rootPath, 'packages/*')]; // This is needed in order to install the dependencies for the declared - // plugin functional used in the selenium functional tests. - // As we are now using the webpack dll for the client vendors dependencies - // when we run the plugin functional tests against the distributable - // dependencies used by such plugins like @eui, react and react-dom can't - // be loaded from the dll as the context is different from the one declared - // into the webpack dll reference plugin. - // In anyway, have a plugin declaring their own dependencies is the - // correct and the expect behavior. +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.stringify = exports.parse = undefined; - projectPaths.push(Object(path__WEBPACK_IMPORTED_MODULE_0__["resolve"])(rootPath, 'test/plugin_functional/plugins/*')); - projectPaths.push(Object(path__WEBPACK_IMPORTED_MODULE_0__["resolve"])(rootPath, 'test/interpreter_functional/plugins/*')); - projectPaths.push(Object(path__WEBPACK_IMPORTED_MODULE_0__["resolve"])(rootPath, 'examples/*')); +var _asyncToGenerator2; - if (!ossOnly) { - projectPaths.push(Object(path__WEBPACK_IMPORTED_MODULE_0__["resolve"])(rootPath, 'x-pack')); - projectPaths.push(Object(path__WEBPACK_IMPORTED_MODULE_0__["resolve"])(rootPath, 'x-pack/plugins/*')); - projectPaths.push(Object(path__WEBPACK_IMPORTED_MODULE_0__["resolve"])(rootPath, 'x-pack/legacy/plugins/*')); - projectPaths.push(Object(path__WEBPACK_IMPORTED_MODULE_0__["resolve"])(rootPath, 'x-pack/test/functional_with_es_ssl/fixtures/plugins/*')); - } +function _load_asyncToGenerator() { + return _asyncToGenerator2 = _interopRequireDefault(__webpack_require__(1)); +} - if (!skipKibanaPlugins) { - projectPaths.push(Object(path__WEBPACK_IMPORTED_MODULE_0__["resolve"])(rootPath, '../kibana-extra/*')); - projectPaths.push(Object(path__WEBPACK_IMPORTED_MODULE_0__["resolve"])(rootPath, '../kibana-extra/*/packages/*')); - projectPaths.push(Object(path__WEBPACK_IMPORTED_MODULE_0__["resolve"])(rootPath, '../kibana-extra/*/plugins/*')); - projectPaths.push(Object(path__WEBPACK_IMPORTED_MODULE_0__["resolve"])(rootPath, 'plugins/*')); - projectPaths.push(Object(path__WEBPACK_IMPORTED_MODULE_0__["resolve"])(rootPath, 'plugins/*/packages/*')); - projectPaths.push(Object(path__WEBPACK_IMPORTED_MODULE_0__["resolve"])(rootPath, 'plugins/*/plugins/*')); +var _parse; + +function _load_parse() { + return _parse = __webpack_require__(81); +} + +Object.defineProperty(exports, 'parse', { + enumerable: true, + get: function get() { + return _interopRequireDefault(_parse || _load_parse()).default; } +}); - return projectPaths; +var _stringify; + +function _load_stringify() { + return _stringify = __webpack_require__(150); } -/***/ }), -/* 281 */ -/***/ (function(module, __webpack_exports__, __webpack_require__) { +Object.defineProperty(exports, 'stringify', { + enumerable: true, + get: function get() { + return _interopRequireDefault(_stringify || _load_stringify()).default; + } +}); +exports.implodeEntry = implodeEntry; +exports.explodeEntry = explodeEntry; -"use strict"; -__webpack_require__.r(__webpack_exports__); -/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getAllChecksums", function() { return getAllChecksums; }); -/* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(133); -/* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(fs__WEBPACK_IMPORTED_MODULE_0__); -/* harmony import */ var crypto__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(282); -/* harmony import */ var crypto__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(crypto__WEBPACK_IMPORTED_MODULE_1__); -/* harmony import */ var util__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(111); -/* harmony import */ var util__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(util__WEBPACK_IMPORTED_MODULE_2__); -/* harmony import */ var execa__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(236); -/* harmony import */ var execa__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(execa__WEBPACK_IMPORTED_MODULE_3__); -/* harmony import */ var _yarn_lock__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(283); -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ +var _misc; +function _load_misc() { + return _misc = __webpack_require__(12); +} +var _normalizePattern; +function _load_normalizePattern() { + return _normalizePattern = __webpack_require__(29); +} +var _parse2; -const statAsync = Object(util__WEBPACK_IMPORTED_MODULE_2__["promisify"])(fs__WEBPACK_IMPORTED_MODULE_0___default.a.stat); +function _load_parse2() { + return _parse2 = _interopRequireDefault(__webpack_require__(81)); +} -const projectBySpecificitySorter = (a, b) => b.path.length - a.path.length; -/** Get the changed files for a set of projects */ +var _constants; +function _load_constants() { + return _constants = __webpack_require__(6); +} -async function getChangesForProjects(projects, kbn, log) { - log.verbose('getting changed files'); - const { - stdout - } = await execa__WEBPACK_IMPORTED_MODULE_3___default()('git', ['ls-files', '-dmto', '--exclude-standard', '--', ...Array.from(projects.values()).filter(p => kbn.isPartOfRepo(p)).map(p => p.path)], { - cwd: kbn.getAbsolute() - }); - const output = stdout.trim(); - const unassignedChanges = new Map(); - - if (output) { - for (const line of output.split('\n')) { - const [tag, ...pathParts] = line.trim().split(' '); - const path = pathParts.join(' '); - - switch (tag) { - case 'M': - case 'C': - // for some reason ls-files returns deleted files as both deleted - // and modified, so make sure not to overwrite changes already - // tracked as "deleted" - if (unassignedChanges.get(path) !== 'deleted') { - unassignedChanges.set(path, 'modified'); - } +var _fs; - break; +function _load_fs() { + return _fs = _interopRequireWildcard(__webpack_require__(5)); +} - case 'R': - unassignedChanges.set(path, 'deleted'); - break; +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } - case '?': - unassignedChanges.set(path, 'untracked'); - break; +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - case 'H': - case 'S': - case 'K': - default: - log.warning(`unexpected modification status "${tag}" for ${path}, please report this!`); - unassignedChanges.set(path, 'invalid'); - break; - } - } - } +const invariant = __webpack_require__(7); - const sortedRelevantProjects = Array.from(projects.values()).sort(projectBySpecificitySorter); - const changesByProject = new Map(); +const path = __webpack_require__(0); +const ssri = __webpack_require__(55); - for (const project of sortedRelevantProjects) { - if (kbn.isOutsideRepo(project)) { - changesByProject.set(project, undefined); - continue; - } +function getName(pattern) { + return (0, (_normalizePattern || _load_normalizePattern()).normalizePattern)(pattern).name; +} - const ownChanges = new Map(); - const prefix = kbn.getRelative(project.path); +function blankObjectUndefined(obj) { + return obj && Object.keys(obj).length ? obj : undefined; +} - for (const [path, type] of unassignedChanges) { - if (path.startsWith(prefix)) { - ownChanges.set(path, type); - unassignedChanges.delete(path); - } - } +function keyForRemote(remote) { + return remote.resolved || (remote.reference && remote.hash ? `${remote.reference}#${remote.hash}` : null); +} - log.verbose(`[${project.name}] found ${ownChanges.size} changes`); - changesByProject.set(project, ownChanges); - } +function serializeIntegrity(integrity) { + // We need this because `Integrity.toString()` does not use sorting to ensure a stable string output + // See https://git.io/vx2Hy + return integrity.toString().split(' ').sort().join(' '); +} - if (unassignedChanges.size) { - throw new Error(`unable to assign all change paths to a project: ${JSON.stringify(Array.from(unassignedChanges.entries()))}`); +function implodeEntry(pattern, obj) { + const inferredName = getName(pattern); + const integrity = obj.integrity ? serializeIntegrity(obj.integrity) : ''; + const imploded = { + name: inferredName === obj.name ? undefined : obj.name, + version: obj.version, + uid: obj.uid === obj.version ? undefined : obj.uid, + resolved: obj.resolved, + registry: obj.registry === 'npm' ? undefined : obj.registry, + dependencies: blankObjectUndefined(obj.dependencies), + optionalDependencies: blankObjectUndefined(obj.optionalDependencies), + permissions: blankObjectUndefined(obj.permissions), + prebuiltVariants: blankObjectUndefined(obj.prebuiltVariants) + }; + if (integrity) { + imploded.integrity = integrity; } - - return changesByProject; + return imploded; } -/** Get the latest commit sha for a project */ - -async function getLatestSha(project, kbn) { - if (kbn.isOutsideRepo(project)) { - return; +function explodeEntry(pattern, obj) { + obj.optionalDependencies = obj.optionalDependencies || {}; + obj.dependencies = obj.dependencies || {}; + obj.uid = obj.uid || obj.version; + obj.permissions = obj.permissions || {}; + obj.registry = obj.registry || 'npm'; + obj.name = obj.name || getName(pattern); + const integrity = obj.integrity; + if (integrity && integrity.isIntegrity) { + obj.integrity = ssri.parse(integrity); } - - const { - stdout - } = await execa__WEBPACK_IMPORTED_MODULE_3___default()('git', ['log', '-n', '1', '--pretty=format:%H', '--', project.path], { - cwd: kbn.getAbsolute() - }); - return stdout.trim() || undefined; + return obj; } -/** - * Get a list of the absolute dependencies of this project, as resolved - * in the yarn.lock file, does not include other projects in the workspace - * or their dependencies - */ +class Lockfile { + constructor({ cache, source, parseResultType } = {}) { + this.source = source || ''; + this.cache = cache; + this.parseResultType = parseResultType; + } -function resolveDepsForProject(project, yarnLock, kbn, log) { - /** map of [name@range, name@resolved] */ - const resolved = new Map(); - const queue = Object.entries(project.allDependencies); + // source string if the `cache` was parsed - while (queue.length) { - const [name, versionRange] = queue.shift(); - const req = `${name}@${versionRange}`; - if (resolved.has(req)) { - continue; + // if true, we're parsing an old yarn file and need to update integrity fields + hasEntriesExistWithoutIntegrity() { + if (!this.cache) { + return false; } - if (!kbn.hasProject(name)) { - const pkg = yarnLock[req]; - - if (!pkg) { - log.warning('yarn.lock file is out of date, please run `yarn kbn bootstrap` to re-enable caching'); - return; - } - - const res = `${name}@${pkg.version}`; - resolved.set(req, res); - const allDepsEntries = [...Object.entries(pkg.dependencies || {}), ...Object.entries(pkg.optionalDependencies || {})]; - - for (const [childName, childVersionRange] of allDepsEntries) { - queue.push([childName, childVersionRange]); + for (const key in this.cache) { + // $FlowFixMe - `this.cache` is clearly defined at this point + if (!/^.*@(file:|http)/.test(key) && this.cache[key] && !this.cache[key].integrity) { + return true; } } + + return false; } - return Array.from(resolved.values()).sort((a, b) => a.localeCompare(b)); -} -/** - * Get the checksum for a specific project in the workspace - */ + static fromDirectory(dir, reporter) { + return (0, (_asyncToGenerator2 || _load_asyncToGenerator()).default)(function* () { + // read the manifest in this directory + const lockfileLoc = path.join(dir, (_constants || _load_constants()).LOCKFILE_FILENAME); + let lockfile; + let rawLockfile = ''; + let parseResult; -async function getChecksum(project, changes, yarnLock, kbn, log) { - const sha = await getLatestSha(project, kbn); + if (yield (_fs || _load_fs()).exists(lockfileLoc)) { + rawLockfile = yield (_fs || _load_fs()).readFile(lockfileLoc); + parseResult = (0, (_parse2 || _load_parse2()).default)(rawLockfile, lockfileLoc); - if (sha) { - log.verbose(`[${project.name}] local sha:`, sha); - } + if (reporter) { + if (parseResult.type === 'merge') { + reporter.info(reporter.lang('lockfileMerged')); + } else if (parseResult.type === 'conflict') { + reporter.warn(reporter.lang('lockfileConflict')); + } + } - if (!changes || Array.from(changes.values()).includes('invalid')) { - log.warning(`[${project.name}] unable to determine local changes, caching disabled`); - return; + lockfile = parseResult.object; + } else if (reporter) { + reporter.info(reporter.lang('noLockfileFound')); + } + + return new Lockfile({ cache: lockfile, source: rawLockfile, parseResultType: parseResult && parseResult.type }); + })(); } - const changesSummary = await Promise.all(Array.from(changes).sort((a, b) => a[0].localeCompare(b[0])).map(async ([path, type]) => { - if (type === 'deleted') { - return `${path}:deleted`; + getLocked(pattern) { + const cache = this.cache; + if (!cache) { + return undefined; } - const stats = await statAsync(kbn.getAbsolute(path)); - log.verbose(`[${project.name}] modified time ${stats.mtimeMs} for ${path}`); - return `${path}:${stats.mtimeMs}`; - })); - const deps = await resolveDepsForProject(project, yarnLock, kbn, log); + const shrunk = pattern in cache && cache[pattern]; - if (!deps) { - return; - } + if (typeof shrunk === 'string') { + return this.getLocked(shrunk); + } else if (shrunk) { + explodeEntry(pattern, shrunk); + return shrunk; + } - log.verbose(`[${project.name}] resolved %d deps`, deps.length); - const checksum = JSON.stringify({ - sha, - changes: changesSummary, - deps - }, null, 2); + return undefined; + } - if (process.env.BOOTSTRAP_CACHE_DEBUG_CHECKSUM) { - return checksum; + removePattern(pattern) { + const cache = this.cache; + if (!cache) { + return; + } + delete cache[pattern]; } - const hash = crypto__WEBPACK_IMPORTED_MODULE_1___default.a.createHash('sha1'); - hash.update(checksum); - return hash.digest('hex'); -} -/** - * Calculate checksums for all projects in the workspace based on - * - last git commit to project directory - * - un-committed changes - * - resolved dependencies from yarn.lock referenced by project package.json - */ + getLockfile(patterns) { + const lockfile = {}; + const seen = new Map(); + // order by name so that lockfile manifest is assigned to the first dependency with this manifest + // the others that have the same remoteKey will just refer to the first + // ordering allows for consistency in lockfile when it is serialized + const sortedPatternsKeys = Object.keys(patterns).sort((_misc || _load_misc()).sortAlpha); -async function getAllChecksums(kbn, log) { - const projects = kbn.getAllProjects(); - const changesByProject = await getChangesForProjects(projects, kbn, log); - const yarnLock = await Object(_yarn_lock__WEBPACK_IMPORTED_MODULE_4__["readYarnLock"])(kbn); - /** map of [project.name, cacheKey] */ + for (var _iterator = sortedPatternsKeys, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : _iterator[Symbol.iterator]();;) { + var _ref; - const cacheKeys = new Map(); - await Promise.all(Array.from(projects.values()).map(async project => { - cacheKeys.set(project.name, await getChecksum(project, changesByProject.get(project), yarnLock, kbn, log)); - })); - return cacheKeys; -} + if (_isArray) { + if (_i >= _iterator.length) break; + _ref = _iterator[_i++]; + } else { + _i = _iterator.next(); + if (_i.done) break; + _ref = _i.value; + } -/***/ }), -/* 282 */ -/***/ (function(module, exports) { + const pattern = _ref; -module.exports = require("crypto"); + const pkg = patterns[pattern]; + const remote = pkg._remote, + ref = pkg._reference; -/***/ }), -/* 283 */ -/***/ (function(module, __webpack_exports__, __webpack_require__) { + invariant(ref, 'Package is missing a reference'); + invariant(remote, 'Package is missing a remote'); -"use strict"; -__webpack_require__.r(__webpack_exports__); -/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "readYarnLock", function() { return readYarnLock; }); -/* harmony import */ var _yarnpkg_lockfile__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(284); -/* harmony import */ var _yarnpkg_lockfile__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_yarnpkg_lockfile__WEBPACK_IMPORTED_MODULE_0__); -/* harmony import */ var _utils_fs__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(130); -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -// @ts-ignore published types are worthless + const remoteKey = keyForRemote(remote); + const seenPattern = remoteKey && seen.get(remoteKey); + if (seenPattern) { + // no point in duplicating it + lockfile[pattern] = seenPattern; + // if we're relying on our name being inferred and two of the patterns have + // different inferred names then we need to set it + if (!seenPattern.name && getName(pattern) !== pkg.name) { + seenPattern.name = pkg.name; + } + continue; + } + const obj = implodeEntry(pattern, { + name: pkg.name, + version: pkg.version, + uid: pkg._uid, + resolved: remote.resolved, + integrity: remote.integrity, + registry: remote.registry, + dependencies: pkg.dependencies, + peerDependencies: pkg.peerDependencies, + optionalDependencies: pkg.optionalDependencies, + permissions: ref.permissions, + prebuiltVariants: pkg.prebuiltVariants + }); -async function readYarnLock(kbn) { - try { - const contents = await Object(_utils_fs__WEBPACK_IMPORTED_MODULE_1__["readFile"])(kbn.getAbsolute('yarn.lock'), 'utf8'); - const yarnLock = Object(_yarnpkg_lockfile__WEBPACK_IMPORTED_MODULE_0__["parse"])(contents); + lockfile[pattern] = obj; - if (yarnLock.type === 'success') { - return yarnLock.object; + if (remoteKey) { + seen.set(remoteKey, obj); + } } - throw new Error('unable to read yarn.lock file, please run `yarn kbn bootstrap`'); - } catch (error) { - if (error.code !== 'ENOENT') { - throw error; - } + return lockfile; } - - return {}; } +exports.default = Lockfile; /***/ }), -/* 284 */ -/***/ (function(module, exports, __webpack_require__) { - -module.exports = -/******/ (function(modules) { // webpackBootstrap -/******/ // The module cache -/******/ var installedModules = {}; -/******/ -/******/ // The require function -/******/ function __webpack_require__(moduleId) { -/******/ -/******/ // Check if module is in cache -/******/ if(installedModules[moduleId]) { -/******/ return installedModules[moduleId].exports; -/******/ } -/******/ // Create a new module (and put it into the cache) -/******/ var module = installedModules[moduleId] = { -/******/ i: moduleId, -/******/ l: false, -/******/ exports: {} -/******/ }; -/******/ -/******/ // Execute the module function -/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); -/******/ -/******/ // Flag the module as loaded -/******/ module.l = true; -/******/ -/******/ // Return the exports of the module -/******/ return module.exports; -/******/ } -/******/ -/******/ -/******/ // expose the modules object (__webpack_modules__) -/******/ __webpack_require__.m = modules; -/******/ -/******/ // expose the module cache -/******/ __webpack_require__.c = installedModules; -/******/ -/******/ // identity function for calling harmony imports with the correct context -/******/ __webpack_require__.i = function(value) { return value; }; -/******/ -/******/ // define getter function for harmony exports -/******/ __webpack_require__.d = function(exports, name, getter) { -/******/ if(!__webpack_require__.o(exports, name)) { -/******/ Object.defineProperty(exports, name, { -/******/ configurable: false, -/******/ enumerable: true, -/******/ get: getter -/******/ }); -/******/ } -/******/ }; -/******/ -/******/ // getDefaultExport function for compatibility with non-harmony modules -/******/ __webpack_require__.n = function(module) { -/******/ var getter = module && module.__esModule ? -/******/ function getDefault() { return module['default']; } : -/******/ function getModuleExports() { return module; }; -/******/ __webpack_require__.d(getter, 'a', getter); -/******/ return getter; -/******/ }; -/******/ -/******/ // Object.prototype.hasOwnProperty.call -/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; -/******/ -/******/ // __webpack_public_path__ -/******/ __webpack_require__.p = ""; -/******/ -/******/ // Load entry module and return exports -/******/ return __webpack_require__(__webpack_require__.s = 14); -/******/ }) -/************************************************************************/ -/******/ ([ -/* 0 */ +/* 15 */, +/* 16 */, +/* 17 */ /***/ (function(module, exports) { -module.exports = __webpack_require__(4); +module.exports = __webpack_require__(138); /***/ }), -/* 1 */ +/* 18 */, +/* 19 */, +/* 20 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -exports.__esModule = true; - -var _promise = __webpack_require__(173); +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = nullify; +function nullify(obj = {}) { + if (Array.isArray(obj)) { + for (var _iterator = obj, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : _iterator[Symbol.iterator]();;) { + var _ref; -var _promise2 = _interopRequireDefault(_promise); + if (_isArray) { + if (_i >= _iterator.length) break; + _ref = _iterator[_i++]; + } else { + _i = _iterator.next(); + if (_i.done) break; + _ref = _i.value; + } -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + const item = _ref; -exports.default = function (fn) { - return function () { - var gen = fn.apply(this, arguments); - return new _promise2.default(function (resolve, reject) { - function step(key, arg) { - try { - var info = gen[key](arg); - var value = info.value; - } catch (error) { - reject(error); - return; - } + nullify(item); + } + } else if (obj !== null && typeof obj === 'object' || typeof obj === 'function') { + Object.setPrototypeOf(obj, null); - if (info.done) { - resolve(value); - } else { - return _promise2.default.resolve(value).then(function (value) { - step("next", value); - }, function (err) { - step("throw", err); - }); - } + // for..in can only be applied to 'object', not 'function' + if (typeof obj === 'object') { + for (const key in obj) { + nullify(obj[key]); } + } + } - return step("next"); - }); - }; -}; + return obj; +} /***/ }), -/* 2 */ +/* 21 */, +/* 22 */ /***/ (function(module, exports) { -module.exports = __webpack_require__(111); +module.exports = __webpack_require__(140); /***/ }), -/* 3 */ +/* 23 */ /***/ (function(module, exports) { -module.exports = __webpack_require__(133); +var core = module.exports = { version: '2.5.7' }; +if (typeof __e == 'number') __e = core; // eslint-disable-line no-undef + /***/ }), -/* 4 */ +/* 24 */, +/* 25 */, +/* 26 */, +/* 27 */ +/***/ (function(module, exports, __webpack_require__) { + +var isObject = __webpack_require__(34); +module.exports = function (it) { + if (!isObject(it)) throw TypeError(it + ' is not an object!'); + return it; +}; + + +/***/ }), +/* 28 */, +/* 29 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -29310,2259 +29640,2760 @@ module.exports = __webpack_require__(133); Object.defineProperty(exports, "__esModule", { value: true }); -class MessageError extends Error { - constructor(msg, code) { - super(msg); - this.code = code; - } +exports.normalizePattern = normalizePattern; -} +/** + * Explode and normalize a pattern into its name and range. + */ -exports.MessageError = MessageError; -class ProcessSpawnError extends MessageError { - constructor(msg, code, process) { - super(msg, code); - this.process = process; - } +function normalizePattern(pattern) { + let hasVersion = false; + let range = 'latest'; + let name = pattern; -} + // if we're a scope then remove the @ and add it back later + let isScoped = false; + if (name[0] === '@') { + isScoped = true; + name = name.slice(1); + } -exports.ProcessSpawnError = ProcessSpawnError; -class SecurityError extends MessageError {} + // take first part as the name + const parts = name.split('@'); + if (parts.length > 1) { + name = parts.shift(); + range = parts.join('@'); -exports.SecurityError = SecurityError; -class ProcessTermError extends MessageError {} + if (range) { + hasVersion = true; + } else { + range = '*'; + } + } -exports.ProcessTermError = ProcessTermError; -class ResponseError extends Error { - constructor(msg, responseCode) { - super(msg); - this.responseCode = responseCode; + // add back @ scope suffix + if (isScoped) { + name = `@${name}`; } + return { name, range, hasVersion }; } -exports.ResponseError = ResponseError; /***/ }), -/* 5 */ +/* 30 */, +/* 31 */ /***/ (function(module, exports, __webpack_require__) { -"use strict"; +var dP = __webpack_require__(50); +var createDesc = __webpack_require__(106); +module.exports = __webpack_require__(33) ? function (object, key, value) { + return dP.f(object, key, createDesc(1, value)); +} : function (object, key, value) { + object[key] = value; + return object; +}; -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.getFirstSuitableFolder = exports.readFirstAvailableStream = exports.makeTempDir = exports.hardlinksWork = exports.writeFilePreservingEol = exports.getFileSizeOnDisk = exports.walk = exports.symlink = exports.find = exports.readJsonAndFile = exports.readJson = exports.readFileAny = exports.hardlinkBulk = exports.copyBulk = exports.unlink = exports.glob = exports.link = exports.chmod = exports.lstat = exports.exists = exports.mkdirp = exports.stat = exports.access = exports.rename = exports.readdir = exports.realpath = exports.readlink = exports.writeFile = exports.open = exports.readFileBuffer = exports.lockQueue = exports.constants = undefined; +/***/ }), +/* 32 */ +/***/ (function(module, exports, __webpack_require__) { -var _asyncToGenerator2; +/* eslint-disable node/no-deprecated-api */ +var buffer = __webpack_require__(63) +var Buffer = buffer.Buffer -function _load_asyncToGenerator() { - return _asyncToGenerator2 = _interopRequireDefault(__webpack_require__(1)); +// alternative to using Object.keys for old browsers +function copyProps (src, dst) { + for (var key in src) { + dst[key] = src[key] + } +} +if (Buffer.from && Buffer.alloc && Buffer.allocUnsafe && Buffer.allocUnsafeSlow) { + module.exports = buffer +} else { + // Copy properties from require('buffer') + copyProps(buffer, exports) + exports.Buffer = SafeBuffer } -let buildActionsForCopy = (() => { - var _ref = (0, (_asyncToGenerator2 || _load_asyncToGenerator()).default)(function* (queue, events, possibleExtraneous, reporter) { +function SafeBuffer (arg, encodingOrOffset, length) { + return Buffer(arg, encodingOrOffset, length) +} - // - let build = (() => { - var _ref5 = (0, (_asyncToGenerator2 || _load_asyncToGenerator()).default)(function* (data) { - const src = data.src, - dest = data.dest, - type = data.type; +// Copy static methods from Buffer +copyProps(Buffer, SafeBuffer) - const onFresh = data.onFresh || noop; - const onDone = data.onDone || noop; +SafeBuffer.from = function (arg, encodingOrOffset, length) { + if (typeof arg === 'number') { + throw new TypeError('Argument must not be a number') + } + return Buffer(arg, encodingOrOffset, length) +} - // TODO https://github.com/yarnpkg/yarn/issues/3751 - // related to bundled dependencies handling - if (files.has(dest.toLowerCase())) { - reporter.verbose(`The case-insensitive file ${dest} shouldn't be copied twice in one bulk copy`); - } else { - files.add(dest.toLowerCase()); - } +SafeBuffer.alloc = function (size, fill, encoding) { + if (typeof size !== 'number') { + throw new TypeError('Argument must be a number') + } + var buf = Buffer(size) + if (fill !== undefined) { + if (typeof encoding === 'string') { + buf.fill(fill, encoding) + } else { + buf.fill(fill) + } + } else { + buf.fill(0) + } + return buf +} - if (type === 'symlink') { - yield mkdirp((_path || _load_path()).default.dirname(dest)); - onFresh(); - actions.symlink.push({ - dest, - linkname: src - }); - onDone(); - return; - } +SafeBuffer.allocUnsafe = function (size) { + if (typeof size !== 'number') { + throw new TypeError('Argument must be a number') + } + return Buffer(size) +} - if (events.ignoreBasenames.indexOf((_path || _load_path()).default.basename(src)) >= 0) { - // ignored file - return; - } +SafeBuffer.allocUnsafeSlow = function (size) { + if (typeof size !== 'number') { + throw new TypeError('Argument must be a number') + } + return buffer.SlowBuffer(size) +} - const srcStat = yield lstat(src); - let srcFiles; - if (srcStat.isDirectory()) { - srcFiles = yield readdir(src); - } +/***/ }), +/* 33 */ +/***/ (function(module, exports, __webpack_require__) { - let destStat; - try { - // try accessing the destination - destStat = yield lstat(dest); - } catch (e) { - // proceed if destination doesn't exist, otherwise error - if (e.code !== 'ENOENT') { - throw e; - } - } +// Thank's IE8 for his funny defineProperty +module.exports = !__webpack_require__(85)(function () { + return Object.defineProperty({}, 'a', { get: function () { return 7; } }).a != 7; +}); - // if destination exists - if (destStat) { - const bothSymlinks = srcStat.isSymbolicLink() && destStat.isSymbolicLink(); - const bothFolders = srcStat.isDirectory() && destStat.isDirectory(); - const bothFiles = srcStat.isFile() && destStat.isFile(); - // EINVAL access errors sometimes happen which shouldn't because node shouldn't be giving - // us modes that aren't valid. investigate this, it's generally safe to proceed. +/***/ }), +/* 34 */ +/***/ (function(module, exports) { - /* if (srcStat.mode !== destStat.mode) { - try { - await access(dest, srcStat.mode); - } catch (err) {} - } */ +module.exports = function (it) { + return typeof it === 'object' ? it !== null : typeof it === 'function'; +}; - if (bothFiles && artifactFiles.has(dest)) { - // this file gets changed during build, likely by a custom install script. Don't bother checking it. - onDone(); - reporter.verbose(reporter.lang('verboseFileSkipArtifact', src)); - return; - } - if (bothFiles && srcStat.size === destStat.size && (0, (_fsNormalized || _load_fsNormalized()).fileDatesEqual)(srcStat.mtime, destStat.mtime)) { - // we can safely assume this is the same file - onDone(); - reporter.verbose(reporter.lang('verboseFileSkip', src, dest, srcStat.size, +srcStat.mtime)); - return; - } +/***/ }), +/* 35 */ +/***/ (function(module, exports) { - if (bothSymlinks) { - const srcReallink = yield readlink(src); - if (srcReallink === (yield readlink(dest))) { - // if both symlinks are the same then we can continue on - onDone(); - reporter.verbose(reporter.lang('verboseFileSkipSymlink', src, dest, srcReallink)); - return; - } - } +module.exports = {}; - if (bothFolders) { - // mark files that aren't in this folder as possibly extraneous - const destFiles = yield readdir(dest); - invariant(srcFiles, 'src files not initialised'); - for (var _iterator4 = destFiles, _isArray4 = Array.isArray(_iterator4), _i4 = 0, _iterator4 = _isArray4 ? _iterator4 : _iterator4[Symbol.iterator]();;) { - var _ref6; +/***/ }), +/* 36 */ +/***/ (function(module, exports) { - if (_isArray4) { - if (_i4 >= _iterator4.length) break; - _ref6 = _iterator4[_i4++]; - } else { - _i4 = _iterator4.next(); - if (_i4.done) break; - _ref6 = _i4.value; - } +module.exports = __webpack_require__(121); - const file = _ref6; +/***/ }), +/* 37 */, +/* 38 */, +/* 39 */, +/* 40 */ +/***/ (function(module, exports, __webpack_require__) { - if (srcFiles.indexOf(file) < 0) { - const loc = (_path || _load_path()).default.join(dest, file); - possibleExtraneous.add(loc); +"use strict"; - if ((yield lstat(loc)).isDirectory()) { - for (var _iterator5 = yield readdir(loc), _isArray5 = Array.isArray(_iterator5), _i5 = 0, _iterator5 = _isArray5 ? _iterator5 : _iterator5[Symbol.iterator]();;) { - var _ref7; - if (_isArray5) { - if (_i5 >= _iterator5.length) break; - _ref7 = _iterator5[_i5++]; - } else { - _i5 = _iterator5.next(); - if (_i5.done) break; - _ref7 = _i5.value; - } +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.wait = wait; +exports.promisify = promisify; +exports.queue = queue; +function wait(delay) { + return new Promise(resolve => { + setTimeout(resolve, delay); + }); +} - const file = _ref7; +function promisify(fn, firstData) { + return function (...args) { + return new Promise(function (resolve, reject) { + args.push(function (err, ...result) { + let res = result; - possibleExtraneous.add((_path || _load_path()).default.join(loc, file)); - } - } - } - } - } + if (result.length <= 1) { + res = result[0]; } - if (destStat && destStat.isSymbolicLink()) { - yield (0, (_fsNormalized || _load_fsNormalized()).unlink)(dest); - destStat = null; + if (firstData) { + res = err; + err = null; } - if (srcStat.isSymbolicLink()) { - onFresh(); - const linkname = yield readlink(src); - actions.symlink.push({ - dest, - linkname - }); - onDone(); - } else if (srcStat.isDirectory()) { - if (!destStat) { - reporter.verbose(reporter.lang('verboseFileFolder', dest)); - yield mkdirp(dest); - } + if (err) { + reject(err); + } else { + resolve(res); + } + }); - const destParts = dest.split((_path || _load_path()).default.sep); - while (destParts.length) { - files.add(destParts.join((_path || _load_path()).default.sep).toLowerCase()); - destParts.pop(); - } + fn.apply(null, args); + }); + }; +} - // push all files to queue - invariant(srcFiles, 'src files not initialised'); - let remaining = srcFiles.length; - if (!remaining) { - onDone(); - } - for (var _iterator6 = srcFiles, _isArray6 = Array.isArray(_iterator6), _i6 = 0, _iterator6 = _isArray6 ? _iterator6 : _iterator6[Symbol.iterator]();;) { - var _ref8; +function queue(arr, promiseProducer, concurrency = Infinity) { + concurrency = Math.min(concurrency, arr.length); - if (_isArray6) { - if (_i6 >= _iterator6.length) break; - _ref8 = _iterator6[_i6++]; - } else { - _i6 = _iterator6.next(); - if (_i6.done) break; - _ref8 = _i6.value; - } + // clone + arr = arr.slice(); - const file = _ref8; + const results = []; + let total = arr.length; + if (!total) { + return Promise.resolve(results); + } - queue.push({ - dest: (_path || _load_path()).default.join(dest, file), - onFresh, - onDone: function (_onDone) { - function onDone() { - return _onDone.apply(this, arguments); - } + return new Promise((resolve, reject) => { + for (let i = 0; i < concurrency; i++) { + next(); + } - onDone.toString = function () { - return _onDone.toString(); - }; + function next() { + const item = arr.shift(); + const promise = promiseProducer(item); - return onDone; - }(function () { - if (--remaining === 0) { - onDone(); - } - }), - src: (_path || _load_path()).default.join(src, file) - }); - } - } else if (srcStat.isFile()) { - onFresh(); - actions.file.push({ - src, - dest, - atime: srcStat.atime, - mtime: srcStat.mtime, - mode: srcStat.mode - }); - onDone(); + promise.then(function (result) { + results.push(result); + + total--; + if (total === 0) { + resolve(results); } else { - throw new Error(`unsure how to copy this: ${src}`); + if (arr.length) { + next(); + } } - }); - - return function build(_x5) { - return _ref5.apply(this, arguments); - }; - })(); - - const artifactFiles = new Set(events.artifactFiles || []); - const files = new Set(); - - // initialise events - for (var _iterator = queue, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : _iterator[Symbol.iterator]();;) { - var _ref2; + }, reject); + } + }); +} - if (_isArray) { - if (_i >= _iterator.length) break; - _ref2 = _iterator[_i++]; - } else { - _i = _iterator.next(); - if (_i.done) break; - _ref2 = _i.value; - } +/***/ }), +/* 41 */ +/***/ (function(module, exports, __webpack_require__) { - const item = _ref2; +var global = __webpack_require__(11); +var core = __webpack_require__(23); +var ctx = __webpack_require__(48); +var hide = __webpack_require__(31); +var has = __webpack_require__(49); +var PROTOTYPE = 'prototype'; - const onDone = item.onDone; - item.onDone = function () { - events.onProgress(item.dest); - if (onDone) { - onDone(); - } +var $export = function (type, name, source) { + var IS_FORCED = type & $export.F; + var IS_GLOBAL = type & $export.G; + var IS_STATIC = type & $export.S; + var IS_PROTO = type & $export.P; + var IS_BIND = type & $export.B; + var IS_WRAP = type & $export.W; + var exports = IS_GLOBAL ? core : core[name] || (core[name] = {}); + var expProto = exports[PROTOTYPE]; + var target = IS_GLOBAL ? global : IS_STATIC ? global[name] : (global[name] || {})[PROTOTYPE]; + var key, own, out; + if (IS_GLOBAL) source = name; + for (key in source) { + // contains in native + own = !IS_FORCED && target && target[key] !== undefined; + if (own && has(exports, key)) continue; + // export native or passed + out = own ? target[key] : source[key]; + // prevent global pollution for namespaces + exports[key] = IS_GLOBAL && typeof target[key] != 'function' ? source[key] + // bind timers to global for call from export context + : IS_BIND && own ? ctx(out, global) + // wrap global constructors for prevent change them in library + : IS_WRAP && target[key] == out ? (function (C) { + var F = function (a, b, c) { + if (this instanceof C) { + switch (arguments.length) { + case 0: return new C(); + case 1: return new C(a); + case 2: return new C(a, b); + } return new C(a, b, c); + } return C.apply(this, arguments); }; + F[PROTOTYPE] = C[PROTOTYPE]; + return F; + // make static versions for prototype methods + })(out) : IS_PROTO && typeof out == 'function' ? ctx(Function.call, out) : out; + // export proto methods to core.%CONSTRUCTOR%.methods.%NAME% + if (IS_PROTO) { + (exports.virtual || (exports.virtual = {}))[key] = out; + // export proto methods to core.%CONSTRUCTOR%.prototype.%NAME% + if (type & $export.R && expProto && !expProto[key]) hide(expProto, key, out); } - events.onStart(queue.length); + } +}; +// type bitmap +$export.F = 1; // forced +$export.G = 2; // global +$export.S = 4; // static +$export.P = 8; // proto +$export.B = 16; // bind +$export.W = 32; // wrap +$export.U = 64; // safe +$export.R = 128; // real proto method for `library` +module.exports = $export; - // start building actions - const actions = { - file: [], - symlink: [], - link: [] - }; - // custom concurrency logic as we're always executing stacks of CONCURRENT_QUEUE_ITEMS queue items - // at a time due to the requirement to push items onto the queue - while (queue.length) { - const items = queue.splice(0, CONCURRENT_QUEUE_ITEMS); - yield Promise.all(items.map(build)); - } +/***/ }), +/* 42 */ +/***/ (function(module, exports, __webpack_require__) { - // simulate the existence of some files to prevent considering them extraneous - for (var _iterator2 = artifactFiles, _isArray2 = Array.isArray(_iterator2), _i2 = 0, _iterator2 = _isArray2 ? _iterator2 : _iterator2[Symbol.iterator]();;) { - var _ref3; +try { + var util = __webpack_require__(2); + if (typeof util.inherits !== 'function') throw ''; + module.exports = util.inherits; +} catch (e) { + module.exports = __webpack_require__(224); +} - if (_isArray2) { - if (_i2 >= _iterator2.length) break; - _ref3 = _iterator2[_i2++]; - } else { - _i2 = _iterator2.next(); - if (_i2.done) break; - _ref3 = _i2.value; - } - - const file = _ref3; - - if (possibleExtraneous.has(file)) { - reporter.verbose(reporter.lang('verboseFilePhantomExtraneous', file)); - possibleExtraneous.delete(file); - } - } - for (var _iterator3 = possibleExtraneous, _isArray3 = Array.isArray(_iterator3), _i3 = 0, _iterator3 = _isArray3 ? _iterator3 : _iterator3[Symbol.iterator]();;) { - var _ref4; +/***/ }), +/* 43 */, +/* 44 */, +/* 45 */ +/***/ (function(module, exports, __webpack_require__) { - if (_isArray3) { - if (_i3 >= _iterator3.length) break; - _ref4 = _iterator3[_i3++]; - } else { - _i3 = _iterator3.next(); - if (_i3.done) break; - _ref4 = _i3.value; - } +"use strict"; - const loc = _ref4; - if (files.has(loc.toLowerCase())) { - possibleExtraneous.delete(loc); - } - } +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.home = undefined; - return actions; - }); +var _rootUser; - return function buildActionsForCopy(_x, _x2, _x3, _x4) { - return _ref.apply(this, arguments); - }; -})(); +function _load_rootUser() { + return _rootUser = _interopRequireDefault(__webpack_require__(169)); +} -let buildActionsForHardlink = (() => { - var _ref9 = (0, (_asyncToGenerator2 || _load_asyncToGenerator()).default)(function* (queue, events, possibleExtraneous, reporter) { +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - // - let build = (() => { - var _ref13 = (0, (_asyncToGenerator2 || _load_asyncToGenerator()).default)(function* (data) { - const src = data.src, - dest = data.dest; +const path = __webpack_require__(0); - const onFresh = data.onFresh || noop; - const onDone = data.onDone || noop; - if (files.has(dest.toLowerCase())) { - // Fixes issue https://github.com/yarnpkg/yarn/issues/2734 - // When bulk hardlinking we have A -> B structure that we want to hardlink to A1 -> B1, - // package-linker passes that modules A1 and B1 need to be hardlinked, - // the recursive linking algorithm of A1 ends up scheduling files in B1 to be linked twice which will case - // an exception. - onDone(); - return; - } - files.add(dest.toLowerCase()); +const home = exports.home = __webpack_require__(36).homedir(); - if (events.ignoreBasenames.indexOf((_path || _load_path()).default.basename(src)) >= 0) { - // ignored file - return; - } +const userHomeDir = (_rootUser || _load_rootUser()).default ? path.resolve('/usr/local/share') : home; - const srcStat = yield lstat(src); - let srcFiles; +exports.default = userHomeDir; - if (srcStat.isDirectory()) { - srcFiles = yield readdir(src); - } +/***/ }), +/* 46 */ +/***/ (function(module, exports) { - const destExists = yield exists(dest); - if (destExists) { - const destStat = yield lstat(dest); +module.exports = function (it) { + if (typeof it != 'function') throw TypeError(it + ' is not a function!'); + return it; +}; - const bothSymlinks = srcStat.isSymbolicLink() && destStat.isSymbolicLink(); - const bothFolders = srcStat.isDirectory() && destStat.isDirectory(); - const bothFiles = srcStat.isFile() && destStat.isFile(); - if (srcStat.mode !== destStat.mode) { - try { - yield access(dest, srcStat.mode); - } catch (err) { - // EINVAL access errors sometimes happen which shouldn't because node shouldn't be giving - // us modes that aren't valid. investigate this, it's generally safe to proceed. - reporter.verbose(err); - } - } +/***/ }), +/* 47 */ +/***/ (function(module, exports) { - if (bothFiles && artifactFiles.has(dest)) { - // this file gets changed during build, likely by a custom install script. Don't bother checking it. - onDone(); - reporter.verbose(reporter.lang('verboseFileSkipArtifact', src)); - return; - } +var toString = {}.toString; - // correct hardlink - if (bothFiles && srcStat.ino !== null && srcStat.ino === destStat.ino) { - onDone(); - reporter.verbose(reporter.lang('verboseFileSkip', src, dest, srcStat.ino)); - return; - } +module.exports = function (it) { + return toString.call(it).slice(8, -1); +}; - if (bothSymlinks) { - const srcReallink = yield readlink(src); - if (srcReallink === (yield readlink(dest))) { - // if both symlinks are the same then we can continue on - onDone(); - reporter.verbose(reporter.lang('verboseFileSkipSymlink', src, dest, srcReallink)); - return; - } - } - if (bothFolders) { - // mark files that aren't in this folder as possibly extraneous - const destFiles = yield readdir(dest); - invariant(srcFiles, 'src files not initialised'); +/***/ }), +/* 48 */ +/***/ (function(module, exports, __webpack_require__) { - for (var _iterator10 = destFiles, _isArray10 = Array.isArray(_iterator10), _i10 = 0, _iterator10 = _isArray10 ? _iterator10 : _iterator10[Symbol.iterator]();;) { - var _ref14; +// optional / simple context binding +var aFunction = __webpack_require__(46); +module.exports = function (fn, that, length) { + aFunction(fn); + if (that === undefined) return fn; + switch (length) { + case 1: return function (a) { + return fn.call(that, a); + }; + case 2: return function (a, b) { + return fn.call(that, a, b); + }; + case 3: return function (a, b, c) { + return fn.call(that, a, b, c); + }; + } + return function (/* ...args */) { + return fn.apply(that, arguments); + }; +}; - if (_isArray10) { - if (_i10 >= _iterator10.length) break; - _ref14 = _iterator10[_i10++]; - } else { - _i10 = _iterator10.next(); - if (_i10.done) break; - _ref14 = _i10.value; - } - const file = _ref14; +/***/ }), +/* 49 */ +/***/ (function(module, exports) { - if (srcFiles.indexOf(file) < 0) { - const loc = (_path || _load_path()).default.join(dest, file); - possibleExtraneous.add(loc); +var hasOwnProperty = {}.hasOwnProperty; +module.exports = function (it, key) { + return hasOwnProperty.call(it, key); +}; - if ((yield lstat(loc)).isDirectory()) { - for (var _iterator11 = yield readdir(loc), _isArray11 = Array.isArray(_iterator11), _i11 = 0, _iterator11 = _isArray11 ? _iterator11 : _iterator11[Symbol.iterator]();;) { - var _ref15; - if (_isArray11) { - if (_i11 >= _iterator11.length) break; - _ref15 = _iterator11[_i11++]; - } else { - _i11 = _iterator11.next(); - if (_i11.done) break; - _ref15 = _i11.value; - } +/***/ }), +/* 50 */ +/***/ (function(module, exports, __webpack_require__) { - const file = _ref15; +var anObject = __webpack_require__(27); +var IE8_DOM_DEFINE = __webpack_require__(184); +var toPrimitive = __webpack_require__(201); +var dP = Object.defineProperty; - possibleExtraneous.add((_path || _load_path()).default.join(loc, file)); - } - } - } - } - } - } +exports.f = __webpack_require__(33) ? Object.defineProperty : function defineProperty(O, P, Attributes) { + anObject(O); + P = toPrimitive(P, true); + anObject(Attributes); + if (IE8_DOM_DEFINE) try { + return dP(O, P, Attributes); + } catch (e) { /* empty */ } + if ('get' in Attributes || 'set' in Attributes) throw TypeError('Accessors not supported!'); + if ('value' in Attributes) O[P] = Attributes.value; + return O; +}; - if (srcStat.isSymbolicLink()) { - onFresh(); - const linkname = yield readlink(src); - actions.symlink.push({ - dest, - linkname - }); - onDone(); - } else if (srcStat.isDirectory()) { - reporter.verbose(reporter.lang('verboseFileFolder', dest)); - yield mkdirp(dest); - const destParts = dest.split((_path || _load_path()).default.sep); - while (destParts.length) { - files.add(destParts.join((_path || _load_path()).default.sep).toLowerCase()); - destParts.pop(); - } +/***/ }), +/* 51 */, +/* 52 */, +/* 53 */, +/* 54 */ +/***/ (function(module, exports) { - // push all files to queue - invariant(srcFiles, 'src files not initialised'); - let remaining = srcFiles.length; - if (!remaining) { - onDone(); - } - for (var _iterator12 = srcFiles, _isArray12 = Array.isArray(_iterator12), _i12 = 0, _iterator12 = _isArray12 ? _iterator12 : _iterator12[Symbol.iterator]();;) { - var _ref16; +module.exports = __webpack_require__(156); - if (_isArray12) { - if (_i12 >= _iterator12.length) break; - _ref16 = _iterator12[_i12++]; - } else { - _i12 = _iterator12.next(); - if (_i12.done) break; - _ref16 = _i12.value; - } +/***/ }), +/* 55 */ +/***/ (function(module, exports, __webpack_require__) { - const file = _ref16; +"use strict"; - queue.push({ - onFresh, - src: (_path || _load_path()).default.join(src, file), - dest: (_path || _load_path()).default.join(dest, file), - onDone: function (_onDone2) { - function onDone() { - return _onDone2.apply(this, arguments); - } - onDone.toString = function () { - return _onDone2.toString(); - }; +const Buffer = __webpack_require__(32).Buffer - return onDone; - }(function () { - if (--remaining === 0) { - onDone(); - } - }) - }); - } - } else if (srcStat.isFile()) { - onFresh(); - actions.link.push({ - src, - dest, - removeDest: destExists - }); - onDone(); - } else { - throw new Error(`unsure how to copy this: ${src}`); - } - }); +const crypto = __webpack_require__(9) +const Transform = __webpack_require__(17).Transform - return function build(_x10) { - return _ref13.apply(this, arguments); - }; - })(); +const SPEC_ALGORITHMS = ['sha256', 'sha384', 'sha512'] - const artifactFiles = new Set(events.artifactFiles || []); - const files = new Set(); +const BASE64_REGEX = /^[a-z0-9+/]+(?:=?=?)$/i +const SRI_REGEX = /^([^-]+)-([^?]+)([?\S*]*)$/ +const STRICT_SRI_REGEX = /^([^-]+)-([A-Za-z0-9+/=]{44,88})(\?[\x21-\x7E]*)*$/ +const VCHAR_REGEX = /^[\x21-\x7E]+$/ - // initialise events - for (var _iterator7 = queue, _isArray7 = Array.isArray(_iterator7), _i7 = 0, _iterator7 = _isArray7 ? _iterator7 : _iterator7[Symbol.iterator]();;) { - var _ref10; +class Hash { + get isHash () { return true } + constructor (hash, opts) { + const strict = !!(opts && opts.strict) + this.source = hash.trim() + // 3.1. Integrity metadata (called "Hash" by ssri) + // https://w3c.github.io/webappsec-subresource-integrity/#integrity-metadata-description + const match = this.source.match( + strict + ? STRICT_SRI_REGEX + : SRI_REGEX + ) + if (!match) { return } + if (strict && !SPEC_ALGORITHMS.some(a => a === match[1])) { return } + this.algorithm = match[1] + this.digest = match[2] - if (_isArray7) { - if (_i7 >= _iterator7.length) break; - _ref10 = _iterator7[_i7++]; - } else { - _i7 = _iterator7.next(); - if (_i7.done) break; - _ref10 = _i7.value; + const rawOpts = match[3] + this.options = rawOpts ? rawOpts.slice(1).split('?') : [] + } + hexDigest () { + return this.digest && Buffer.from(this.digest, 'base64').toString('hex') + } + toJSON () { + return this.toString() + } + toString (opts) { + if (opts && opts.strict) { + // Strict mode enforces the standard as close to the foot of the + // letter as it can. + if (!( + // The spec has very restricted productions for algorithms. + // https://www.w3.org/TR/CSP2/#source-list-syntax + SPEC_ALGORITHMS.some(x => x === this.algorithm) && + // Usually, if someone insists on using a "different" base64, we + // leave it as-is, since there's multiple standards, and the + // specified is not a URL-safe variant. + // https://www.w3.org/TR/CSP2/#base64_value + this.digest.match(BASE64_REGEX) && + // Option syntax is strictly visual chars. + // https://w3c.github.io/webappsec-subresource-integrity/#grammardef-option-expression + // https://tools.ietf.org/html/rfc5234#appendix-B.1 + (this.options || []).every(opt => opt.match(VCHAR_REGEX)) + )) { + return '' } - - const item = _ref10; - - const onDone = item.onDone || noop; - item.onDone = function () { - events.onProgress(item.dest); - onDone(); - }; } - events.onStart(queue.length); - - // start building actions - const actions = { - file: [], - symlink: [], - link: [] - }; + const options = this.options && this.options.length + ? `?${this.options.join('?')}` + : '' + return `${this.algorithm}-${this.digest}${options}` + } +} - // custom concurrency logic as we're always executing stacks of CONCURRENT_QUEUE_ITEMS queue items - // at a time due to the requirement to push items onto the queue - while (queue.length) { - const items = queue.splice(0, CONCURRENT_QUEUE_ITEMS); - yield Promise.all(items.map(build)); +class Integrity { + get isIntegrity () { return true } + toJSON () { + return this.toString() + } + toString (opts) { + opts = opts || {} + let sep = opts.sep || ' ' + if (opts.strict) { + // Entries must be separated by whitespace, according to spec. + sep = sep.replace(/\S+/g, ' ') } - - // simulate the existence of some files to prevent considering them extraneous - for (var _iterator8 = artifactFiles, _isArray8 = Array.isArray(_iterator8), _i8 = 0, _iterator8 = _isArray8 ? _iterator8 : _iterator8[Symbol.iterator]();;) { - var _ref11; - - if (_isArray8) { - if (_i8 >= _iterator8.length) break; - _ref11 = _iterator8[_i8++]; - } else { - _i8 = _iterator8.next(); - if (_i8.done) break; - _ref11 = _i8.value; - } - - const file = _ref11; - - if (possibleExtraneous.has(file)) { - reporter.verbose(reporter.lang('verboseFilePhantomExtraneous', file)); - possibleExtraneous.delete(file); - } + return Object.keys(this).map(k => { + return this[k].map(hash => { + return Hash.prototype.toString.call(hash, opts) + }).filter(x => x.length).join(sep) + }).filter(x => x.length).join(sep) + } + concat (integrity, opts) { + const other = typeof integrity === 'string' + ? integrity + : stringify(integrity, opts) + return parse(`${this.toString(opts)} ${other}`, opts) + } + hexDigest () { + return parse(this, {single: true}).hexDigest() + } + match (integrity, opts) { + const other = parse(integrity, opts) + const algo = other.pickAlgorithm(opts) + return ( + this[algo] && + other[algo] && + this[algo].find(hash => + other[algo].find(otherhash => + hash.digest === otherhash.digest + ) + ) + ) || false + } + pickAlgorithm (opts) { + const pickAlgorithm = (opts && opts.pickAlgorithm) || getPrioritizedHash + const keys = Object.keys(this) + if (!keys.length) { + throw new Error(`No algorithms available for ${ + JSON.stringify(this.toString()) + }`) } + return keys.reduce((acc, algo) => { + return pickAlgorithm(acc, algo) || acc + }) + } +} - for (var _iterator9 = possibleExtraneous, _isArray9 = Array.isArray(_iterator9), _i9 = 0, _iterator9 = _isArray9 ? _iterator9 : _iterator9[Symbol.iterator]();;) { - var _ref12; - - if (_isArray9) { - if (_i9 >= _iterator9.length) break; - _ref12 = _iterator9[_i9++]; - } else { - _i9 = _iterator9.next(); - if (_i9.done) break; - _ref12 = _i9.value; - } - - const loc = _ref12; +module.exports.parse = parse +function parse (sri, opts) { + opts = opts || {} + if (typeof sri === 'string') { + return _parse(sri, opts) + } else if (sri.algorithm && sri.digest) { + const fullSri = new Integrity() + fullSri[sri.algorithm] = [sri] + return _parse(stringify(fullSri, opts), opts) + } else { + return _parse(stringify(sri, opts), opts) + } +} - if (files.has(loc.toLowerCase())) { - possibleExtraneous.delete(loc); - } +function _parse (integrity, opts) { + // 3.4.3. Parse metadata + // https://w3c.github.io/webappsec-subresource-integrity/#parse-metadata + if (opts.single) { + return new Hash(integrity, opts) + } + return integrity.trim().split(/\s+/).reduce((acc, string) => { + const hash = new Hash(string, opts) + if (hash.algorithm && hash.digest) { + const algo = hash.algorithm + if (!acc[algo]) { acc[algo] = [] } + acc[algo].push(hash) } + return acc + }, new Integrity()) +} - return actions; - }); - - return function buildActionsForHardlink(_x6, _x7, _x8, _x9) { - return _ref9.apply(this, arguments); - }; -})(); - -let copyBulk = exports.copyBulk = (() => { - var _ref17 = (0, (_asyncToGenerator2 || _load_asyncToGenerator()).default)(function* (queue, reporter, _events) { - const events = { - onStart: _events && _events.onStart || noop, - onProgress: _events && _events.onProgress || noop, - possibleExtraneous: _events ? _events.possibleExtraneous : new Set(), - ignoreBasenames: _events && _events.ignoreBasenames || [], - artifactFiles: _events && _events.artifactFiles || [] - }; +module.exports.stringify = stringify +function stringify (obj, opts) { + if (obj.algorithm && obj.digest) { + return Hash.prototype.toString.call(obj, opts) + } else if (typeof obj === 'string') { + return stringify(parse(obj, opts), opts) + } else { + return Integrity.prototype.toString.call(obj, opts) + } +} - const actions = yield buildActionsForCopy(queue, events, events.possibleExtraneous, reporter); - events.onStart(actions.file.length + actions.symlink.length + actions.link.length); +module.exports.fromHex = fromHex +function fromHex (hexDigest, algorithm, opts) { + const optString = (opts && opts.options && opts.options.length) + ? `?${opts.options.join('?')}` + : '' + return parse( + `${algorithm}-${ + Buffer.from(hexDigest, 'hex').toString('base64') + }${optString}`, opts + ) +} - const fileActions = actions.file; +module.exports.fromData = fromData +function fromData (data, opts) { + opts = opts || {} + const algorithms = opts.algorithms || ['sha512'] + const optString = opts.options && opts.options.length + ? `?${opts.options.join('?')}` + : '' + return algorithms.reduce((acc, algo) => { + const digest = crypto.createHash(algo).update(data).digest('base64') + const hash = new Hash( + `${algo}-${digest}${optString}`, + opts + ) + if (hash.algorithm && hash.digest) { + const algo = hash.algorithm + if (!acc[algo]) { acc[algo] = [] } + acc[algo].push(hash) + } + return acc + }, new Integrity()) +} - const currentlyWriting = new Map(); +module.exports.fromStream = fromStream +function fromStream (stream, opts) { + opts = opts || {} + const P = opts.Promise || Promise + const istream = integrityStream(opts) + return new P((resolve, reject) => { + stream.pipe(istream) + stream.on('error', reject) + istream.on('error', reject) + let sri + istream.on('integrity', s => { sri = s }) + istream.on('end', () => resolve(sri)) + istream.on('data', () => {}) + }) +} - yield (_promise || _load_promise()).queue(fileActions, (() => { - var _ref18 = (0, (_asyncToGenerator2 || _load_asyncToGenerator()).default)(function* (data) { - let writePromise; - while (writePromise = currentlyWriting.get(data.dest)) { - yield writePromise; +module.exports.checkData = checkData +function checkData (data, sri, opts) { + opts = opts || {} + sri = parse(sri, opts) + if (!Object.keys(sri).length) { + if (opts.error) { + throw Object.assign( + new Error('No valid integrity hashes to check against'), { + code: 'EINTEGRITY' } + ) + } else { + return false + } + } + const algorithm = sri.pickAlgorithm(opts) + const digest = crypto.createHash(algorithm).update(data).digest('base64') + const newSri = parse({algorithm, digest}) + const match = newSri.match(sri, opts) + if (match || !opts.error) { + return match + } else if (typeof opts.size === 'number' && (data.length !== opts.size)) { + const err = new Error(`data size mismatch when checking ${sri}.\n Wanted: ${opts.size}\n Found: ${data.length}`) + err.code = 'EBADSIZE' + err.found = data.length + err.expected = opts.size + err.sri = sri + throw err + } else { + const err = new Error(`Integrity checksum failed when using ${algorithm}: Wanted ${sri}, but got ${newSri}. (${data.length} bytes)`) + err.code = 'EINTEGRITY' + err.found = newSri + err.expected = sri + err.algorithm = algorithm + err.sri = sri + throw err + } +} - reporter.verbose(reporter.lang('verboseFileCopy', data.src, data.dest)); - const copier = (0, (_fsNormalized || _load_fsNormalized()).copyFile)(data, function () { - return currentlyWriting.delete(data.dest); - }); - currentlyWriting.set(data.dest, copier); - events.onProgress(data.dest); - return copier; - }); +module.exports.checkStream = checkStream +function checkStream (stream, sri, opts) { + opts = opts || {} + const P = opts.Promise || Promise + const checker = integrityStream(Object.assign({}, opts, { + integrity: sri + })) + return new P((resolve, reject) => { + stream.pipe(checker) + stream.on('error', reject) + checker.on('error', reject) + let sri + checker.on('verified', s => { sri = s }) + checker.on('end', () => resolve(sri)) + checker.on('data', () => {}) + }) +} - return function (_x14) { - return _ref18.apply(this, arguments); - }; - })(), CONCURRENT_QUEUE_ITEMS); +module.exports.integrityStream = integrityStream +function integrityStream (opts) { + opts = opts || {} + // For verification + const sri = opts.integrity && parse(opts.integrity, opts) + const goodSri = sri && Object.keys(sri).length + const algorithm = goodSri && sri.pickAlgorithm(opts) + const digests = goodSri && sri[algorithm] + // Calculating stream + const algorithms = Array.from( + new Set( + (opts.algorithms || ['sha512']) + .concat(algorithm ? [algorithm] : []) + ) + ) + const hashes = algorithms.map(crypto.createHash) + let streamSize = 0 + const stream = new Transform({ + transform (chunk, enc, cb) { + streamSize += chunk.length + hashes.forEach(h => h.update(chunk, enc)) + cb(null, chunk, enc) + } + }).on('end', () => { + const optString = (opts.options && opts.options.length) + ? `?${opts.options.join('?')}` + : '' + const newSri = parse(hashes.map((h, i) => { + return `${algorithms[i]}-${h.digest('base64')}${optString}` + }).join(' '), opts) + // Integrity verification mode + const match = goodSri && newSri.match(sri, opts) + if (typeof opts.size === 'number' && streamSize !== opts.size) { + const err = new Error(`stream size mismatch when checking ${sri}.\n Wanted: ${opts.size}\n Found: ${streamSize}`) + err.code = 'EBADSIZE' + err.found = streamSize + err.expected = opts.size + err.sri = sri + stream.emit('error', err) + } else if (opts.integrity && !match) { + const err = new Error(`${sri} integrity checksum failed when using ${algorithm}: wanted ${digests} but got ${newSri}. (${streamSize} bytes)`) + err.code = 'EINTEGRITY' + err.found = newSri + err.expected = digests + err.algorithm = algorithm + err.sri = sri + stream.emit('error', err) + } else { + stream.emit('size', streamSize) + stream.emit('integrity', newSri) + match && stream.emit('verified', match) + } + }) + return stream +} - // we need to copy symlinks last as they could reference files we were copying - const symlinkActions = actions.symlink; - yield (_promise || _load_promise()).queue(symlinkActions, function (data) { - const linkname = (_path || _load_path()).default.resolve((_path || _load_path()).default.dirname(data.dest), data.linkname); - reporter.verbose(reporter.lang('verboseFileSymlink', data.dest, linkname)); - return symlink(linkname, data.dest); - }); - }); +module.exports.create = createIntegrity +function createIntegrity (opts) { + opts = opts || {} + const algorithms = opts.algorithms || ['sha512'] + const optString = opts.options && opts.options.length + ? `?${opts.options.join('?')}` + : '' - return function copyBulk(_x11, _x12, _x13) { - return _ref17.apply(this, arguments); - }; -})(); + const hashes = algorithms.map(crypto.createHash) -let hardlinkBulk = exports.hardlinkBulk = (() => { - var _ref19 = (0, (_asyncToGenerator2 || _load_asyncToGenerator()).default)(function* (queue, reporter, _events) { - const events = { - onStart: _events && _events.onStart || noop, - onProgress: _events && _events.onProgress || noop, - possibleExtraneous: _events ? _events.possibleExtraneous : new Set(), - artifactFiles: _events && _events.artifactFiles || [], - ignoreBasenames: [] - }; + return { + update: function (chunk, enc) { + hashes.forEach(h => h.update(chunk, enc)) + return this + }, + digest: function (enc) { + const integrity = algorithms.reduce((acc, algo) => { + const digest = hashes.shift().digest('base64') + const hash = new Hash( + `${algo}-${digest}${optString}`, + opts + ) + if (hash.algorithm && hash.digest) { + const algo = hash.algorithm + if (!acc[algo]) { acc[algo] = [] } + acc[algo].push(hash) + } + return acc + }, new Integrity()) - const actions = yield buildActionsForHardlink(queue, events, events.possibleExtraneous, reporter); - events.onStart(actions.file.length + actions.symlink.length + actions.link.length); + return integrity + } + } +} - const fileActions = actions.link; +const NODE_HASHES = new Set(crypto.getHashes()) - yield (_promise || _load_promise()).queue(fileActions, (() => { - var _ref20 = (0, (_asyncToGenerator2 || _load_asyncToGenerator()).default)(function* (data) { - reporter.verbose(reporter.lang('verboseFileLink', data.src, data.dest)); - if (data.removeDest) { - yield (0, (_fsNormalized || _load_fsNormalized()).unlink)(data.dest); - } - yield link(data.src, data.dest); - }); +// This is a Best Effort™ at a reasonable priority for hash algos +const DEFAULT_PRIORITY = [ + 'md5', 'whirlpool', 'sha1', 'sha224', 'sha256', 'sha384', 'sha512', + // TODO - it's unclear _which_ of these Node will actually use as its name + // for the algorithm, so we guesswork it based on the OpenSSL names. + 'sha3', + 'sha3-256', 'sha3-384', 'sha3-512', + 'sha3_256', 'sha3_384', 'sha3_512' +].filter(algo => NODE_HASHES.has(algo)) - return function (_x18) { - return _ref20.apply(this, arguments); - }; - })(), CONCURRENT_QUEUE_ITEMS); +function getPrioritizedHash (algo1, algo2) { + return DEFAULT_PRIORITY.indexOf(algo1.toLowerCase()) >= DEFAULT_PRIORITY.indexOf(algo2.toLowerCase()) + ? algo1 + : algo2 +} - // we need to copy symlinks last as they could reference files we were copying - const symlinkActions = actions.symlink; - yield (_promise || _load_promise()).queue(symlinkActions, function (data) { - const linkname = (_path || _load_path()).default.resolve((_path || _load_path()).default.dirname(data.dest), data.linkname); - reporter.verbose(reporter.lang('verboseFileSymlink', data.dest, linkname)); - return symlink(linkname, data.dest); - }); - }); - return function hardlinkBulk(_x15, _x16, _x17) { - return _ref19.apply(this, arguments); - }; -})(); +/***/ }), +/* 56 */, +/* 57 */, +/* 58 */, +/* 59 */, +/* 60 */ +/***/ (function(module, exports, __webpack_require__) { -let readFileAny = exports.readFileAny = (() => { - var _ref21 = (0, (_asyncToGenerator2 || _load_asyncToGenerator()).default)(function* (files) { - for (var _iterator13 = files, _isArray13 = Array.isArray(_iterator13), _i13 = 0, _iterator13 = _isArray13 ? _iterator13 : _iterator13[Symbol.iterator]();;) { - var _ref22; +module.exports = minimatch +minimatch.Minimatch = Minimatch - if (_isArray13) { - if (_i13 >= _iterator13.length) break; - _ref22 = _iterator13[_i13++]; - } else { - _i13 = _iterator13.next(); - if (_i13.done) break; - _ref22 = _i13.value; - } +var path = { sep: '/' } +try { + path = __webpack_require__(0) +} catch (er) {} - const file = _ref22; +var GLOBSTAR = minimatch.GLOBSTAR = Minimatch.GLOBSTAR = {} +var expand = __webpack_require__(175) - if (yield exists(file)) { - return readFile(file); - } - } - return null; - }); +var plTypes = { + '!': { open: '(?:(?!(?:', close: '))[^/]*?)'}, + '?': { open: '(?:', close: ')?' }, + '+': { open: '(?:', close: ')+' }, + '*': { open: '(?:', close: ')*' }, + '@': { open: '(?:', close: ')' } +} - return function readFileAny(_x19) { - return _ref21.apply(this, arguments); - }; -})(); +// any single thing other than / +// don't need to escape / when using new RegExp() +var qmark = '[^/]' -let readJson = exports.readJson = (() => { - var _ref23 = (0, (_asyncToGenerator2 || _load_asyncToGenerator()).default)(function* (loc) { - return (yield readJsonAndFile(loc)).object; - }); +// * => any number of characters +var star = qmark + '*?' - return function readJson(_x20) { - return _ref23.apply(this, arguments); - }; -})(); +// ** when dots are allowed. Anything goes, except .. and . +// not (^ or / followed by one or two dots followed by $ or /), +// followed by anything, any number of times. +var twoStarDot = '(?:(?!(?:\\\/|^)(?:\\.{1,2})($|\\\/)).)*?' -let readJsonAndFile = exports.readJsonAndFile = (() => { - var _ref24 = (0, (_asyncToGenerator2 || _load_asyncToGenerator()).default)(function* (loc) { - const file = yield readFile(loc); - try { - return { - object: (0, (_map || _load_map()).default)(JSON.parse(stripBOM(file))), - content: file - }; - } catch (err) { - err.message = `${loc}: ${err.message}`; - throw err; - } - }); +// not a ^ or / followed by a dot, +// followed by anything, any number of times. +var twoStarNoDot = '(?:(?!(?:\\\/|^)\\.).)*?' - return function readJsonAndFile(_x21) { - return _ref24.apply(this, arguments); - }; -})(); +// characters that need to be escaped in RegExp. +var reSpecials = charSet('().*{}+?[]^$\\!') -let find = exports.find = (() => { - var _ref25 = (0, (_asyncToGenerator2 || _load_asyncToGenerator()).default)(function* (filename, dir) { - const parts = dir.split((_path || _load_path()).default.sep); +// "abc" -> { a:true, b:true, c:true } +function charSet (s) { + return s.split('').reduce(function (set, c) { + set[c] = true + return set + }, {}) +} - while (parts.length) { - const loc = parts.concat(filename).join((_path || _load_path()).default.sep); +// normalizes slashes. +var slashSplit = /\/+/ - if (yield exists(loc)) { - return loc; - } else { - parts.pop(); - } - } +minimatch.filter = filter +function filter (pattern, options) { + options = options || {} + return function (p, i, list) { + return minimatch(p, pattern, options) + } +} - return false; - }); +function ext (a, b) { + a = a || {} + b = b || {} + var t = {} + Object.keys(b).forEach(function (k) { + t[k] = b[k] + }) + Object.keys(a).forEach(function (k) { + t[k] = a[k] + }) + return t +} - return function find(_x22, _x23) { - return _ref25.apply(this, arguments); - }; -})(); +minimatch.defaults = function (def) { + if (!def || !Object.keys(def).length) return minimatch -let symlink = exports.symlink = (() => { - var _ref26 = (0, (_asyncToGenerator2 || _load_asyncToGenerator()).default)(function* (src, dest) { - try { - const stats = yield lstat(dest); - if (stats.isSymbolicLink()) { - const resolved = yield realpath(dest); - if (resolved === src) { - return; - } - } - } catch (err) { - if (err.code !== 'ENOENT') { - throw err; - } - } - // We use rimraf for unlink which never throws an ENOENT on missing target - yield (0, (_fsNormalized || _load_fsNormalized()).unlink)(dest); + var orig = minimatch - if (process.platform === 'win32') { - // use directory junctions if possible on win32, this requires absolute paths - yield fsSymlink(src, dest, 'junction'); - } else { - // use relative paths otherwise which will be retained if the directory is moved - let relative; - try { - relative = (_path || _load_path()).default.relative((_fs || _load_fs()).default.realpathSync((_path || _load_path()).default.dirname(dest)), (_fs || _load_fs()).default.realpathSync(src)); - } catch (err) { - if (err.code !== 'ENOENT') { - throw err; - } - relative = (_path || _load_path()).default.relative((_path || _load_path()).default.dirname(dest), src); - } - // When path.relative returns an empty string for the current directory, we should instead use - // '.', which is a valid fs.symlink target. - yield fsSymlink(relative || '.', dest); - } - }); + var m = function minimatch (p, pattern, options) { + return orig.minimatch(p, pattern, ext(def, options)) + } - return function symlink(_x24, _x25) { - return _ref26.apply(this, arguments); - }; -})(); + m.Minimatch = function Minimatch (pattern, options) { + return new orig.Minimatch(pattern, ext(def, options)) + } -let walk = exports.walk = (() => { - var _ref27 = (0, (_asyncToGenerator2 || _load_asyncToGenerator()).default)(function* (dir, relativeDir, ignoreBasenames = new Set()) { - let files = []; + return m +} - let filenames = yield readdir(dir); - if (ignoreBasenames.size) { - filenames = filenames.filter(function (name) { - return !ignoreBasenames.has(name); - }); - } +Minimatch.defaults = function (def) { + if (!def || !Object.keys(def).length) return Minimatch + return minimatch.defaults(def).Minimatch +} - for (var _iterator14 = filenames, _isArray14 = Array.isArray(_iterator14), _i14 = 0, _iterator14 = _isArray14 ? _iterator14 : _iterator14[Symbol.iterator]();;) { - var _ref28; +function minimatch (p, pattern, options) { + if (typeof pattern !== 'string') { + throw new TypeError('glob pattern string required') + } - if (_isArray14) { - if (_i14 >= _iterator14.length) break; - _ref28 = _iterator14[_i14++]; - } else { - _i14 = _iterator14.next(); - if (_i14.done) break; - _ref28 = _i14.value; - } + if (!options) options = {} - const name = _ref28; + // shortcut: comments match nothing. + if (!options.nocomment && pattern.charAt(0) === '#') { + return false + } - const relative = relativeDir ? (_path || _load_path()).default.join(relativeDir, name) : name; - const loc = (_path || _load_path()).default.join(dir, name); - const stat = yield lstat(loc); + // "" only matches "" + if (pattern.trim() === '') return p === '' - files.push({ - relative, - basename: name, - absolute: loc, - mtime: +stat.mtime - }); - - if (stat.isDirectory()) { - files = files.concat((yield walk(loc, relative, ignoreBasenames))); - } - } - - return files; - }); - - return function walk(_x26, _x27) { - return _ref27.apply(this, arguments); - }; -})(); + return new Minimatch(pattern, options).match(p) +} -let getFileSizeOnDisk = exports.getFileSizeOnDisk = (() => { - var _ref29 = (0, (_asyncToGenerator2 || _load_asyncToGenerator()).default)(function* (loc) { - const stat = yield lstat(loc); - const size = stat.size, - blockSize = stat.blksize; +function Minimatch (pattern, options) { + if (!(this instanceof Minimatch)) { + return new Minimatch(pattern, options) + } + if (typeof pattern !== 'string') { + throw new TypeError('glob pattern string required') + } - return Math.ceil(size / blockSize) * blockSize; - }); + if (!options) options = {} + pattern = pattern.trim() - return function getFileSizeOnDisk(_x28) { - return _ref29.apply(this, arguments); - }; -})(); + // windows support: need to use /, not \ + if (path.sep !== '/') { + pattern = pattern.split(path.sep).join('/') + } -let getEolFromFile = (() => { - var _ref30 = (0, (_asyncToGenerator2 || _load_asyncToGenerator()).default)(function* (path) { - if (!(yield exists(path))) { - return undefined; - } + this.options = options + this.set = [] + this.pattern = pattern + this.regexp = null + this.negate = false + this.comment = false + this.empty = false - const buffer = yield readFileBuffer(path); + // make the set of regexps etc. + this.make() +} - for (let i = 0; i < buffer.length; ++i) { - if (buffer[i] === cr) { - return '\r\n'; - } - if (buffer[i] === lf) { - return '\n'; - } - } - return undefined; - }); +Minimatch.prototype.debug = function () {} - return function getEolFromFile(_x29) { - return _ref30.apply(this, arguments); - }; -})(); +Minimatch.prototype.make = make +function make () { + // don't do it more than once. + if (this._made) return -let writeFilePreservingEol = exports.writeFilePreservingEol = (() => { - var _ref31 = (0, (_asyncToGenerator2 || _load_asyncToGenerator()).default)(function* (path, data) { - const eol = (yield getEolFromFile(path)) || (_os || _load_os()).default.EOL; - if (eol !== '\n') { - data = data.replace(/\n/g, eol); - } - yield writeFile(path, data); - }); + var pattern = this.pattern + var options = this.options - return function writeFilePreservingEol(_x30, _x31) { - return _ref31.apply(this, arguments); - }; -})(); + // empty patterns and comments match nothing. + if (!options.nocomment && pattern.charAt(0) === '#') { + this.comment = true + return + } + if (!pattern) { + this.empty = true + return + } -let hardlinksWork = exports.hardlinksWork = (() => { - var _ref32 = (0, (_asyncToGenerator2 || _load_asyncToGenerator()).default)(function* (dir) { - const filename = 'test-file' + Math.random(); - const file = (_path || _load_path()).default.join(dir, filename); - const fileLink = (_path || _load_path()).default.join(dir, filename + '-link'); - try { - yield writeFile(file, 'test'); - yield link(file, fileLink); - } catch (err) { - return false; - } finally { - yield (0, (_fsNormalized || _load_fsNormalized()).unlink)(file); - yield (0, (_fsNormalized || _load_fsNormalized()).unlink)(fileLink); - } - return true; - }); + // step 1: figure out negation, etc. + this.parseNegate() - return function hardlinksWork(_x32) { - return _ref32.apply(this, arguments); - }; -})(); + // step 2: expand braces + var set = this.globSet = this.braceExpand() -// not a strict polyfill for Node's fs.mkdtemp + if (options.debug) this.debug = console.error + this.debug(this.pattern, set) -let makeTempDir = exports.makeTempDir = (() => { - var _ref33 = (0, (_asyncToGenerator2 || _load_asyncToGenerator()).default)(function* (prefix) { - const dir = (_path || _load_path()).default.join((_os || _load_os()).default.tmpdir(), `yarn-${prefix || ''}-${Date.now()}-${Math.random()}`); - yield (0, (_fsNormalized || _load_fsNormalized()).unlink)(dir); - yield mkdirp(dir); - return dir; - }); + // step 3: now we have a set, so turn each one into a series of path-portion + // matching patterns. + // These will be regexps, except in the case of "**", which is + // set to the GLOBSTAR object for globstar behavior, + // and will not contain any / characters + set = this.globParts = set.map(function (s) { + return s.split(slashSplit) + }) - return function makeTempDir(_x33) { - return _ref33.apply(this, arguments); - }; -})(); + this.debug(this.pattern, set) -let readFirstAvailableStream = exports.readFirstAvailableStream = (() => { - var _ref34 = (0, (_asyncToGenerator2 || _load_asyncToGenerator()).default)(function* (paths) { - for (var _iterator15 = paths, _isArray15 = Array.isArray(_iterator15), _i15 = 0, _iterator15 = _isArray15 ? _iterator15 : _iterator15[Symbol.iterator]();;) { - var _ref35; + // glob --> regexps + set = set.map(function (s, si, set) { + return s.map(this.parse, this) + }, this) - if (_isArray15) { - if (_i15 >= _iterator15.length) break; - _ref35 = _iterator15[_i15++]; - } else { - _i15 = _iterator15.next(); - if (_i15.done) break; - _ref35 = _i15.value; - } + this.debug(this.pattern, set) - const path = _ref35; + // filter out everything that didn't compile properly. + set = set.filter(function (s) { + return s.indexOf(false) === -1 + }) - try { - const fd = yield open(path, 'r'); - return (_fs || _load_fs()).default.createReadStream(path, { fd }); - } catch (err) { - // Try the next one - } - } - return null; - }); + this.debug(this.pattern, set) - return function readFirstAvailableStream(_x34) { - return _ref34.apply(this, arguments); - }; -})(); + this.set = set +} -let getFirstSuitableFolder = exports.getFirstSuitableFolder = (() => { - var _ref36 = (0, (_asyncToGenerator2 || _load_asyncToGenerator()).default)(function* (paths, mode = constants.W_OK | constants.X_OK) { - const result = { - skipped: [], - folder: null - }; +Minimatch.prototype.parseNegate = parseNegate +function parseNegate () { + var pattern = this.pattern + var negate = false + var options = this.options + var negateOffset = 0 - for (var _iterator16 = paths, _isArray16 = Array.isArray(_iterator16), _i16 = 0, _iterator16 = _isArray16 ? _iterator16 : _iterator16[Symbol.iterator]();;) { - var _ref37; + if (options.nonegate) return - if (_isArray16) { - if (_i16 >= _iterator16.length) break; - _ref37 = _iterator16[_i16++]; - } else { - _i16 = _iterator16.next(); - if (_i16.done) break; - _ref37 = _i16.value; - } + for (var i = 0, l = pattern.length + ; i < l && pattern.charAt(i) === '!' + ; i++) { + negate = !negate + negateOffset++ + } - const folder = _ref37; + if (negateOffset) this.pattern = pattern.substr(negateOffset) + this.negate = negate +} - try { - yield mkdirp(folder); - yield access(folder, mode); +// Brace expansion: +// a{b,c}d -> abd acd +// a{b,}c -> abc ac +// a{0..3}d -> a0d a1d a2d a3d +// a{b,c{d,e}f}g -> abg acdfg acefg +// a{b,c}d{e,f}g -> abdeg acdeg abdeg abdfg +// +// Invalid sets are not expanded. +// a{2..}b -> a{2..}b +// a{b}c -> a{b}c +minimatch.braceExpand = function (pattern, options) { + return braceExpand(pattern, options) +} - result.folder = folder; +Minimatch.prototype.braceExpand = braceExpand - return result; - } catch (error) { - result.skipped.push({ - error, - folder - }); - } +function braceExpand (pattern, options) { + if (!options) { + if (this instanceof Minimatch) { + options = this.options + } else { + options = {} } - return result; - }); - - return function getFirstSuitableFolder(_x35) { - return _ref36.apply(this, arguments); - }; -})(); - -exports.copy = copy; -exports.readFile = readFile; -exports.readFileRaw = readFileRaw; -exports.normalizeOS = normalizeOS; + } -var _fs; + pattern = typeof pattern === 'undefined' + ? this.pattern : pattern -function _load_fs() { - return _fs = _interopRequireDefault(__webpack_require__(3)); -} + if (typeof pattern === 'undefined') { + throw new TypeError('undefined pattern') + } -var _glob; + if (options.nobrace || + !pattern.match(/\{.*\}/)) { + // shortcut. no need to expand. + return [pattern] + } -function _load_glob() { - return _glob = _interopRequireDefault(__webpack_require__(75)); + return expand(pattern) } -var _os; +// parse a component of the expanded set. +// At this point, no pattern may contain "/" in it +// so we're going to return a 2d array, where each entry is the full +// pattern, split on '/', and then turned into a regular expression. +// A regexp is made at the end which joins each array with an +// escaped /, and another full one which joins each regexp with |. +// +// Following the lead of Bash 4.1, note that "**" only has special meaning +// when it is the *only* thing in a path portion. Otherwise, any series +// of * is equivalent to a single *. Globstar behavior is enabled by +// default, and can be disabled by setting options.noglobstar. +Minimatch.prototype.parse = parse +var SUBPARSE = {} +function parse (pattern, isSub) { + if (pattern.length > 1024 * 64) { + throw new TypeError('pattern is too long') + } -function _load_os() { - return _os = _interopRequireDefault(__webpack_require__(36)); -} + var options = this.options -var _path; + // shortcuts + if (!options.noglobstar && pattern === '**') return GLOBSTAR + if (pattern === '') return '' -function _load_path() { - return _path = _interopRequireDefault(__webpack_require__(0)); -} + var re = '' + var hasMagic = !!options.nocase + var escaping = false + // ? => one single character + var patternListStack = [] + var negativeLists = [] + var stateChar + var inClass = false + var reClassStart = -1 + var classStart = -1 + // . and .. never match anything that doesn't start with ., + // even when options.dot is set. + var patternStart = pattern.charAt(0) === '.' ? '' // anything + // not (start or / followed by . or .. followed by / or end) + : options.dot ? '(?!(?:^|\\\/)\\.{1,2}(?:$|\\\/))' + : '(?!\\.)' + var self = this -var _blockingQueue; + function clearStateChar () { + if (stateChar) { + // we had some state-tracking character + // that wasn't consumed by this pass. + switch (stateChar) { + case '*': + re += star + hasMagic = true + break + case '?': + re += qmark + hasMagic = true + break + default: + re += '\\' + stateChar + break + } + self.debug('clearStateChar %j %j', stateChar, re) + stateChar = false + } + } -function _load_blockingQueue() { - return _blockingQueue = _interopRequireDefault(__webpack_require__(84)); -} + for (var i = 0, len = pattern.length, c + ; (i < len) && (c = pattern.charAt(i)) + ; i++) { + this.debug('%s\t%s %s %j', pattern, i, re, c) -var _promise; + // skip over any that are escaped. + if (escaping && reSpecials[c]) { + re += '\\' + c + escaping = false + continue + } -function _load_promise() { - return _promise = _interopRequireWildcard(__webpack_require__(40)); -} + switch (c) { + case '/': + // completely not allowed, even escaped. + // Should already be path-split by now. + return false -var _promise2; + case '\\': + clearStateChar() + escaping = true + continue -function _load_promise2() { - return _promise2 = __webpack_require__(40); -} + // the various stateChar values + // for the "extglob" stuff. + case '?': + case '*': + case '+': + case '@': + case '!': + this.debug('%s\t%s %s %j <-- stateChar', pattern, i, re, c) -var _map; + // all of those are literals inside a class, except that + // the glob [!a] means [^a] in regexp + if (inClass) { + this.debug(' in class') + if (c === '!' && i === classStart + 1) c = '^' + re += c + continue + } -function _load_map() { - return _map = _interopRequireDefault(__webpack_require__(20)); -} + // if we already have a stateChar, then it means + // that there was something like ** or +? in there. + // Handle the stateChar, then proceed with this one. + self.debug('call clearStateChar %j', stateChar) + clearStateChar() + stateChar = c + // if extglob is disabled, then +(asdf|foo) isn't a thing. + // just clear the statechar *now*, rather than even diving into + // the patternList stuff. + if (options.noext) clearStateChar() + continue -var _fsNormalized; + case '(': + if (inClass) { + re += '(' + continue + } -function _load_fsNormalized() { - return _fsNormalized = __webpack_require__(164); -} + if (!stateChar) { + re += '\\(' + continue + } -function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + patternListStack.push({ + type: stateChar, + start: i - 1, + reStart: re.length, + open: plTypes[stateChar].open, + close: plTypes[stateChar].close + }) + // negation is (?:(?!js)[^/]*) + re += stateChar === '!' ? '(?:(?!(?:' : '(?:' + this.debug('plType %j %j', stateChar, re) + stateChar = false + continue -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + case ')': + if (inClass || !patternListStack.length) { + re += '\\)' + continue + } -const constants = exports.constants = typeof (_fs || _load_fs()).default.constants !== 'undefined' ? (_fs || _load_fs()).default.constants : { - R_OK: (_fs || _load_fs()).default.R_OK, - W_OK: (_fs || _load_fs()).default.W_OK, - X_OK: (_fs || _load_fs()).default.X_OK -}; + clearStateChar() + hasMagic = true + var pl = patternListStack.pop() + // negation is (?:(?!js)[^/]*) + // The others are (?:) + re += pl.close + if (pl.type === '!') { + negativeLists.push(pl) + } + pl.reEnd = re.length + continue -const lockQueue = exports.lockQueue = new (_blockingQueue || _load_blockingQueue()).default('fs lock'); + case '|': + if (inClass || !patternListStack.length || escaping) { + re += '\\|' + escaping = false + continue + } -const readFileBuffer = exports.readFileBuffer = (0, (_promise2 || _load_promise2()).promisify)((_fs || _load_fs()).default.readFile); -const open = exports.open = (0, (_promise2 || _load_promise2()).promisify)((_fs || _load_fs()).default.open); -const writeFile = exports.writeFile = (0, (_promise2 || _load_promise2()).promisify)((_fs || _load_fs()).default.writeFile); -const readlink = exports.readlink = (0, (_promise2 || _load_promise2()).promisify)((_fs || _load_fs()).default.readlink); -const realpath = exports.realpath = (0, (_promise2 || _load_promise2()).promisify)((_fs || _load_fs()).default.realpath); -const readdir = exports.readdir = (0, (_promise2 || _load_promise2()).promisify)((_fs || _load_fs()).default.readdir); -const rename = exports.rename = (0, (_promise2 || _load_promise2()).promisify)((_fs || _load_fs()).default.rename); -const access = exports.access = (0, (_promise2 || _load_promise2()).promisify)((_fs || _load_fs()).default.access); -const stat = exports.stat = (0, (_promise2 || _load_promise2()).promisify)((_fs || _load_fs()).default.stat); -const mkdirp = exports.mkdirp = (0, (_promise2 || _load_promise2()).promisify)(__webpack_require__(116)); -const exists = exports.exists = (0, (_promise2 || _load_promise2()).promisify)((_fs || _load_fs()).default.exists, true); -const lstat = exports.lstat = (0, (_promise2 || _load_promise2()).promisify)((_fs || _load_fs()).default.lstat); -const chmod = exports.chmod = (0, (_promise2 || _load_promise2()).promisify)((_fs || _load_fs()).default.chmod); -const link = exports.link = (0, (_promise2 || _load_promise2()).promisify)((_fs || _load_fs()).default.link); -const glob = exports.glob = (0, (_promise2 || _load_promise2()).promisify)((_glob || _load_glob()).default); -exports.unlink = (_fsNormalized || _load_fsNormalized()).unlink; + clearStateChar() + re += '|' + continue -// fs.copyFile uses the native file copying instructions on the system, performing much better -// than any JS-based solution and consumes fewer resources. Repeated testing to fine tune the -// concurrency level revealed 128 as the sweet spot on a quad-core, 16 CPU Intel system with SSD. + // these are mostly the same in regexp and glob + case '[': + // swallow any state-tracking char before the [ + clearStateChar() -const CONCURRENT_QUEUE_ITEMS = (_fs || _load_fs()).default.copyFile ? 128 : 4; + if (inClass) { + re += '\\' + c + continue + } -const fsSymlink = (0, (_promise2 || _load_promise2()).promisify)((_fs || _load_fs()).default.symlink); -const invariant = __webpack_require__(7); -const stripBOM = __webpack_require__(122); + inClass = true + classStart = i + reClassStart = re.length + re += c + continue -const noop = () => {}; + case ']': + // a right bracket shall lose its special + // meaning and represent itself in + // a bracket expression if it occurs + // first in the list. -- POSIX.2 2.8.3.2 + if (i === classStart + 1 || !inClass) { + re += '\\' + c + escaping = false + continue + } -function copy(src, dest, reporter) { - return copyBulk([{ src, dest }], reporter); -} - -function _readFile(loc, encoding) { - return new Promise((resolve, reject) => { - (_fs || _load_fs()).default.readFile(loc, encoding, function (err, content) { - if (err) { - reject(err); - } else { - resolve(content); - } - }); - }); -} - -function readFile(loc) { - return _readFile(loc, 'utf8').then(normalizeOS); -} - -function readFileRaw(loc) { - return _readFile(loc, 'binary'); -} + // handle the case where we left a class open. + // "[z-a]" is valid, equivalent to "\[z-a\]" + if (inClass) { + // split where the last [ was, make sure we don't have + // an invalid re. if so, re-walk the contents of the + // would-be class to re-translate any characters that + // were passed through as-is + // TODO: It would probably be faster to determine this + // without a try/catch and a new RegExp, but it's tricky + // to do safely. For now, this is safe and works. + var cs = pattern.substring(classStart + 1, i) + try { + RegExp('[' + cs + ']') + } catch (er) { + // not a valid class! + var sp = this.parse(cs, SUBPARSE) + re = re.substr(0, reClassStart) + '\\[' + sp[0] + '\\]' + hasMagic = hasMagic || sp[1] + inClass = false + continue + } + } -function normalizeOS(body) { - return body.replace(/\r\n/g, '\n'); -} + // finish up the class. + hasMagic = true + inClass = false + re += c + continue -const cr = '\r'.charCodeAt(0); -const lf = '\n'.charCodeAt(0); + default: + // swallow any state char that wasn't consumed + clearStateChar() -/***/ }), -/* 6 */ -/***/ (function(module, exports, __webpack_require__) { + if (escaping) { + // no need + escaping = false + } else if (reSpecials[c] + && !(c === '^' && inClass)) { + re += '\\' + } -"use strict"; + re += c + } // switch + } // for -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.getPathKey = getPathKey; -const os = __webpack_require__(36); -const path = __webpack_require__(0); -const userHome = __webpack_require__(45).default; + // handle the case where we left a class open. + // "[abc" is valid, equivalent to "\[abc" + if (inClass) { + // split where the last [ was, and escape it + // this is a huge pita. We now have to re-walk + // the contents of the would-be class to re-translate + // any characters that were passed through as-is + cs = pattern.substr(classStart + 1) + sp = this.parse(cs, SUBPARSE) + re = re.substr(0, reClassStart) + '\\[' + sp[0] + hasMagic = hasMagic || sp[1] + } -var _require = __webpack_require__(171); + // handle the case where we had a +( thing at the *end* + // of the pattern. + // each pattern list stack adds 3 chars, and we need to go through + // and escape any | chars that were passed through as-is for the regexp. + // Go through and escape them, taking care not to double-escape any + // | chars that were already escaped. + for (pl = patternListStack.pop(); pl; pl = patternListStack.pop()) { + var tail = re.slice(pl.reStart + pl.open.length) + this.debug('setting tail', re, pl) + // maybe some even number of \, then maybe 1 \, followed by a | + tail = tail.replace(/((?:\\{2}){0,64})(\\?)\|/g, function (_, $1, $2) { + if (!$2) { + // the | isn't already escaped, so escape it. + $2 = '\\' + } -const getCacheDir = _require.getCacheDir, - getConfigDir = _require.getConfigDir, - getDataDir = _require.getDataDir; + // need to escape all those slashes *again*, without escaping the + // one that we need for escaping the | character. As it works out, + // escaping an even number of slashes can be done by simply repeating + // it exactly after itself. That's why this trick works. + // + // I am sorry that you have to see this. + return $1 + $1 + $2 + '|' + }) -const isWebpackBundle = __webpack_require__(227); + this.debug('tail=%j\n %s', tail, tail, pl, re) + var t = pl.type === '*' ? star + : pl.type === '?' ? qmark + : '\\' + pl.type -const DEPENDENCY_TYPES = exports.DEPENDENCY_TYPES = ['devDependencies', 'dependencies', 'optionalDependencies', 'peerDependencies']; -const RESOLUTIONS = exports.RESOLUTIONS = 'resolutions'; -const MANIFEST_FIELDS = exports.MANIFEST_FIELDS = [RESOLUTIONS, ...DEPENDENCY_TYPES]; + hasMagic = true + re = re.slice(0, pl.reStart) + t + '\\(' + tail + } -const SUPPORTED_NODE_VERSIONS = exports.SUPPORTED_NODE_VERSIONS = '^4.8.0 || ^5.7.0 || ^6.2.2 || >=8.0.0'; + // handle trailing things that only matter at the very end. + clearStateChar() + if (escaping) { + // trailing \\ + re += '\\\\' + } -const YARN_REGISTRY = exports.YARN_REGISTRY = 'https://registry.yarnpkg.com'; + // only need to apply the nodot start if the re starts with + // something that could conceivably capture a dot + var addPatternStart = false + switch (re.charAt(0)) { + case '.': + case '[': + case '(': addPatternStart = true + } -const YARN_DOCS = exports.YARN_DOCS = 'https://yarnpkg.com/en/docs/cli/'; -const YARN_INSTALLER_SH = exports.YARN_INSTALLER_SH = 'https://yarnpkg.com/install.sh'; -const YARN_INSTALLER_MSI = exports.YARN_INSTALLER_MSI = 'https://yarnpkg.com/latest.msi'; + // Hack to work around lack of negative lookbehind in JS + // A pattern like: *.!(x).!(y|z) needs to ensure that a name + // like 'a.xyz.yz' doesn't match. So, the first negative + // lookahead, has to look ALL the way ahead, to the end of + // the pattern. + for (var n = negativeLists.length - 1; n > -1; n--) { + var nl = negativeLists[n] -const SELF_UPDATE_VERSION_URL = exports.SELF_UPDATE_VERSION_URL = 'https://yarnpkg.com/latest-version'; + var nlBefore = re.slice(0, nl.reStart) + var nlFirst = re.slice(nl.reStart, nl.reEnd - 8) + var nlLast = re.slice(nl.reEnd - 8, nl.reEnd) + var nlAfter = re.slice(nl.reEnd) -// cache version, bump whenever we make backwards incompatible changes -const CACHE_VERSION = exports.CACHE_VERSION = 2; + nlLast += nlAfter -// lockfile version, bump whenever we make backwards incompatible changes -const LOCKFILE_VERSION = exports.LOCKFILE_VERSION = 1; + // Handle nested stuff like *(*.js|!(*.json)), where open parens + // mean that we should *not* include the ) in the bit that is considered + // "after" the negated section. + var openParensBefore = nlBefore.split('(').length - 1 + var cleanAfter = nlAfter + for (i = 0; i < openParensBefore; i++) { + cleanAfter = cleanAfter.replace(/\)[+*?]?/, '') + } + nlAfter = cleanAfter -// max amount of network requests to perform concurrently -const NETWORK_CONCURRENCY = exports.NETWORK_CONCURRENCY = 8; + var dollar = '' + if (nlAfter === '' && isSub !== SUBPARSE) { + dollar = '$' + } + var newRe = nlBefore + nlFirst + nlAfter + dollar + nlLast + re = newRe + } -// HTTP timeout used when downloading packages -const NETWORK_TIMEOUT = exports.NETWORK_TIMEOUT = 30 * 1000; // in milliseconds + // if the re is not "" at this point, then we need to make sure + // it doesn't match against an empty path part. + // Otherwise a/* will match a/, which it should not. + if (re !== '' && hasMagic) { + re = '(?=.)' + re + } -// max amount of child processes to execute concurrently -const CHILD_CONCURRENCY = exports.CHILD_CONCURRENCY = 5; + if (addPatternStart) { + re = patternStart + re + } -const REQUIRED_PACKAGE_KEYS = exports.REQUIRED_PACKAGE_KEYS = ['name', 'version', '_uid']; + // parsing just a piece of a larger pattern. + if (isSub === SUBPARSE) { + return [re, hasMagic] + } -function getPreferredCacheDirectories() { - const preferredCacheDirectories = [getCacheDir()]; + // skip the regexp for non-magical patterns + // unescape anything in it, though, so that it'll be + // an exact match against a file etc. + if (!hasMagic) { + return globUnescape(pattern) + } - if (process.getuid) { - // $FlowFixMe: process.getuid exists, dammit - preferredCacheDirectories.push(path.join(os.tmpdir(), `.yarn-cache-${process.getuid()}`)); + var flags = options.nocase ? 'i' : '' + try { + var regExp = new RegExp('^' + re + '$', flags) + } catch (er) { + // If it was an invalid regular expression, then it can't match + // anything. This trick looks for a character after the end of + // the string, which is of course impossible, except in multi-line + // mode, but it's not a /m regex. + return new RegExp('$.') } - preferredCacheDirectories.push(path.join(os.tmpdir(), `.yarn-cache`)); + regExp._glob = pattern + regExp._src = re - return preferredCacheDirectories; + return regExp } -const PREFERRED_MODULE_CACHE_DIRECTORIES = exports.PREFERRED_MODULE_CACHE_DIRECTORIES = getPreferredCacheDirectories(); -const CONFIG_DIRECTORY = exports.CONFIG_DIRECTORY = getConfigDir(); -const DATA_DIRECTORY = exports.DATA_DIRECTORY = getDataDir(); -const LINK_REGISTRY_DIRECTORY = exports.LINK_REGISTRY_DIRECTORY = path.join(DATA_DIRECTORY, 'link'); -const GLOBAL_MODULE_DIRECTORY = exports.GLOBAL_MODULE_DIRECTORY = path.join(DATA_DIRECTORY, 'global'); - -const NODE_BIN_PATH = exports.NODE_BIN_PATH = process.execPath; -const YARN_BIN_PATH = exports.YARN_BIN_PATH = getYarnBinPath(); - -// Webpack needs to be configured with node.__dirname/__filename = false -function getYarnBinPath() { - if (isWebpackBundle) { - return __filename; - } else { - return path.join(__dirname, '..', 'bin', 'yarn.js'); - } +minimatch.makeRe = function (pattern, options) { + return new Minimatch(pattern, options || {}).makeRe() } -const NODE_MODULES_FOLDER = exports.NODE_MODULES_FOLDER = 'node_modules'; -const NODE_PACKAGE_JSON = exports.NODE_PACKAGE_JSON = 'package.json'; - -const POSIX_GLOBAL_PREFIX = exports.POSIX_GLOBAL_PREFIX = `${process.env.DESTDIR || ''}/usr/local`; -const FALLBACK_GLOBAL_PREFIX = exports.FALLBACK_GLOBAL_PREFIX = path.join(userHome, '.yarn'); +Minimatch.prototype.makeRe = makeRe +function makeRe () { + if (this.regexp || this.regexp === false) return this.regexp -const META_FOLDER = exports.META_FOLDER = '.yarn-meta'; -const INTEGRITY_FILENAME = exports.INTEGRITY_FILENAME = '.yarn-integrity'; -const LOCKFILE_FILENAME = exports.LOCKFILE_FILENAME = 'yarn.lock'; -const METADATA_FILENAME = exports.METADATA_FILENAME = '.yarn-metadata.json'; -const TARBALL_FILENAME = exports.TARBALL_FILENAME = '.yarn-tarball.tgz'; -const CLEAN_FILENAME = exports.CLEAN_FILENAME = '.yarnclean'; + // at this point, this.set is a 2d array of partial + // pattern strings, or "**". + // + // It's better to use .match(). This function shouldn't + // be used, really, but it's pretty convenient sometimes, + // when you just want to work with a regex. + var set = this.set -const NPM_LOCK_FILENAME = exports.NPM_LOCK_FILENAME = 'package-lock.json'; -const NPM_SHRINKWRAP_FILENAME = exports.NPM_SHRINKWRAP_FILENAME = 'npm-shrinkwrap.json'; + if (!set.length) { + this.regexp = false + return this.regexp + } + var options = this.options -const DEFAULT_INDENT = exports.DEFAULT_INDENT = ' '; -const SINGLE_INSTANCE_PORT = exports.SINGLE_INSTANCE_PORT = 31997; -const SINGLE_INSTANCE_FILENAME = exports.SINGLE_INSTANCE_FILENAME = '.yarn-single-instance'; + var twoStar = options.noglobstar ? star + : options.dot ? twoStarDot + : twoStarNoDot + var flags = options.nocase ? 'i' : '' -const ENV_PATH_KEY = exports.ENV_PATH_KEY = getPathKey(process.platform, process.env); + var re = set.map(function (pattern) { + return pattern.map(function (p) { + return (p === GLOBSTAR) ? twoStar + : (typeof p === 'string') ? regExpEscape(p) + : p._src + }).join('\\\/') + }).join('|') -function getPathKey(platform, env) { - let pathKey = 'PATH'; + // must match entire pattern + // ending in a * or ** will make it less strict. + re = '^(?:' + re + ')$' - // windows calls its path "Path" usually, but this is not guaranteed. - if (platform === 'win32') { - pathKey = 'Path'; + // can match anything, as long as it's not this. + if (this.negate) re = '^(?!' + re + ').*$' - for (const key in env) { - if (key.toLowerCase() === 'path') { - pathKey = key; - } - } + try { + this.regexp = new RegExp(re, flags) + } catch (ex) { + this.regexp = false } + return this.regexp +} - return pathKey; +minimatch.match = function (list, pattern, options) { + options = options || {} + var mm = new Minimatch(pattern, options) + list = list.filter(function (f) { + return mm.match(f) + }) + if (mm.options.nonull && !list.length) { + list.push(pattern) + } + return list } -const VERSION_COLOR_SCHEME = exports.VERSION_COLOR_SCHEME = { - major: 'red', - premajor: 'red', - minor: 'yellow', - preminor: 'yellow', - patch: 'green', - prepatch: 'green', - prerelease: 'red', - unchanged: 'white', - unknown: 'red' -}; +Minimatch.prototype.match = match +function match (f, partial) { + this.debug('match', f, this.pattern) + // short-circuit in the case of busted things. + // comments, etc. + if (this.comment) return false + if (this.empty) return f === '' -/***/ }), -/* 7 */ -/***/ (function(module, exports, __webpack_require__) { + if (f === '/' && partial) return true -"use strict"; -/** - * Copyright (c) 2013-present, Facebook, Inc. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ + var options = this.options + // windows: need to use /, not \ + if (path.sep !== '/') { + f = f.split(path.sep).join('/') + } + // treat the test path as a set of pathparts. + f = f.split(slashSplit) + this.debug(this.pattern, 'split', f) -/** - * Use invariant() to assert state which your program assumes to be true. - * - * Provide sprintf-style format (only %s is supported) and arguments - * to provide information about what broke and what you were - * expecting. - * - * The invariant message will be stripped in production, but the invariant - * will remain to ensure logic does not differ in production. - */ + // just ONE of the pattern sets in this.set needs to match + // in order for it to be valid. If negating, then just one + // match means that we have failed. + // Either way, return on the first hit. -var NODE_ENV = "none"; + var set = this.set + this.debug(this.pattern, 'set', set) -var invariant = function(condition, format, a, b, c, d, e, f) { - if (NODE_ENV !== 'production') { - if (format === undefined) { - throw new Error('invariant requires an error message argument'); - } + // Find the basename of the path by looking for the last non-empty segment + var filename + var i + for (i = f.length - 1; i >= 0; i--) { + filename = f[i] + if (filename) break } - if (!condition) { - var error; - if (format === undefined) { - error = new Error( - 'Minified exception occurred; use the non-minified dev environment ' + - 'for the full error message and additional helpful warnings.' - ); - } else { - var args = [a, b, c, d, e, f]; - var argIndex = 0; - error = new Error( - format.replace(/%s/g, function() { return args[argIndex++]; }) - ); - error.name = 'Invariant Violation'; + for (i = 0; i < set.length; i++) { + var pattern = set[i] + var file = f + if (options.matchBase && pattern.length === 1) { + file = [filename] + } + var hit = this.matchOne(file, pattern, partial) + if (hit) { + if (options.flipNegate) return true + return !this.negate } - - error.framesToPop = 1; // we don't care about invariant's own frame - throw error; } -}; -module.exports = invariant; + // didn't get any hits. this is success if it's a negative + // pattern, failure otherwise. + if (options.flipNegate) return false + return this.negate +} +// set partial to true to test if, for example, +// "/a/b" matches the start of "/*/b/*/d" +// Partial means, if you run out of file before you run +// out of pattern, then that's fine, as long as all +// the parts match. +Minimatch.prototype.matchOne = function (file, pattern, partial) { + var options = this.options -/***/ }), -/* 8 */, -/* 9 */ -/***/ (function(module, exports) { + this.debug('matchOne', + { 'this': this, file: file, pattern: pattern }) -module.exports = __webpack_require__(282); + this.debug('matchOne', file.length, pattern.length) -/***/ }), -/* 10 */, -/* 11 */ -/***/ (function(module, exports) { + for (var fi = 0, + pi = 0, + fl = file.length, + pl = pattern.length + ; (fi < fl) && (pi < pl) + ; fi++, pi++) { + this.debug('matchOne loop') + var p = pattern[pi] + var f = file[fi] -// https://github.com/zloirock/core-js/issues/86#issuecomment-115759028 -var global = module.exports = typeof window != 'undefined' && window.Math == Math - ? window : typeof self != 'undefined' && self.Math == Math ? self - // eslint-disable-next-line no-new-func - : Function('return this')(); -if (typeof __g == 'number') __g = global; // eslint-disable-line no-undef + this.debug(pattern, p, f) + // should be impossible. + // some invalid regexp stuff in the set. + if (p === false) return false -/***/ }), -/* 12 */ -/***/ (function(module, exports, __webpack_require__) { + if (p === GLOBSTAR) { + this.debug('GLOBSTAR', [pattern, p, f]) -"use strict"; + // "**" + // a/**/b/**/c would match the following: + // a/b/x/y/z/c + // a/x/y/z/b/c + // a/b/x/b/x/c + // a/b/c + // To do this, take the rest of the pattern after + // the **, and see if it would match the file remainder. + // If so, return success. + // If not, the ** "swallows" a segment, and try again. + // This is recursively awful. + // + // a/**/b/**/c matching a/b/x/y/z/c + // - a matches a + // - doublestar + // - matchOne(b/x/y/z/c, b/**/c) + // - b matches b + // - doublestar + // - matchOne(x/y/z/c, c) -> no + // - matchOne(y/z/c, c) -> no + // - matchOne(z/c, c) -> no + // - matchOne(c, c) yes, hit + var fr = fi + var pr = pi + 1 + if (pr === pl) { + this.debug('** at the end') + // a ** at the end will just swallow the rest. + // We have found a match. + // however, it will not swallow /.x, unless + // options.dot is set. + // . and .. are *never* matched by **, for explosively + // exponential reasons. + for (; fi < fl; fi++) { + if (file[fi] === '.' || file[fi] === '..' || + (!options.dot && file[fi].charAt(0) === '.')) return false + } + return true + } + // ok, let's see if we can swallow whatever we can. + while (fr < fl) { + var swallowee = file[fr] -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.sortAlpha = sortAlpha; -exports.entries = entries; -exports.removePrefix = removePrefix; -exports.removeSuffix = removeSuffix; -exports.addSuffix = addSuffix; -exports.hyphenate = hyphenate; -exports.camelCase = camelCase; -exports.compareSortedArrays = compareSortedArrays; -exports.sleep = sleep; -const _camelCase = __webpack_require__(176); + this.debug('\nglobstar while', file, fr, pattern, pr, swallowee) -function sortAlpha(a, b) { - // sort alphabetically in a deterministic way - const shortLen = Math.min(a.length, b.length); - for (let i = 0; i < shortLen; i++) { - const aChar = a.charCodeAt(i); - const bChar = b.charCodeAt(i); - if (aChar !== bChar) { - return aChar - bChar; + // XXX remove this slice. Just pass the start index. + if (this.matchOne(file.slice(fr), pattern.slice(pr), partial)) { + this.debug('globstar found match!', fr, fl, swallowee) + // found a match. + return true + } else { + // can't swallow "." or ".." ever. + // can only swallow ".foo" when explicitly asked. + if (swallowee === '.' || swallowee === '..' || + (!options.dot && swallowee.charAt(0) === '.')) { + this.debug('dot detected!', file, fr, pattern, pr) + break + } + + // ** swallows a segment, and continue. + this.debug('globstar swallow a segment, and continue') + fr++ + } + } + + // no match was found. + // However, in partial mode, we can't say this is necessarily over. + // If there's more *pattern* left, then + if (partial) { + // ran out of file + this.debug('\n>>> no match, partial?', file, fr, pattern, pr) + if (fr === fl) return true + } + return false } - } - return a.length - b.length; -} -function entries(obj) { - const entries = []; - if (obj) { - for (const key in obj) { - entries.push([key, obj[key]]); + // something other than ** + // non-magic patterns just have to match exactly + // patterns with magic have been turned into regexps. + var hit + if (typeof p === 'string') { + if (options.nocase) { + hit = f.toLowerCase() === p.toLowerCase() + } else { + hit = f === p + } + this.debug('string match', p, f, hit) + } else { + hit = f.match(p) + this.debug('pattern match', p, f, hit) } - } - return entries; -} -function removePrefix(pattern, prefix) { - if (pattern.startsWith(prefix)) { - pattern = pattern.slice(prefix.length); + if (!hit) return false } - return pattern; -} + // Note: ending in / means that we'll get a final "" + // at the end of the pattern. This can only match a + // corresponding "" at the end of the file. + // If the file ends in /, then it can only match a + // a pattern that ends in /, unless the pattern just + // doesn't have any more for it. But, a/b/ should *not* + // match "a/b/*", even though "" matches against the + // [^/]*? pattern, except in partial mode, where it might + // simply not be reached yet. + // However, a/b/ should still satisfy a/* -function removeSuffix(pattern, suffix) { - if (pattern.endsWith(suffix)) { - return pattern.slice(0, -suffix.length); + // now either we fell off the end of the pattern, or we're done. + if (fi === fl && pi === pl) { + // ran out of pattern and filename at the same time. + // an exact hit! + return true + } else if (fi === fl) { + // ran out of file, but still had pattern left. + // this is ok if we're doing the match as part of + // a glob fs traversal. + return partial + } else if (pi === pl) { + // ran out of pattern, still have file left. + // this is only acceptable if we're on the very last + // empty segment of a file with a trailing slash. + // a/* should match a/b/ + var emptyFileEnd = (fi === fl - 1) && (file[fi] === '') + return emptyFileEnd } - return pattern; + // should be unreachable. + throw new Error('wtf?') } -function addSuffix(pattern, suffix) { - if (!pattern.endsWith(suffix)) { - return pattern + suffix; - } - - return pattern; +// replace stuff like \* with * +function globUnescape (s) { + return s.replace(/\\(.)/g, '$1') } -function hyphenate(str) { - return str.replace(/[A-Z]/g, match => { - return '-' + match.charAt(0).toLowerCase(); - }); +function regExpEscape (s) { + return s.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&') } -function camelCase(str) { - if (/[A-Z]/.test(str)) { - return null; - } else { - return _camelCase(str); + +/***/ }), +/* 61 */ +/***/ (function(module, exports, __webpack_require__) { + +var wrappy = __webpack_require__(123) +module.exports = wrappy(once) +module.exports.strict = wrappy(onceStrict) + +once.proto = once(function () { + Object.defineProperty(Function.prototype, 'once', { + value: function () { + return once(this) + }, + configurable: true + }) + + Object.defineProperty(Function.prototype, 'onceStrict', { + value: function () { + return onceStrict(this) + }, + configurable: true + }) +}) + +function once (fn) { + var f = function () { + if (f.called) return f.value + f.called = true + return f.value = fn.apply(this, arguments) } + f.called = false + return f } -function compareSortedArrays(array1, array2) { - if (array1.length !== array2.length) { - return false; - } - for (let i = 0, len = array1.length; i < len; i++) { - if (array1[i] !== array2[i]) { - return false; - } +function onceStrict (fn) { + var f = function () { + if (f.called) + throw new Error(f.onceError) + f.called = true + return f.value = fn.apply(this, arguments) } - return true; + var name = fn.name || 'Function wrapped with `once`' + f.onceError = name + " shouldn't be called more than once" + f.called = false + return f } -function sleep(ms) { - return new Promise(resolve => { - setTimeout(resolve, ms); - }); -} /***/ }), -/* 13 */ -/***/ (function(module, exports, __webpack_require__) { +/* 62 */, +/* 63 */ +/***/ (function(module, exports) { -var store = __webpack_require__(107)('wks'); -var uid = __webpack_require__(111); -var Symbol = __webpack_require__(11).Symbol; -var USE_SYMBOL = typeof Symbol == 'function'; +module.exports = __webpack_require__(277); -var $exports = module.exports = function (name) { - return store[name] || (store[name] = - USE_SYMBOL && Symbol[name] || (USE_SYMBOL ? Symbol : uid)('Symbol.' + name)); -}; +/***/ }), +/* 64 */, +/* 65 */, +/* 66 */, +/* 67 */ +/***/ (function(module, exports) { -$exports.store = store; +// 7.2.1 RequireObjectCoercible(argument) +module.exports = function (it) { + if (it == undefined) throw TypeError("Can't call method on " + it); + return it; +}; /***/ }), -/* 14 */ +/* 68 */ /***/ (function(module, exports, __webpack_require__) { -"use strict"; +var isObject = __webpack_require__(34); +var document = __webpack_require__(11).document; +// typeof document.createElement is 'object' in old IE +var is = isObject(document) && isObject(document.createElement); +module.exports = function (it) { + return is ? document.createElement(it) : {}; +}; -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.stringify = exports.parse = undefined; +/***/ }), +/* 69 */ +/***/ (function(module, exports) { -var _asyncToGenerator2; +module.exports = true; -function _load_asyncToGenerator() { - return _asyncToGenerator2 = _interopRequireDefault(__webpack_require__(1)); -} -var _parse; +/***/ }), +/* 70 */ +/***/ (function(module, exports, __webpack_require__) { -function _load_parse() { - return _parse = __webpack_require__(81); +"use strict"; + +// 25.4.1.5 NewPromiseCapability(C) +var aFunction = __webpack_require__(46); + +function PromiseCapability(C) { + var resolve, reject; + this.promise = new C(function ($$resolve, $$reject) { + if (resolve !== undefined || reject !== undefined) throw TypeError('Bad Promise constructor'); + resolve = $$resolve; + reject = $$reject; + }); + this.resolve = aFunction(resolve); + this.reject = aFunction(reject); } -Object.defineProperty(exports, 'parse', { - enumerable: true, - get: function get() { - return _interopRequireDefault(_parse || _load_parse()).default; - } -}); +module.exports.f = function (C) { + return new PromiseCapability(C); +}; -var _stringify; -function _load_stringify() { - return _stringify = __webpack_require__(150); -} +/***/ }), +/* 71 */ +/***/ (function(module, exports, __webpack_require__) { -Object.defineProperty(exports, 'stringify', { - enumerable: true, - get: function get() { - return _interopRequireDefault(_stringify || _load_stringify()).default; - } -}); -exports.implodeEntry = implodeEntry; -exports.explodeEntry = explodeEntry; +var def = __webpack_require__(50).f; +var has = __webpack_require__(49); +var TAG = __webpack_require__(13)('toStringTag'); -var _misc; +module.exports = function (it, tag, stat) { + if (it && !has(it = stat ? it : it.prototype, TAG)) def(it, TAG, { configurable: true, value: tag }); +}; -function _load_misc() { - return _misc = __webpack_require__(12); -} -var _normalizePattern; +/***/ }), +/* 72 */ +/***/ (function(module, exports, __webpack_require__) { -function _load_normalizePattern() { - return _normalizePattern = __webpack_require__(29); -} +var shared = __webpack_require__(107)('keys'); +var uid = __webpack_require__(111); +module.exports = function (key) { + return shared[key] || (shared[key] = uid(key)); +}; -var _parse2; -function _load_parse2() { - return _parse2 = _interopRequireDefault(__webpack_require__(81)); -} +/***/ }), +/* 73 */ +/***/ (function(module, exports) { -var _constants; +// 7.1.4 ToInteger +var ceil = Math.ceil; +var floor = Math.floor; +module.exports = function (it) { + return isNaN(it = +it) ? 0 : (it > 0 ? floor : ceil)(it); +}; -function _load_constants() { - return _constants = __webpack_require__(6); -} -var _fs; +/***/ }), +/* 74 */ +/***/ (function(module, exports, __webpack_require__) { -function _load_fs() { - return _fs = _interopRequireWildcard(__webpack_require__(5)); -} +// to indexed object, toObject with fallback for non-array-like ES3 strings +var IObject = __webpack_require__(131); +var defined = __webpack_require__(67); +module.exports = function (it) { + return IObject(defined(it)); +}; -function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } +/***/ }), +/* 75 */ +/***/ (function(module, exports, __webpack_require__) { -const invariant = __webpack_require__(7); +// Approach: +// +// 1. Get the minimatch set +// 2. For each pattern in the set, PROCESS(pattern, false) +// 3. Store matches per-set, then uniq them +// +// PROCESS(pattern, inGlobStar) +// Get the first [n] items from pattern that are all strings +// Join these together. This is PREFIX. +// If there is no more remaining, then stat(PREFIX) and +// add to matches if it succeeds. END. +// +// If inGlobStar and PREFIX is symlink and points to dir +// set ENTRIES = [] +// else readdir(PREFIX) as ENTRIES +// If fail, END +// +// with ENTRIES +// If pattern[n] is GLOBSTAR +// // handle the case where the globstar match is empty +// // by pruning it out, and testing the resulting pattern +// PROCESS(pattern[0..n] + pattern[n+1 .. $], false) +// // handle other cases. +// for ENTRY in ENTRIES (not dotfiles) +// // attach globstar + tail onto the entry +// // Mark that this entry is a globstar match +// PROCESS(pattern[0..n] + ENTRY + pattern[n .. $], true) +// +// else // not globstar +// for ENTRY in ENTRIES (not dotfiles, unless pattern[n] is dot) +// Test ENTRY against pattern[n] +// If fails, continue +// If passes, PROCESS(pattern[0..n] + item + pattern[n+1 .. $]) +// +// Caveat: +// Cache all stats and readdirs results to minimize syscall. Since all +// we ever care about is existence and directory-ness, we can just keep +// `true` for files, and [children,...] for directories, or `false` for +// things that don't exist. -const path = __webpack_require__(0); -const ssri = __webpack_require__(55); +module.exports = glob -function getName(pattern) { - return (0, (_normalizePattern || _load_normalizePattern()).normalizePattern)(pattern).name; -} +var fs = __webpack_require__(3) +var rp = __webpack_require__(114) +var minimatch = __webpack_require__(60) +var Minimatch = minimatch.Minimatch +var inherits = __webpack_require__(42) +var EE = __webpack_require__(54).EventEmitter +var path = __webpack_require__(0) +var assert = __webpack_require__(22) +var isAbsolute = __webpack_require__(76) +var globSync = __webpack_require__(218) +var common = __webpack_require__(115) +var alphasort = common.alphasort +var alphasorti = common.alphasorti +var setopts = common.setopts +var ownProp = common.ownProp +var inflight = __webpack_require__(223) +var util = __webpack_require__(2) +var childrenIgnored = common.childrenIgnored +var isIgnored = common.isIgnored -function blankObjectUndefined(obj) { - return obj && Object.keys(obj).length ? obj : undefined; -} +var once = __webpack_require__(61) -function keyForRemote(remote) { - return remote.resolved || (remote.reference && remote.hash ? `${remote.reference}#${remote.hash}` : null); -} +function glob (pattern, options, cb) { + if (typeof options === 'function') cb = options, options = {} + if (!options) options = {} -function serializeIntegrity(integrity) { - // We need this because `Integrity.toString()` does not use sorting to ensure a stable string output - // See https://git.io/vx2Hy - return integrity.toString().split(' ').sort().join(' '); + if (options.sync) { + if (cb) + throw new TypeError('callback provided to sync glob') + return globSync(pattern, options) + } + + return new Glob(pattern, options, cb) } -function implodeEntry(pattern, obj) { - const inferredName = getName(pattern); - const integrity = obj.integrity ? serializeIntegrity(obj.integrity) : ''; - const imploded = { - name: inferredName === obj.name ? undefined : obj.name, - version: obj.version, - uid: obj.uid === obj.version ? undefined : obj.uid, - resolved: obj.resolved, - registry: obj.registry === 'npm' ? undefined : obj.registry, - dependencies: blankObjectUndefined(obj.dependencies), - optionalDependencies: blankObjectUndefined(obj.optionalDependencies), - permissions: blankObjectUndefined(obj.permissions), - prebuiltVariants: blankObjectUndefined(obj.prebuiltVariants) - }; - if (integrity) { - imploded.integrity = integrity; +glob.sync = globSync +var GlobSync = glob.GlobSync = globSync.GlobSync + +// old api surface +glob.glob = glob + +function extend (origin, add) { + if (add === null || typeof add !== 'object') { + return origin } - return imploded; -} -function explodeEntry(pattern, obj) { - obj.optionalDependencies = obj.optionalDependencies || {}; - obj.dependencies = obj.dependencies || {}; - obj.uid = obj.uid || obj.version; - obj.permissions = obj.permissions || {}; - obj.registry = obj.registry || 'npm'; - obj.name = obj.name || getName(pattern); - const integrity = obj.integrity; - if (integrity && integrity.isIntegrity) { - obj.integrity = ssri.parse(integrity); + var keys = Object.keys(add) + var i = keys.length + while (i--) { + origin[keys[i]] = add[keys[i]] } - return obj; + return origin } -class Lockfile { - constructor({ cache, source, parseResultType } = {}) { - this.source = source || ''; - this.cache = cache; - this.parseResultType = parseResultType; - } +glob.hasMagic = function (pattern, options_) { + var options = extend({}, options_) + options.noprocess = true - // source string if the `cache` was parsed + var g = new Glob(pattern, options) + var set = g.minimatch.set + if (!pattern) + return false - // if true, we're parsing an old yarn file and need to update integrity fields - hasEntriesExistWithoutIntegrity() { - if (!this.cache) { - return false; - } + if (set.length > 1) + return true - for (const key in this.cache) { - // $FlowFixMe - `this.cache` is clearly defined at this point - if (!/^.*@(file:|http)/.test(key) && this.cache[key] && !this.cache[key].integrity) { - return true; - } - } + for (var j = 0; j < set[0].length; j++) { + if (typeof set[0][j] !== 'string') + return true + } - return false; + return false +} + +glob.Glob = Glob +inherits(Glob, EE) +function Glob (pattern, options, cb) { + if (typeof options === 'function') { + cb = options + options = null } - static fromDirectory(dir, reporter) { - return (0, (_asyncToGenerator2 || _load_asyncToGenerator()).default)(function* () { - // read the manifest in this directory - const lockfileLoc = path.join(dir, (_constants || _load_constants()).LOCKFILE_FILENAME); + if (options && options.sync) { + if (cb) + throw new TypeError('callback provided to sync glob') + return new GlobSync(pattern, options) + } - let lockfile; - let rawLockfile = ''; - let parseResult; + if (!(this instanceof Glob)) + return new Glob(pattern, options, cb) - if (yield (_fs || _load_fs()).exists(lockfileLoc)) { - rawLockfile = yield (_fs || _load_fs()).readFile(lockfileLoc); - parseResult = (0, (_parse2 || _load_parse2()).default)(rawLockfile, lockfileLoc); + setopts(this, pattern, options) + this._didRealPath = false - if (reporter) { - if (parseResult.type === 'merge') { - reporter.info(reporter.lang('lockfileMerged')); - } else if (parseResult.type === 'conflict') { - reporter.warn(reporter.lang('lockfileConflict')); - } - } + // process each pattern in the minimatch set + var n = this.minimatch.set.length - lockfile = parseResult.object; - } else if (reporter) { - reporter.info(reporter.lang('noLockfileFound')); - } + // The matches are stored as {: true,...} so that + // duplicates are automagically pruned. + // Later, we do an Object.keys() on these. + // Keep them as a list so we can fill in when nonull is set. + this.matches = new Array(n) - return new Lockfile({ cache: lockfile, source: rawLockfile, parseResultType: parseResult && parseResult.type }); - })(); + if (typeof cb === 'function') { + cb = once(cb) + this.on('error', cb) + this.on('end', function (matches) { + cb(null, matches) + }) } - getLocked(pattern) { - const cache = this.cache; - if (!cache) { - return undefined; - } + var self = this + this._processing = 0 - const shrunk = pattern in cache && cache[pattern]; + this._emitQueue = [] + this._processQueue = [] + this.paused = false - if (typeof shrunk === 'string') { - return this.getLocked(shrunk); - } else if (shrunk) { - explodeEntry(pattern, shrunk); - return shrunk; - } + if (this.noprocess) + return this - return undefined; - } + if (n === 0) + return done() - removePattern(pattern) { - const cache = this.cache; - if (!cache) { - return; - } - delete cache[pattern]; + var sync = true + for (var i = 0; i < n; i ++) { + this._process(this.minimatch.set[i], i, false, done) } + sync = false - getLockfile(patterns) { - const lockfile = {}; - const seen = new Map(); - - // order by name so that lockfile manifest is assigned to the first dependency with this manifest - // the others that have the same remoteKey will just refer to the first - // ordering allows for consistency in lockfile when it is serialized - const sortedPatternsKeys = Object.keys(patterns).sort((_misc || _load_misc()).sortAlpha); - - for (var _iterator = sortedPatternsKeys, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : _iterator[Symbol.iterator]();;) { - var _ref; - - if (_isArray) { - if (_i >= _iterator.length) break; - _ref = _iterator[_i++]; + function done () { + --self._processing + if (self._processing <= 0) { + if (sync) { + process.nextTick(function () { + self._finish() + }) } else { - _i = _iterator.next(); - if (_i.done) break; - _ref = _i.value; + self._finish() } + } + } +} - const pattern = _ref; +Glob.prototype._finish = function () { + assert(this instanceof Glob) + if (this.aborted) + return - const pkg = patterns[pattern]; - const remote = pkg._remote, - ref = pkg._reference; + if (this.realpath && !this._didRealpath) + return this._realpath() - invariant(ref, 'Package is missing a reference'); - invariant(remote, 'Package is missing a remote'); + common.finish(this) + this.emit('end', this.found) +} - const remoteKey = keyForRemote(remote); - const seenPattern = remoteKey && seen.get(remoteKey); - if (seenPattern) { - // no point in duplicating it - lockfile[pattern] = seenPattern; +Glob.prototype._realpath = function () { + if (this._didRealpath) + return - // if we're relying on our name being inferred and two of the patterns have - // different inferred names then we need to set it - if (!seenPattern.name && getName(pattern) !== pkg.name) { - seenPattern.name = pkg.name; - } - continue; - } - const obj = implodeEntry(pattern, { - name: pkg.name, - version: pkg.version, - uid: pkg._uid, - resolved: remote.resolved, - integrity: remote.integrity, - registry: remote.registry, - dependencies: pkg.dependencies, - peerDependencies: pkg.peerDependencies, - optionalDependencies: pkg.optionalDependencies, - permissions: ref.permissions, - prebuiltVariants: pkg.prebuiltVariants - }); + this._didRealpath = true - lockfile[pattern] = obj; + var n = this.matches.length + if (n === 0) + return this._finish() - if (remoteKey) { - seen.set(remoteKey, obj); - } - } + var self = this + for (var i = 0; i < this.matches.length; i++) + this._realpathSet(i, next) - return lockfile; + function next () { + if (--n === 0) + self._finish() } } -exports.default = Lockfile; -/***/ }), -/* 15 */, -/* 16 */, -/* 17 */ -/***/ (function(module, exports) { +Glob.prototype._realpathSet = function (index, cb) { + var matchset = this.matches[index] + if (!matchset) + return cb() -module.exports = __webpack_require__(137); + var found = Object.keys(matchset) + var self = this + var n = found.length -/***/ }), -/* 18 */, -/* 19 */, -/* 20 */ -/***/ (function(module, exports, __webpack_require__) { + if (n === 0) + return cb() -"use strict"; + var set = this.matches[index] = Object.create(null) + found.forEach(function (p, i) { + // If there's a problem with the stat, then it means that + // one or more of the links in the realpath couldn't be + // resolved. just return the abs value in that case. + p = self._makeAbs(p) + rp.realpath(p, self.realpathCache, function (er, real) { + if (!er) + set[real] = true + else if (er.syscall === 'stat') + set[p] = true + else + self.emit('error', er) // srsly wtf right here + + if (--n === 0) { + self.matches[index] = set + cb() + } + }) + }) +} +Glob.prototype._mark = function (p) { + return common.mark(this, p) +} -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.default = nullify; -function nullify(obj = {}) { - if (Array.isArray(obj)) { - for (var _iterator = obj, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : _iterator[Symbol.iterator]();;) { - var _ref; +Glob.prototype._makeAbs = function (f) { + return common.makeAbs(this, f) +} - if (_isArray) { - if (_i >= _iterator.length) break; - _ref = _iterator[_i++]; - } else { - _i = _iterator.next(); - if (_i.done) break; - _ref = _i.value; - } +Glob.prototype.abort = function () { + this.aborted = true + this.emit('abort') +} - const item = _ref; +Glob.prototype.pause = function () { + if (!this.paused) { + this.paused = true + this.emit('pause') + } +} - nullify(item); +Glob.prototype.resume = function () { + if (this.paused) { + this.emit('resume') + this.paused = false + if (this._emitQueue.length) { + var eq = this._emitQueue.slice(0) + this._emitQueue.length = 0 + for (var i = 0; i < eq.length; i ++) { + var e = eq[i] + this._emitMatch(e[0], e[1]) + } } - } else if (obj !== null && typeof obj === 'object' || typeof obj === 'function') { - Object.setPrototypeOf(obj, null); - - // for..in can only be applied to 'object', not 'function' - if (typeof obj === 'object') { - for (const key in obj) { - nullify(obj[key]); + if (this._processQueue.length) { + var pq = this._processQueue.slice(0) + this._processQueue.length = 0 + for (var i = 0; i < pq.length; i ++) { + var p = pq[i] + this._processing-- + this._process(p[0], p[1], p[2], p[3]) } } } - - return obj; } -/***/ }), -/* 21 */, -/* 22 */ -/***/ (function(module, exports) { +Glob.prototype._process = function (pattern, index, inGlobStar, cb) { + assert(this instanceof Glob) + assert(typeof cb === 'function') -module.exports = __webpack_require__(139); + if (this.aborted) + return -/***/ }), -/* 23 */ -/***/ (function(module, exports) { + this._processing++ + if (this.paused) { + this._processQueue.push([pattern, index, inGlobStar, cb]) + return + } -var core = module.exports = { version: '2.5.7' }; -if (typeof __e == 'number') __e = core; // eslint-disable-line no-undef + //console.error('PROCESS %d', this._processing, pattern) + // Get the first [n] parts of pattern that are all strings. + var n = 0 + while (typeof pattern[n] === 'string') { + n ++ + } + // now n is the index of the first one that is *not* a string. -/***/ }), -/* 24 */, -/* 25 */, -/* 26 */, -/* 27 */ -/***/ (function(module, exports, __webpack_require__) { + // see if there's anything else + var prefix + switch (n) { + // if not, then this is rather simple + case pattern.length: + this._processSimple(pattern.join('/'), index, cb) + return -var isObject = __webpack_require__(34); -module.exports = function (it) { - if (!isObject(it)) throw TypeError(it + ' is not an object!'); - return it; -}; + case 0: + // pattern *starts* with some non-trivial item. + // going to readdir(cwd), but not include the prefix in matches. + prefix = null + break + default: + // pattern has some string bits in the front. + // whatever it starts with, whether that's 'absolute' like /foo/bar, + // or 'relative' like '../baz' + prefix = pattern.slice(0, n).join('/') + break + } -/***/ }), -/* 28 */, -/* 29 */ -/***/ (function(module, exports, __webpack_require__) { + var remain = pattern.slice(n) -"use strict"; + // get the list of entries. + var read + if (prefix === null) + read = '.' + else if (isAbsolute(prefix) || isAbsolute(pattern.join('/'))) { + if (!prefix || !isAbsolute(prefix)) + prefix = '/' + prefix + read = prefix + } else + read = prefix + var abs = this._makeAbs(read) -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.normalizePattern = normalizePattern; + //if ignored, skip _processing + if (childrenIgnored(this, read)) + return cb() -/** - * Explode and normalize a pattern into its name and range. - */ + var isGlobStar = remain[0] === minimatch.GLOBSTAR + if (isGlobStar) + this._processGlobStar(prefix, read, abs, remain, index, inGlobStar, cb) + else + this._processReaddir(prefix, read, abs, remain, index, inGlobStar, cb) +} -function normalizePattern(pattern) { - let hasVersion = false; - let range = 'latest'; - let name = pattern; +Glob.prototype._processReaddir = function (prefix, read, abs, remain, index, inGlobStar, cb) { + var self = this + this._readdir(abs, inGlobStar, function (er, entries) { + return self._processReaddir2(prefix, read, abs, remain, index, inGlobStar, entries, cb) + }) +} - // if we're a scope then remove the @ and add it back later - let isScoped = false; - if (name[0] === '@') { - isScoped = true; - name = name.slice(1); - } +Glob.prototype._processReaddir2 = function (prefix, read, abs, remain, index, inGlobStar, entries, cb) { - // take first part as the name - const parts = name.split('@'); - if (parts.length > 1) { - name = parts.shift(); - range = parts.join('@'); + // if the abs isn't a dir, then nothing can match! + if (!entries) + return cb() - if (range) { - hasVersion = true; - } else { - range = '*'; + // It will only match dot entries if it starts with a dot, or if + // dot is set. Stuff like @(.foo|.bar) isn't allowed. + var pn = remain[0] + var negate = !!this.minimatch.negate + var rawGlob = pn._glob + var dotOk = this.dot || rawGlob.charAt(0) === '.' + + var matchedEntries = [] + for (var i = 0; i < entries.length; i++) { + var e = entries[i] + if (e.charAt(0) !== '.' || dotOk) { + var m + if (negate && !prefix) { + m = !e.match(pn) + } else { + m = e.match(pn) + } + if (m) + matchedEntries.push(e) } } - // add back @ scope suffix - if (isScoped) { - name = `@${name}`; + //console.error('prd2', prefix, entries, remain[0]._glob, matchedEntries) + + var len = matchedEntries.length + // If there are no matched entries, then nothing matches. + if (len === 0) + return cb() + + // if this is the last remaining pattern bit, then no need for + // an additional stat *unless* the user has specified mark or + // stat explicitly. We know they exist, since readdir returned + // them. + + if (remain.length === 1 && !this.mark && !this.stat) { + if (!this.matches[index]) + this.matches[index] = Object.create(null) + + for (var i = 0; i < len; i ++) { + var e = matchedEntries[i] + if (prefix) { + if (prefix !== '/') + e = prefix + '/' + e + else + e = prefix + e + } + + if (e.charAt(0) === '/' && !this.nomount) { + e = path.join(this.root, e) + } + this._emitMatch(index, e) + } + // This was the last one, and no stats were needed + return cb() } - return { name, range, hasVersion }; + // now test all matched entries as stand-ins for that part + // of the pattern. + remain.shift() + for (var i = 0; i < len; i ++) { + var e = matchedEntries[i] + var newPattern + if (prefix) { + if (prefix !== '/') + e = prefix + '/' + e + else + e = prefix + e + } + this._process([e].concat(remain), index, inGlobStar, cb) + } + cb() } -/***/ }), -/* 30 */, -/* 31 */ -/***/ (function(module, exports, __webpack_require__) { +Glob.prototype._emitMatch = function (index, e) { + if (this.aborted) + return -var dP = __webpack_require__(50); -var createDesc = __webpack_require__(106); -module.exports = __webpack_require__(33) ? function (object, key, value) { - return dP.f(object, key, createDesc(1, value)); -} : function (object, key, value) { - object[key] = value; - return object; -}; + if (isIgnored(this, e)) + return + + if (this.paused) { + this._emitQueue.push([index, e]) + return + } + var abs = isAbsolute(e) ? e : this._makeAbs(e) -/***/ }), -/* 32 */ -/***/ (function(module, exports, __webpack_require__) { + if (this.mark) + e = this._mark(e) -/* eslint-disable node/no-deprecated-api */ -var buffer = __webpack_require__(63) -var Buffer = buffer.Buffer + if (this.absolute) + e = abs -// alternative to using Object.keys for old browsers -function copyProps (src, dst) { - for (var key in src) { - dst[key] = src[key] + if (this.matches[index][e]) + return + + if (this.nodir) { + var c = this.cache[abs] + if (c === 'DIR' || Array.isArray(c)) + return } -} -if (Buffer.from && Buffer.alloc && Buffer.allocUnsafe && Buffer.allocUnsafeSlow) { - module.exports = buffer -} else { - // Copy properties from require('buffer') - copyProps(buffer, exports) - exports.Buffer = SafeBuffer -} -function SafeBuffer (arg, encodingOrOffset, length) { - return Buffer(arg, encodingOrOffset, length) -} + this.matches[index][e] = true -// Copy static methods from Buffer -copyProps(Buffer, SafeBuffer) + var st = this.statCache[abs] + if (st) + this.emit('stat', e, st) -SafeBuffer.from = function (arg, encodingOrOffset, length) { - if (typeof arg === 'number') { - throw new TypeError('Argument must not be a number') - } - return Buffer(arg, encodingOrOffset, length) + this.emit('match', e) } -SafeBuffer.alloc = function (size, fill, encoding) { - if (typeof size !== 'number') { - throw new TypeError('Argument must be a number') +Glob.prototype._readdirInGlobStar = function (abs, cb) { + if (this.aborted) + return + + // follow all symlinked directories forever + // just proceed as if this is a non-globstar situation + if (this.follow) + return this._readdir(abs, false, cb) + + var lstatkey = 'lstat\0' + abs + var self = this + var lstatcb = inflight(lstatkey, lstatcb_) + + if (lstatcb) + fs.lstat(abs, lstatcb) + + function lstatcb_ (er, lstat) { + if (er && er.code === 'ENOENT') + return cb() + + var isSym = lstat && lstat.isSymbolicLink() + self.symlinks[abs] = isSym + + // If it's not a symlink or a dir, then it's definitely a regular file. + // don't bother doing a readdir in that case. + if (!isSym && lstat && !lstat.isDirectory()) { + self.cache[abs] = 'FILE' + cb() + } else + self._readdir(abs, false, cb) } - var buf = Buffer(size) - if (fill !== undefined) { - if (typeof encoding === 'string') { - buf.fill(fill, encoding) - } else { - buf.fill(fill) - } - } else { - buf.fill(0) +} + +Glob.prototype._readdir = function (abs, inGlobStar, cb) { + if (this.aborted) + return + + cb = inflight('readdir\0'+abs+'\0'+inGlobStar, cb) + if (!cb) + return + + //console.error('RD %j %j', +inGlobStar, abs) + if (inGlobStar && !ownProp(this.symlinks, abs)) + return this._readdirInGlobStar(abs, cb) + + if (ownProp(this.cache, abs)) { + var c = this.cache[abs] + if (!c || c === 'FILE') + return cb() + + if (Array.isArray(c)) + return cb(null, c) } - return buf + + var self = this + fs.readdir(abs, readdirCb(this, abs, cb)) } -SafeBuffer.allocUnsafe = function (size) { - if (typeof size !== 'number') { - throw new TypeError('Argument must be a number') +function readdirCb (self, abs, cb) { + return function (er, entries) { + if (er) + self._readdirError(abs, er, cb) + else + self._readdirEntries(abs, entries, cb) } - return Buffer(size) } -SafeBuffer.allocUnsafeSlow = function (size) { - if (typeof size !== 'number') { - throw new TypeError('Argument must be a number') +Glob.prototype._readdirEntries = function (abs, entries, cb) { + if (this.aborted) + return + + // if we haven't asked to stat everything, then just + // assume that everything in there exists, so we can avoid + // having to stat it a second time. + if (!this.mark && !this.stat) { + for (var i = 0; i < entries.length; i ++) { + var e = entries[i] + if (abs === '/') + e = abs + e + else + e = abs + '/' + e + this.cache[e] = true + } } - return buffer.SlowBuffer(size) + + this.cache[abs] = entries + return cb(null, entries) } +Glob.prototype._readdirError = function (f, er, cb) { + if (this.aborted) + return -/***/ }), -/* 33 */ -/***/ (function(module, exports, __webpack_require__) { + // handle errors, and cache the information + switch (er.code) { + case 'ENOTSUP': // https://github.com/isaacs/node-glob/issues/205 + case 'ENOTDIR': // totally normal. means it *does* exist. + var abs = this._makeAbs(f) + this.cache[abs] = 'FILE' + if (abs === this.cwdAbs) { + var error = new Error(er.code + ' invalid cwd ' + this.cwd) + error.path = this.cwd + error.code = er.code + this.emit('error', error) + this.abort() + } + break -// Thank's IE8 for his funny defineProperty -module.exports = !__webpack_require__(85)(function () { - return Object.defineProperty({}, 'a', { get: function () { return 7; } }).a != 7; -}); + case 'ENOENT': // not terribly unusual + case 'ELOOP': + case 'ENAMETOOLONG': + case 'UNKNOWN': + this.cache[this._makeAbs(f)] = false + break + default: // some unusual error. Treat as failure. + this.cache[this._makeAbs(f)] = false + if (this.strict) { + this.emit('error', er) + // If the error is handled, then we abort + // if not, we threw out of here + this.abort() + } + if (!this.silent) + console.error('glob error', er) + break + } -/***/ }), -/* 34 */ -/***/ (function(module, exports) { + return cb() +} -module.exports = function (it) { - return typeof it === 'object' ? it !== null : typeof it === 'function'; -}; +Glob.prototype._processGlobStar = function (prefix, read, abs, remain, index, inGlobStar, cb) { + var self = this + this._readdir(abs, inGlobStar, function (er, entries) { + self._processGlobStar2(prefix, read, abs, remain, index, inGlobStar, entries, cb) + }) +} -/***/ }), -/* 35 */ -/***/ (function(module, exports) { +Glob.prototype._processGlobStar2 = function (prefix, read, abs, remain, index, inGlobStar, entries, cb) { + //console.error('pgs2', prefix, remain[0], entries) -module.exports = {}; + // no entries means not a dir, so it can never have matches + // foo.txt/** doesn't match foo.txt + if (!entries) + return cb() + + // test without the globstar, and with every child both below + // and replacing the globstar. + var remainWithoutGlobStar = remain.slice(1) + var gspref = prefix ? [ prefix ] : [] + var noGlobStar = gspref.concat(remainWithoutGlobStar) + // the noGlobStar pattern exits the inGlobStar state + this._process(noGlobStar, index, false, cb) -/***/ }), -/* 36 */ -/***/ (function(module, exports) { + var isSym = this.symlinks[abs] + var len = entries.length -module.exports = __webpack_require__(120); + // If it's a symlink, and we're in a globstar, then stop + if (isSym && inGlobStar) + return cb() -/***/ }), -/* 37 */, -/* 38 */, -/* 39 */, -/* 40 */ -/***/ (function(module, exports, __webpack_require__) { + for (var i = 0; i < len; i++) { + var e = entries[i] + if (e.charAt(0) === '.' && !this.dot) + continue -"use strict"; + // these two cases enter the inGlobStar state + var instead = gspref.concat(entries[i], remainWithoutGlobStar) + this._process(instead, index, true, cb) + var below = gspref.concat(entries[i], remain) + this._process(below, index, true, cb) + } -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.wait = wait; -exports.promisify = promisify; -exports.queue = queue; -function wait(delay) { - return new Promise(resolve => { - setTimeout(resolve, delay); - }); + cb() } -function promisify(fn, firstData) { - return function (...args) { - return new Promise(function (resolve, reject) { - args.push(function (err, ...result) { - let res = result; +Glob.prototype._processSimple = function (prefix, index, cb) { + // XXX review this. Shouldn't it be doing the mounting etc + // before doing stat? kinda weird? + var self = this + this._stat(prefix, function (er, exists) { + self._processSimple2(prefix, index, er, exists, cb) + }) +} +Glob.prototype._processSimple2 = function (prefix, index, er, exists, cb) { - if (result.length <= 1) { - res = result[0]; - } + //console.error('ps2', prefix, exists) - if (firstData) { - res = err; - err = null; - } + if (!this.matches[index]) + this.matches[index] = Object.create(null) - if (err) { - reject(err); - } else { - resolve(res); - } - }); + // If it doesn't exist, then just mark the lack of results + if (!exists) + return cb() - fn.apply(null, args); - }); - }; + if (prefix && isAbsolute(prefix) && !this.nomount) { + var trail = /[\/\\]$/.test(prefix) + if (prefix.charAt(0) === '/') { + prefix = path.join(this.root, prefix) + } else { + prefix = path.resolve(this.root, prefix) + if (trail) + prefix += '/' + } + } + + if (process.platform === 'win32') + prefix = prefix.replace(/\\/g, '/') + + // Mark this as a match + this._emitMatch(index, prefix) + cb() } -function queue(arr, promiseProducer, concurrency = Infinity) { - concurrency = Math.min(concurrency, arr.length); +// Returns either 'DIR', 'FILE', or false +Glob.prototype._stat = function (f, cb) { + var abs = this._makeAbs(f) + var needDir = f.slice(-1) === '/' - // clone - arr = arr.slice(); + if (f.length > this.maxLength) + return cb() - const results = []; - let total = arr.length; - if (!total) { - return Promise.resolve(results); + if (!this.stat && ownProp(this.cache, abs)) { + var c = this.cache[abs] + + if (Array.isArray(c)) + c = 'DIR' + + // It exists, but maybe not how we need it + if (!needDir || c === 'DIR') + return cb(null, c) + + if (needDir && c === 'FILE') + return cb() + + // otherwise we have to stat, because maybe c=true + // if we know it exists, but not what it is. } - return new Promise((resolve, reject) => { - for (let i = 0; i < concurrency; i++) { - next(); + var exists + var stat = this.statCache[abs] + if (stat !== undefined) { + if (stat === false) + return cb(null, stat) + else { + var type = stat.isDirectory() ? 'DIR' : 'FILE' + if (needDir && type === 'FILE') + return cb() + else + return cb(null, type, stat) } + } - function next() { - const item = arr.shift(); - const promise = promiseProducer(item); - - promise.then(function (result) { - results.push(result); + var self = this + var statcb = inflight('stat\0' + abs, lstatcb_) + if (statcb) + fs.lstat(abs, statcb) - total--; - if (total === 0) { - resolve(results); - } else { - if (arr.length) { - next(); - } - } - }, reject); + function lstatcb_ (er, lstat) { + if (lstat && lstat.isSymbolicLink()) { + // If it's a symlink, then treat it as the target, unless + // the target does not exist, then treat it as a file. + return fs.stat(abs, function (er, stat) { + if (er) + self._stat2(f, abs, null, lstat, cb) + else + self._stat2(f, abs, er, stat, cb) + }) + } else { + self._stat2(f, abs, er, lstat, cb) } - }); + } } -/***/ }), -/* 41 */ -/***/ (function(module, exports, __webpack_require__) { +Glob.prototype._stat2 = function (f, abs, er, stat, cb) { + if (er && (er.code === 'ENOENT' || er.code === 'ENOTDIR')) { + this.statCache[abs] = false + return cb() + } -var global = __webpack_require__(11); -var core = __webpack_require__(23); -var ctx = __webpack_require__(48); -var hide = __webpack_require__(31); -var has = __webpack_require__(49); -var PROTOTYPE = 'prototype'; + var needDir = f.slice(-1) === '/' + this.statCache[abs] = stat -var $export = function (type, name, source) { - var IS_FORCED = type & $export.F; - var IS_GLOBAL = type & $export.G; - var IS_STATIC = type & $export.S; - var IS_PROTO = type & $export.P; - var IS_BIND = type & $export.B; - var IS_WRAP = type & $export.W; - var exports = IS_GLOBAL ? core : core[name] || (core[name] = {}); - var expProto = exports[PROTOTYPE]; - var target = IS_GLOBAL ? global : IS_STATIC ? global[name] : (global[name] || {})[PROTOTYPE]; - var key, own, out; - if (IS_GLOBAL) source = name; - for (key in source) { - // contains in native - own = !IS_FORCED && target && target[key] !== undefined; - if (own && has(exports, key)) continue; - // export native or passed - out = own ? target[key] : source[key]; - // prevent global pollution for namespaces - exports[key] = IS_GLOBAL && typeof target[key] != 'function' ? source[key] - // bind timers to global for call from export context - : IS_BIND && own ? ctx(out, global) - // wrap global constructors for prevent change them in library - : IS_WRAP && target[key] == out ? (function (C) { - var F = function (a, b, c) { - if (this instanceof C) { - switch (arguments.length) { - case 0: return new C(); - case 1: return new C(a); - case 2: return new C(a, b); - } return new C(a, b, c); - } return C.apply(this, arguments); - }; - F[PROTOTYPE] = C[PROTOTYPE]; - return F; - // make static versions for prototype methods - })(out) : IS_PROTO && typeof out == 'function' ? ctx(Function.call, out) : out; - // export proto methods to core.%CONSTRUCTOR%.methods.%NAME% - if (IS_PROTO) { - (exports.virtual || (exports.virtual = {}))[key] = out; - // export proto methods to core.%CONSTRUCTOR%.prototype.%NAME% - if (type & $export.R && expProto && !expProto[key]) hide(expProto, key, out); - } - } -}; -// type bitmap -$export.F = 1; // forced -$export.G = 2; // global -$export.S = 4; // static -$export.P = 8; // proto -$export.B = 16; // bind -$export.W = 32; // wrap -$export.U = 64; // safe -$export.R = 128; // real proto method for `library` -module.exports = $export; + if (abs.slice(-1) === '/' && stat && !stat.isDirectory()) + return cb(null, false, stat) + + var c = true + if (stat) + c = stat.isDirectory() ? 'DIR' : 'FILE' + this.cache[abs] = this.cache[abs] || c + + if (needDir && c === 'FILE') + return cb() + + return cb(null, c, stat) +} /***/ }), -/* 42 */ +/* 76 */ /***/ (function(module, exports, __webpack_require__) { -try { - var util = __webpack_require__(2); - if (typeof util.inherits !== 'function') throw ''; - module.exports = util.inherits; -} catch (e) { - module.exports = __webpack_require__(224); +"use strict"; + + +function posix(path) { + return path.charAt(0) === '/'; +} + +function win32(path) { + // https://github.com/nodejs/node/blob/b3fcc245fb25539909ef1d5eaa01dbf92e168633/lib/path.js#L56 + var splitDeviceRe = /^([a-zA-Z]:|[\\\/]{2}[^\\\/]+[\\\/]+[^\\\/]+)?([\\\/])?([\s\S]*?)$/; + var result = splitDeviceRe.exec(path); + var device = result[1] || ''; + var isUnc = Boolean(device && device.charAt(1) !== ':'); + + // UNC paths are always absolute + return Boolean(result[2] || isUnc); } +module.exports = process.platform === 'win32' ? win32 : posix; +module.exports.posix = posix; +module.exports.win32 = win32; + /***/ }), -/* 43 */, -/* 44 */, -/* 45 */ +/* 77 */, +/* 78 */, +/* 79 */ +/***/ (function(module, exports) { + +module.exports = __webpack_require__(122); + +/***/ }), +/* 80 */, +/* 81 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -31571,2427 +32402,2098 @@ try { Object.defineProperty(exports, "__esModule", { value: true }); -exports.home = undefined; -var _rootUser; +exports.default = function (str, fileLoc = 'lockfile') { + str = (0, (_stripBom || _load_stripBom()).default)(str); + return hasMergeConflicts(str) ? parseWithConflict(str, fileLoc) : { type: 'success', object: parse(str, fileLoc) }; +}; -function _load_rootUser() { - return _rootUser = _interopRequireDefault(__webpack_require__(169)); +var _util; + +function _load_util() { + return _util = _interopRequireDefault(__webpack_require__(2)); } -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } +var _invariant; -const path = __webpack_require__(0); +function _load_invariant() { + return _invariant = _interopRequireDefault(__webpack_require__(7)); +} -const home = exports.home = __webpack_require__(36).homedir(); +var _stripBom; -const userHomeDir = (_rootUser || _load_rootUser()).default ? path.resolve('/usr/local/share') : home; +function _load_stripBom() { + return _stripBom = _interopRequireDefault(__webpack_require__(122)); +} -exports.default = userHomeDir; +var _constants; -/***/ }), -/* 46 */ -/***/ (function(module, exports) { +function _load_constants() { + return _constants = __webpack_require__(6); +} -module.exports = function (it) { - if (typeof it != 'function') throw TypeError(it + ' is not a function!'); - return it; -}; +var _errors; +function _load_errors() { + return _errors = __webpack_require__(4); +} -/***/ }), -/* 47 */ -/***/ (function(module, exports) { +var _map; -var toString = {}.toString; +function _load_map() { + return _map = _interopRequireDefault(__webpack_require__(20)); +} -module.exports = function (it) { - return toString.call(it).slice(8, -1); -}; +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } +/* eslint quotes: 0 */ -/***/ }), -/* 48 */ -/***/ (function(module, exports, __webpack_require__) { +const VERSION_REGEX = /^yarn lockfile v(\d+)$/; -// optional / simple context binding -var aFunction = __webpack_require__(46); -module.exports = function (fn, that, length) { - aFunction(fn); - if (that === undefined) return fn; - switch (length) { - case 1: return function (a) { - return fn.call(that, a); - }; - case 2: return function (a, b) { - return fn.call(that, a, b); - }; - case 3: return function (a, b, c) { - return fn.call(that, a, b, c); - }; - } - return function (/* ...args */) { - return fn.apply(that, arguments); - }; +const TOKEN_TYPES = { + boolean: 'BOOLEAN', + string: 'STRING', + identifier: 'IDENTIFIER', + eof: 'EOF', + colon: 'COLON', + newline: 'NEWLINE', + comment: 'COMMENT', + indent: 'INDENT', + invalid: 'INVALID', + number: 'NUMBER', + comma: 'COMMA' }; +const VALID_PROP_VALUE_TOKENS = [TOKEN_TYPES.boolean, TOKEN_TYPES.string, TOKEN_TYPES.number]; -/***/ }), -/* 49 */ -/***/ (function(module, exports) { - -var hasOwnProperty = {}.hasOwnProperty; -module.exports = function (it, key) { - return hasOwnProperty.call(it, key); -}; +function isValidPropValueToken(token) { + return VALID_PROP_VALUE_TOKENS.indexOf(token.type) >= 0; +} +function* tokenise(input) { + let lastNewline = false; + let line = 1; + let col = 0; -/***/ }), -/* 50 */ -/***/ (function(module, exports, __webpack_require__) { + function buildToken(type, value) { + return { line, col, type, value }; + } -var anObject = __webpack_require__(27); -var IE8_DOM_DEFINE = __webpack_require__(184); -var toPrimitive = __webpack_require__(201); -var dP = Object.defineProperty; + while (input.length) { + let chop = 0; -exports.f = __webpack_require__(33) ? Object.defineProperty : function defineProperty(O, P, Attributes) { - anObject(O); - P = toPrimitive(P, true); - anObject(Attributes); - if (IE8_DOM_DEFINE) try { - return dP(O, P, Attributes); - } catch (e) { /* empty */ } - if ('get' in Attributes || 'set' in Attributes) throw TypeError('Accessors not supported!'); - if ('value' in Attributes) O[P] = Attributes.value; - return O; -}; + if (input[0] === '\n' || input[0] === '\r') { + chop++; + // If this is a \r\n line, ignore both chars but only add one new line + if (input[1] === '\n') { + chop++; + } + line++; + col = 0; + yield buildToken(TOKEN_TYPES.newline); + } else if (input[0] === '#') { + chop++; + let val = ''; + while (input[chop] !== '\n') { + val += input[chop]; + chop++; + } + yield buildToken(TOKEN_TYPES.comment, val); + } else if (input[0] === ' ') { + if (lastNewline) { + let indent = ''; + for (let i = 0; input[i] === ' '; i++) { + indent += input[i]; + } -/***/ }), -/* 51 */, -/* 52 */, -/* 53 */, -/* 54 */ -/***/ (function(module, exports) { + if (indent.length % 2) { + throw new TypeError('Invalid number of spaces'); + } else { + chop = indent.length; + yield buildToken(TOKEN_TYPES.indent, indent.length / 2); + } + } else { + chop++; + } + } else if (input[0] === '"') { + let val = ''; -module.exports = __webpack_require__(155); + for (let i = 0;; i++) { + const currentChar = input[i]; + val += currentChar; -/***/ }), -/* 55 */ -/***/ (function(module, exports, __webpack_require__) { + if (i > 0 && currentChar === '"') { + const isEscaped = input[i - 1] === '\\' && input[i - 2] !== '\\'; + if (!isEscaped) { + break; + } + } + } -"use strict"; + chop = val.length; + try { + yield buildToken(TOKEN_TYPES.string, JSON.parse(val)); + } catch (err) { + if (err instanceof SyntaxError) { + yield buildToken(TOKEN_TYPES.invalid); + } else { + throw err; + } + } + } else if (/^[0-9]/.test(input)) { + let val = ''; + for (let i = 0; /^[0-9]$/.test(input[i]); i++) { + val += input[i]; + } + chop = val.length; -const Buffer = __webpack_require__(32).Buffer + yield buildToken(TOKEN_TYPES.number, +val); + } else if (/^true/.test(input)) { + yield buildToken(TOKEN_TYPES.boolean, true); + chop = 4; + } else if (/^false/.test(input)) { + yield buildToken(TOKEN_TYPES.boolean, false); + chop = 5; + } else if (input[0] === ':') { + yield buildToken(TOKEN_TYPES.colon); + chop++; + } else if (input[0] === ',') { + yield buildToken(TOKEN_TYPES.comma); + chop++; + } else if (/^[a-zA-Z\/-]/g.test(input)) { + let name = ''; + for (let i = 0; i < input.length; i++) { + const char = input[i]; + if (char === ':' || char === ' ' || char === '\n' || char === '\r' || char === ',') { + break; + } else { + name += char; + } + } + chop = name.length; -const crypto = __webpack_require__(9) -const Transform = __webpack_require__(17).Transform + yield buildToken(TOKEN_TYPES.string, name); + } else { + yield buildToken(TOKEN_TYPES.invalid); + } -const SPEC_ALGORITHMS = ['sha256', 'sha384', 'sha512'] + if (!chop) { + // will trigger infinite recursion + yield buildToken(TOKEN_TYPES.invalid); + } -const BASE64_REGEX = /^[a-z0-9+/]+(?:=?=?)$/i -const SRI_REGEX = /^([^-]+)-([^?]+)([?\S*]*)$/ -const STRICT_SRI_REGEX = /^([^-]+)-([A-Za-z0-9+/=]{44,88})(\?[\x21-\x7E]*)*$/ -const VCHAR_REGEX = /^[\x21-\x7E]+$/ + col += chop; + lastNewline = input[0] === '\n' || input[0] === '\r' && input[1] === '\n'; + input = input.slice(chop); + } -class Hash { - get isHash () { return true } - constructor (hash, opts) { - const strict = !!(opts && opts.strict) - this.source = hash.trim() - // 3.1. Integrity metadata (called "Hash" by ssri) - // https://w3c.github.io/webappsec-subresource-integrity/#integrity-metadata-description - const match = this.source.match( - strict - ? STRICT_SRI_REGEX - : SRI_REGEX - ) - if (!match) { return } - if (strict && !SPEC_ALGORITHMS.some(a => a === match[1])) { return } - this.algorithm = match[1] - this.digest = match[2] + yield buildToken(TOKEN_TYPES.eof); +} - const rawOpts = match[3] - this.options = rawOpts ? rawOpts.slice(1).split('?') : [] - } - hexDigest () { - return this.digest && Buffer.from(this.digest, 'base64').toString('hex') - } - toJSON () { - return this.toString() +class Parser { + constructor(input, fileLoc = 'lockfile') { + this.comments = []; + this.tokens = tokenise(input); + this.fileLoc = fileLoc; } - toString (opts) { - if (opts && opts.strict) { - // Strict mode enforces the standard as close to the foot of the - // letter as it can. - if (!( - // The spec has very restricted productions for algorithms. - // https://www.w3.org/TR/CSP2/#source-list-syntax - SPEC_ALGORITHMS.some(x => x === this.algorithm) && - // Usually, if someone insists on using a "different" base64, we - // leave it as-is, since there's multiple standards, and the - // specified is not a URL-safe variant. - // https://www.w3.org/TR/CSP2/#base64_value - this.digest.match(BASE64_REGEX) && - // Option syntax is strictly visual chars. - // https://w3c.github.io/webappsec-subresource-integrity/#grammardef-option-expression - // https://tools.ietf.org/html/rfc5234#appendix-B.1 - (this.options || []).every(opt => opt.match(VCHAR_REGEX)) - )) { - return '' + + onComment(token) { + const value = token.value; + (0, (_invariant || _load_invariant()).default)(typeof value === 'string', 'expected token value to be a string'); + + const comment = value.trim(); + + const versionMatch = comment.match(VERSION_REGEX); + if (versionMatch) { + const version = +versionMatch[1]; + if (version > (_constants || _load_constants()).LOCKFILE_VERSION) { + throw new (_errors || _load_errors()).MessageError(`Can't install from a lockfile of version ${version} as you're on an old yarn version that only supports ` + `versions up to ${(_constants || _load_constants()).LOCKFILE_VERSION}. Run \`$ yarn self-update\` to upgrade to the latest version.`); } } - const options = this.options && this.options.length - ? `?${this.options.join('?')}` - : '' - return `${this.algorithm}-${this.digest}${options}` - } -} -class Integrity { - get isIntegrity () { return true } - toJSON () { - return this.toString() - } - toString (opts) { - opts = opts || {} - let sep = opts.sep || ' ' - if (opts.strict) { - // Entries must be separated by whitespace, according to spec. - sep = sep.replace(/\S+/g, ' ') - } - return Object.keys(this).map(k => { - return this[k].map(hash => { - return Hash.prototype.toString.call(hash, opts) - }).filter(x => x.length).join(sep) - }).filter(x => x.length).join(sep) - } - concat (integrity, opts) { - const other = typeof integrity === 'string' - ? integrity - : stringify(integrity, opts) - return parse(`${this.toString(opts)} ${other}`, opts) - } - hexDigest () { - return parse(this, {single: true}).hexDigest() - } - match (integrity, opts) { - const other = parse(integrity, opts) - const algo = other.pickAlgorithm(opts) - return ( - this[algo] && - other[algo] && - this[algo].find(hash => - other[algo].find(otherhash => - hash.digest === otherhash.digest - ) - ) - ) || false + this.comments.push(comment); } - pickAlgorithm (opts) { - const pickAlgorithm = (opts && opts.pickAlgorithm) || getPrioritizedHash - const keys = Object.keys(this) - if (!keys.length) { - throw new Error(`No algorithms available for ${ - JSON.stringify(this.toString()) - }`) + + next() { + const item = this.tokens.next(); + (0, (_invariant || _load_invariant()).default)(item, 'expected a token'); + + const done = item.done, + value = item.value; + + if (done || !value) { + throw new Error('No more tokens'); + } else if (value.type === TOKEN_TYPES.comment) { + this.onComment(value); + return this.next(); + } else { + return this.token = value; } - return keys.reduce((acc, algo) => { - return pickAlgorithm(acc, algo) || acc - }) } -} -module.exports.parse = parse -function parse (sri, opts) { - opts = opts || {} - if (typeof sri === 'string') { - return _parse(sri, opts) - } else if (sri.algorithm && sri.digest) { - const fullSri = new Integrity() - fullSri[sri.algorithm] = [sri] - return _parse(stringify(fullSri, opts), opts) - } else { - return _parse(stringify(sri, opts), opts) + unexpected(msg = 'Unexpected token') { + throw new SyntaxError(`${msg} ${this.token.line}:${this.token.col} in ${this.fileLoc}`); } -} -function _parse (integrity, opts) { - // 3.4.3. Parse metadata - // https://w3c.github.io/webappsec-subresource-integrity/#parse-metadata - if (opts.single) { - return new Hash(integrity, opts) - } - return integrity.trim().split(/\s+/).reduce((acc, string) => { - const hash = new Hash(string, opts) - if (hash.algorithm && hash.digest) { - const algo = hash.algorithm - if (!acc[algo]) { acc[algo] = [] } - acc[algo].push(hash) + expect(tokType) { + if (this.token.type === tokType) { + this.next(); + } else { + this.unexpected(); } - return acc - }, new Integrity()) -} + } -module.exports.stringify = stringify -function stringify (obj, opts) { - if (obj.algorithm && obj.digest) { - return Hash.prototype.toString.call(obj, opts) - } else if (typeof obj === 'string') { - return stringify(parse(obj, opts), opts) - } else { - return Integrity.prototype.toString.call(obj, opts) + eat(tokType) { + if (this.token.type === tokType) { + this.next(); + return true; + } else { + return false; + } } -} -module.exports.fromHex = fromHex -function fromHex (hexDigest, algorithm, opts) { - const optString = (opts && opts.options && opts.options.length) - ? `?${opts.options.join('?')}` - : '' - return parse( - `${algorithm}-${ - Buffer.from(hexDigest, 'hex').toString('base64') - }${optString}`, opts - ) -} + parse(indent = 0) { + const obj = (0, (_map || _load_map()).default)(); -module.exports.fromData = fromData -function fromData (data, opts) { - opts = opts || {} - const algorithms = opts.algorithms || ['sha512'] - const optString = opts.options && opts.options.length - ? `?${opts.options.join('?')}` - : '' - return algorithms.reduce((acc, algo) => { - const digest = crypto.createHash(algo).update(data).digest('base64') - const hash = new Hash( - `${algo}-${digest}${optString}`, - opts - ) - if (hash.algorithm && hash.digest) { - const algo = hash.algorithm - if (!acc[algo]) { acc[algo] = [] } - acc[algo].push(hash) - } - return acc - }, new Integrity()) -} + while (true) { + const propToken = this.token; -module.exports.fromStream = fromStream -function fromStream (stream, opts) { - opts = opts || {} - const P = opts.Promise || Promise - const istream = integrityStream(opts) - return new P((resolve, reject) => { - stream.pipe(istream) - stream.on('error', reject) - istream.on('error', reject) - let sri - istream.on('integrity', s => { sri = s }) - istream.on('end', () => resolve(sri)) - istream.on('data', () => {}) - }) -} + if (propToken.type === TOKEN_TYPES.newline) { + const nextToken = this.next(); + if (!indent) { + // if we have 0 indentation then the next token doesn't matter + continue; + } -module.exports.checkData = checkData -function checkData (data, sri, opts) { - opts = opts || {} - sri = parse(sri, opts) - if (!Object.keys(sri).length) { - if (opts.error) { - throw Object.assign( - new Error('No valid integrity hashes to check against'), { - code: 'EINTEGRITY' + if (nextToken.type !== TOKEN_TYPES.indent) { + // if we have no indentation after a newline then we've gone down a level + break; } - ) - } else { - return false - } - } - const algorithm = sri.pickAlgorithm(opts) - const digest = crypto.createHash(algorithm).update(data).digest('base64') - const newSri = parse({algorithm, digest}) - const match = newSri.match(sri, opts) - if (match || !opts.error) { - return match - } else if (typeof opts.size === 'number' && (data.length !== opts.size)) { - const err = new Error(`data size mismatch when checking ${sri}.\n Wanted: ${opts.size}\n Found: ${data.length}`) - err.code = 'EBADSIZE' - err.found = data.length - err.expected = opts.size - err.sri = sri - throw err - } else { - const err = new Error(`Integrity checksum failed when using ${algorithm}: Wanted ${sri}, but got ${newSri}. (${data.length} bytes)`) - err.code = 'EINTEGRITY' - err.found = newSri - err.expected = sri - err.algorithm = algorithm - err.sri = sri - throw err - } -} -module.exports.checkStream = checkStream -function checkStream (stream, sri, opts) { - opts = opts || {} - const P = opts.Promise || Promise - const checker = integrityStream(Object.assign({}, opts, { - integrity: sri - })) - return new P((resolve, reject) => { - stream.pipe(checker) - stream.on('error', reject) - checker.on('error', reject) - let sri - checker.on('verified', s => { sri = s }) - checker.on('end', () => resolve(sri)) - checker.on('data', () => {}) - }) -} + if (nextToken.value === indent) { + // all is good, the indent is on our level + this.next(); + } else { + // the indentation is less than our level + break; + } + } else if (propToken.type === TOKEN_TYPES.indent) { + if (propToken.value === indent) { + this.next(); + } else { + break; + } + } else if (propToken.type === TOKEN_TYPES.eof) { + break; + } else if (propToken.type === TOKEN_TYPES.string) { + // property key + const key = propToken.value; + (0, (_invariant || _load_invariant()).default)(key, 'Expected a key'); -module.exports.integrityStream = integrityStream -function integrityStream (opts) { - opts = opts || {} - // For verification - const sri = opts.integrity && parse(opts.integrity, opts) - const goodSri = sri && Object.keys(sri).length - const algorithm = goodSri && sri.pickAlgorithm(opts) - const digests = goodSri && sri[algorithm] - // Calculating stream - const algorithms = Array.from( - new Set( - (opts.algorithms || ['sha512']) - .concat(algorithm ? [algorithm] : []) - ) - ) - const hashes = algorithms.map(crypto.createHash) - let streamSize = 0 - const stream = new Transform({ - transform (chunk, enc, cb) { - streamSize += chunk.length - hashes.forEach(h => h.update(chunk, enc)) - cb(null, chunk, enc) - } - }).on('end', () => { - const optString = (opts.options && opts.options.length) - ? `?${opts.options.join('?')}` - : '' - const newSri = parse(hashes.map((h, i) => { - return `${algorithms[i]}-${h.digest('base64')}${optString}` - }).join(' '), opts) - // Integrity verification mode - const match = goodSri && newSri.match(sri, opts) - if (typeof opts.size === 'number' && streamSize !== opts.size) { - const err = new Error(`stream size mismatch when checking ${sri}.\n Wanted: ${opts.size}\n Found: ${streamSize}`) - err.code = 'EBADSIZE' - err.found = streamSize - err.expected = opts.size - err.sri = sri - stream.emit('error', err) - } else if (opts.integrity && !match) { - const err = new Error(`${sri} integrity checksum failed when using ${algorithm}: wanted ${digests} but got ${newSri}. (${streamSize} bytes)`) - err.code = 'EINTEGRITY' - err.found = newSri - err.expected = digests - err.algorithm = algorithm - err.sri = sri - stream.emit('error', err) - } else { - stream.emit('size', streamSize) - stream.emit('integrity', newSri) - match && stream.emit('verified', match) - } - }) - return stream -} + const keys = [key]; + this.next(); -module.exports.create = createIntegrity -function createIntegrity (opts) { - opts = opts || {} - const algorithms = opts.algorithms || ['sha512'] - const optString = opts.options && opts.options.length - ? `?${opts.options.join('?')}` - : '' + // support multiple keys + while (this.token.type === TOKEN_TYPES.comma) { + this.next(); // skip comma - const hashes = algorithms.map(crypto.createHash) + const keyToken = this.token; + if (keyToken.type !== TOKEN_TYPES.string) { + this.unexpected('Expected string'); + } - return { - update: function (chunk, enc) { - hashes.forEach(h => h.update(chunk, enc)) - return this - }, - digest: function (enc) { - const integrity = algorithms.reduce((acc, algo) => { - const digest = hashes.shift().digest('base64') - const hash = new Hash( - `${algo}-${digest}${optString}`, - opts - ) - if (hash.algorithm && hash.digest) { - const algo = hash.algorithm - if (!acc[algo]) { acc[algo] = [] } - acc[algo].push(hash) + const key = keyToken.value; + (0, (_invariant || _load_invariant()).default)(key, 'Expected a key'); + keys.push(key); + this.next(); } - return acc - }, new Integrity()) - - return integrity - } - } -} -const NODE_HASHES = new Set(crypto.getHashes()) - -// This is a Best Effort™ at a reasonable priority for hash algos -const DEFAULT_PRIORITY = [ - 'md5', 'whirlpool', 'sha1', 'sha224', 'sha256', 'sha384', 'sha512', - // TODO - it's unclear _which_ of these Node will actually use as its name - // for the algorithm, so we guesswork it based on the OpenSSL names. - 'sha3', - 'sha3-256', 'sha3-384', 'sha3-512', - 'sha3_256', 'sha3_384', 'sha3_512' -].filter(algo => NODE_HASHES.has(algo)) - -function getPrioritizedHash (algo1, algo2) { - return DEFAULT_PRIORITY.indexOf(algo1.toLowerCase()) >= DEFAULT_PRIORITY.indexOf(algo2.toLowerCase()) - ? algo1 - : algo2 -} - - -/***/ }), -/* 56 */, -/* 57 */, -/* 58 */, -/* 59 */, -/* 60 */ -/***/ (function(module, exports, __webpack_require__) { + const valToken = this.token; -module.exports = minimatch -minimatch.Minimatch = Minimatch + if (valToken.type === TOKEN_TYPES.colon) { + // object + this.next(); -var path = { sep: '/' } -try { - path = __webpack_require__(0) -} catch (er) {} + // parse object + const val = this.parse(indent + 1); -var GLOBSTAR = minimatch.GLOBSTAR = Minimatch.GLOBSTAR = {} -var expand = __webpack_require__(175) + for (var _iterator = keys, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : _iterator[Symbol.iterator]();;) { + var _ref; -var plTypes = { - '!': { open: '(?:(?!(?:', close: '))[^/]*?)'}, - '?': { open: '(?:', close: ')?' }, - '+': { open: '(?:', close: ')+' }, - '*': { open: '(?:', close: ')*' }, - '@': { open: '(?:', close: ')' } -} + if (_isArray) { + if (_i >= _iterator.length) break; + _ref = _iterator[_i++]; + } else { + _i = _iterator.next(); + if (_i.done) break; + _ref = _i.value; + } -// any single thing other than / -// don't need to escape / when using new RegExp() -var qmark = '[^/]' + const key = _ref; -// * => any number of characters -var star = qmark + '*?' + obj[key] = val; + } -// ** when dots are allowed. Anything goes, except .. and . -// not (^ or / followed by one or two dots followed by $ or /), -// followed by anything, any number of times. -var twoStarDot = '(?:(?!(?:\\\/|^)(?:\\.{1,2})($|\\\/)).)*?' + if (indent && this.token.type !== TOKEN_TYPES.indent) { + break; + } + } else if (isValidPropValueToken(valToken)) { + // plain value + for (var _iterator2 = keys, _isArray2 = Array.isArray(_iterator2), _i2 = 0, _iterator2 = _isArray2 ? _iterator2 : _iterator2[Symbol.iterator]();;) { + var _ref2; -// not a ^ or / followed by a dot, -// followed by anything, any number of times. -var twoStarNoDot = '(?:(?!(?:\\\/|^)\\.).)*?' + if (_isArray2) { + if (_i2 >= _iterator2.length) break; + _ref2 = _iterator2[_i2++]; + } else { + _i2 = _iterator2.next(); + if (_i2.done) break; + _ref2 = _i2.value; + } -// characters that need to be escaped in RegExp. -var reSpecials = charSet('().*{}+?[]^$\\!') + const key = _ref2; -// "abc" -> { a:true, b:true, c:true } -function charSet (s) { - return s.split('').reduce(function (set, c) { - set[c] = true - return set - }, {}) -} + obj[key] = valToken.value; + } -// normalizes slashes. -var slashSplit = /\/+/ + this.next(); + } else { + this.unexpected('Invalid value type'); + } + } else { + this.unexpected(`Unknown token: ${(_util || _load_util()).default.inspect(propToken)}`); + } + } -minimatch.filter = filter -function filter (pattern, options) { - options = options || {} - return function (p, i, list) { - return minimatch(p, pattern, options) + return obj; } } -function ext (a, b) { - a = a || {} - b = b || {} - var t = {} - Object.keys(b).forEach(function (k) { - t[k] = b[k] - }) - Object.keys(a).forEach(function (k) { - t[k] = a[k] - }) - return t -} +const MERGE_CONFLICT_ANCESTOR = '|||||||'; +const MERGE_CONFLICT_END = '>>>>>>>'; +const MERGE_CONFLICT_SEP = '======='; +const MERGE_CONFLICT_START = '<<<<<<<'; -minimatch.defaults = function (def) { - if (!def || !Object.keys(def).length) return minimatch +/** + * Extract the two versions of the lockfile from a merge conflict. + */ +function extractConflictVariants(str) { + const variants = [[], []]; + const lines = str.split(/\r?\n/g); + let skip = false; - var orig = minimatch + while (lines.length) { + const line = lines.shift(); + if (line.startsWith(MERGE_CONFLICT_START)) { + // get the first variant + while (lines.length) { + const conflictLine = lines.shift(); + if (conflictLine === MERGE_CONFLICT_SEP) { + skip = false; + break; + } else if (skip || conflictLine.startsWith(MERGE_CONFLICT_ANCESTOR)) { + skip = true; + continue; + } else { + variants[0].push(conflictLine); + } + } - var m = function minimatch (p, pattern, options) { - return orig.minimatch(p, pattern, ext(def, options)) + // get the second variant + while (lines.length) { + const conflictLine = lines.shift(); + if (conflictLine.startsWith(MERGE_CONFLICT_END)) { + break; + } else { + variants[1].push(conflictLine); + } + } + } else { + variants[0].push(line); + variants[1].push(line); + } } - m.Minimatch = function Minimatch (pattern, options) { - return new orig.Minimatch(pattern, ext(def, options)) - } + return [variants[0].join('\n'), variants[1].join('\n')]; +} - return m +/** + * Check if a lockfile has merge conflicts. + */ +function hasMergeConflicts(str) { + return str.includes(MERGE_CONFLICT_START) && str.includes(MERGE_CONFLICT_SEP) && str.includes(MERGE_CONFLICT_END); } -Minimatch.defaults = function (def) { - if (!def || !Object.keys(def).length) return Minimatch - return minimatch.defaults(def).Minimatch +/** + * Parse the lockfile. + */ +function parse(str, fileLoc) { + const parser = new Parser(str, fileLoc); + parser.next(); + return parser.parse(); } -function minimatch (p, pattern, options) { - if (typeof pattern !== 'string') { - throw new TypeError('glob pattern string required') +/** + * Parse and merge the two variants in a conflicted lockfile. + */ +function parseWithConflict(str, fileLoc) { + const variants = extractConflictVariants(str); + try { + return { type: 'merge', object: Object.assign({}, parse(variants[0], fileLoc), parse(variants[1], fileLoc)) }; + } catch (err) { + if (err instanceof SyntaxError) { + return { type: 'conflict', object: {} }; + } else { + throw err; + } } +} - if (!options) options = {} +/***/ }), +/* 82 */, +/* 83 */, +/* 84 */ +/***/ (function(module, exports, __webpack_require__) { - // shortcut: comments match nothing. - if (!options.nocomment && pattern.charAt(0) === '#') { - return false - } +"use strict"; - // "" only matches "" - if (pattern.trim() === '') return p === '' - return new Minimatch(pattern, options).match(p) -} +Object.defineProperty(exports, "__esModule", { + value: true +}); -function Minimatch (pattern, options) { - if (!(this instanceof Minimatch)) { - return new Minimatch(pattern, options) - } +var _map; - if (typeof pattern !== 'string') { - throw new TypeError('glob pattern string required') - } +function _load_map() { + return _map = _interopRequireDefault(__webpack_require__(20)); +} - if (!options) options = {} - pattern = pattern.trim() +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - // windows support: need to use /, not \ - if (path.sep !== '/') { - pattern = pattern.split(path.sep).join('/') - } +const debug = __webpack_require__(212)('yarn'); - this.options = options - this.set = [] - this.pattern = pattern - this.regexp = null - this.negate = false - this.comment = false - this.empty = false +class BlockingQueue { + constructor(alias, maxConcurrency = Infinity) { + this.concurrencyQueue = []; + this.maxConcurrency = maxConcurrency; + this.runningCount = 0; + this.warnedStuck = false; + this.alias = alias; + this.first = true; - // make the set of regexps etc. - this.make() -} + this.running = (0, (_map || _load_map()).default)(); + this.queue = (0, (_map || _load_map()).default)(); -Minimatch.prototype.debug = function () {} + this.stuckTick = this.stuckTick.bind(this); + } -Minimatch.prototype.make = make -function make () { - // don't do it more than once. - if (this._made) return + stillActive() { + if (this.stuckTimer) { + clearTimeout(this.stuckTimer); + } - var pattern = this.pattern - var options = this.options + this.stuckTimer = setTimeout(this.stuckTick, 5000); - // empty patterns and comments match nothing. - if (!options.nocomment && pattern.charAt(0) === '#') { - this.comment = true - return + // We need to check the existence of unref because of https://github.com/facebook/jest/issues/4559 + // $FlowFixMe: Node's setInterval returns a Timeout, not a Number + this.stuckTimer.unref && this.stuckTimer.unref(); } - if (!pattern) { - this.empty = true - return + + stuckTick() { + if (this.runningCount === 1) { + this.warnedStuck = true; + debug(`The ${JSON.stringify(this.alias)} blocking queue may be stuck. 5 seconds ` + `without any activity with 1 worker: ${Object.keys(this.running)[0]}`); + } } - // step 1: figure out negation, etc. - this.parseNegate() + push(key, factory) { + if (this.first) { + this.first = false; + } else { + this.stillActive(); + } - // step 2: expand braces - var set = this.globSet = this.braceExpand() + return new Promise((resolve, reject) => { + // we're already running so push ourselves to the queue + const queue = this.queue[key] = this.queue[key] || []; + queue.push({ factory, resolve, reject }); - if (options.debug) this.debug = console.error + if (!this.running[key]) { + this.shift(key); + } + }); + } - this.debug(this.pattern, set) + shift(key) { + if (this.running[key]) { + delete this.running[key]; + this.runningCount--; - // step 3: now we have a set, so turn each one into a series of path-portion - // matching patterns. - // These will be regexps, except in the case of "**", which is - // set to the GLOBSTAR object for globstar behavior, - // and will not contain any / characters - set = this.globParts = set.map(function (s) { - return s.split(slashSplit) - }) + if (this.stuckTimer) { + clearTimeout(this.stuckTimer); + this.stuckTimer = null; + } - this.debug(this.pattern, set) + if (this.warnedStuck) { + this.warnedStuck = false; + debug(`${JSON.stringify(this.alias)} blocking queue finally resolved. Nothing to worry about.`); + } + } - // glob --> regexps - set = set.map(function (s, si, set) { - return s.map(this.parse, this) - }, this) + const queue = this.queue[key]; + if (!queue) { + return; + } - this.debug(this.pattern, set) + var _queue$shift = queue.shift(); - // filter out everything that didn't compile properly. - set = set.filter(function (s) { - return s.indexOf(false) === -1 - }) + const resolve = _queue$shift.resolve, + reject = _queue$shift.reject, + factory = _queue$shift.factory; - this.debug(this.pattern, set) + if (!queue.length) { + delete this.queue[key]; + } - this.set = set -} + const next = () => { + this.shift(key); + this.shiftConcurrencyQueue(); + }; -Minimatch.prototype.parseNegate = parseNegate -function parseNegate () { - var pattern = this.pattern - var negate = false - var options = this.options - var negateOffset = 0 + const run = () => { + this.running[key] = true; + this.runningCount++; - if (options.nonegate) return + factory().then(function (val) { + resolve(val); + next(); + return null; + }).catch(function (err) { + reject(err); + next(); + }); + }; - for (var i = 0, l = pattern.length - ; i < l && pattern.charAt(i) === '!' - ; i++) { - negate = !negate - negateOffset++ + this.maybePushConcurrencyQueue(run); } - if (negateOffset) this.pattern = pattern.substr(negateOffset) - this.negate = negate + maybePushConcurrencyQueue(run) { + if (this.runningCount < this.maxConcurrency) { + run(); + } else { + this.concurrencyQueue.push(run); + } + } + + shiftConcurrencyQueue() { + if (this.runningCount < this.maxConcurrency) { + const fn = this.concurrencyQueue.shift(); + if (fn) { + fn(); + } + } + } } +exports.default = BlockingQueue; -// Brace expansion: -// a{b,c}d -> abd acd -// a{b,}c -> abc ac -// a{0..3}d -> a0d a1d a2d a3d -// a{b,c{d,e}f}g -> abg acdfg acefg -// a{b,c}d{e,f}g -> abdeg acdeg abdeg abdfg -// -// Invalid sets are not expanded. -// a{2..}b -> a{2..}b -// a{b}c -> a{b}c -minimatch.braceExpand = function (pattern, options) { - return braceExpand(pattern, options) -} - -Minimatch.prototype.braceExpand = braceExpand - -function braceExpand (pattern, options) { - if (!options) { - if (this instanceof Minimatch) { - options = this.options - } else { - options = {} - } - } - - pattern = typeof pattern === 'undefined' - ? this.pattern : pattern +/***/ }), +/* 85 */ +/***/ (function(module, exports) { - if (typeof pattern === 'undefined') { - throw new TypeError('undefined pattern') +module.exports = function (exec) { + try { + return !!exec(); + } catch (e) { + return true; } +}; - if (options.nobrace || - !pattern.match(/\{.*\}/)) { - // shortcut. no need to expand. - return [pattern] - } - return expand(pattern) -} +/***/ }), +/* 86 */, +/* 87 */, +/* 88 */, +/* 89 */, +/* 90 */, +/* 91 */, +/* 92 */, +/* 93 */, +/* 94 */, +/* 95 */, +/* 96 */, +/* 97 */, +/* 98 */, +/* 99 */, +/* 100 */ +/***/ (function(module, exports, __webpack_require__) { -// parse a component of the expanded set. -// At this point, no pattern may contain "/" in it -// so we're going to return a 2d array, where each entry is the full -// pattern, split on '/', and then turned into a regular expression. -// A regexp is made at the end which joins each array with an -// escaped /, and another full one which joins each regexp with |. -// -// Following the lead of Bash 4.1, note that "**" only has special meaning -// when it is the *only* thing in a path portion. Otherwise, any series -// of * is equivalent to a single *. Globstar behavior is enabled by -// default, and can be disabled by setting options.noglobstar. -Minimatch.prototype.parse = parse -var SUBPARSE = {} -function parse (pattern, isSub) { - if (pattern.length > 1024 * 64) { - throw new TypeError('pattern is too long') - } +// getting tag from 19.1.3.6 Object.prototype.toString() +var cof = __webpack_require__(47); +var TAG = __webpack_require__(13)('toStringTag'); +// ES3 wrong here +var ARG = cof(function () { return arguments; }()) == 'Arguments'; - var options = this.options +// fallback for IE11 Script Access Denied error +var tryGet = function (it, key) { + try { + return it[key]; + } catch (e) { /* empty */ } +}; - // shortcuts - if (!options.noglobstar && pattern === '**') return GLOBSTAR - if (pattern === '') return '' +module.exports = function (it) { + var O, T, B; + return it === undefined ? 'Undefined' : it === null ? 'Null' + // @@toStringTag case + : typeof (T = tryGet(O = Object(it), TAG)) == 'string' ? T + // builtinTag case + : ARG ? cof(O) + // ES3 arguments fallback + : (B = cof(O)) == 'Object' && typeof O.callee == 'function' ? 'Arguments' : B; +}; - var re = '' - var hasMagic = !!options.nocase - var escaping = false - // ? => one single character - var patternListStack = [] - var negativeLists = [] - var stateChar - var inClass = false - var reClassStart = -1 - var classStart = -1 - // . and .. never match anything that doesn't start with ., - // even when options.dot is set. - var patternStart = pattern.charAt(0) === '.' ? '' // anything - // not (start or / followed by . or .. followed by / or end) - : options.dot ? '(?!(?:^|\\\/)\\.{1,2}(?:$|\\\/))' - : '(?!\\.)' - var self = this - function clearStateChar () { - if (stateChar) { - // we had some state-tracking character - // that wasn't consumed by this pass. - switch (stateChar) { - case '*': - re += star - hasMagic = true - break - case '?': - re += qmark - hasMagic = true - break - default: - re += '\\' + stateChar - break - } - self.debug('clearStateChar %j %j', stateChar, re) - stateChar = false - } - } +/***/ }), +/* 101 */ +/***/ (function(module, exports) { - for (var i = 0, len = pattern.length, c - ; (i < len) && (c = pattern.charAt(i)) - ; i++) { - this.debug('%s\t%s %s %j', pattern, i, re, c) +// IE 8- don't enum bug keys +module.exports = ( + 'constructor,hasOwnProperty,isPrototypeOf,propertyIsEnumerable,toLocaleString,toString,valueOf' +).split(','); - // skip over any that are escaped. - if (escaping && reSpecials[c]) { - re += '\\' + c - escaping = false - continue - } - switch (c) { - case '/': - // completely not allowed, even escaped. - // Should already be path-split by now. - return false +/***/ }), +/* 102 */ +/***/ (function(module, exports, __webpack_require__) { - case '\\': - clearStateChar() - escaping = true - continue +var document = __webpack_require__(11).document; +module.exports = document && document.documentElement; - // the various stateChar values - // for the "extglob" stuff. - case '?': - case '*': - case '+': - case '@': - case '!': - this.debug('%s\t%s %s %j <-- stateChar', pattern, i, re, c) - // all of those are literals inside a class, except that - // the glob [!a] means [^a] in regexp - if (inClass) { - this.debug(' in class') - if (c === '!' && i === classStart + 1) c = '^' - re += c - continue - } +/***/ }), +/* 103 */ +/***/ (function(module, exports, __webpack_require__) { - // if we already have a stateChar, then it means - // that there was something like ** or +? in there. - // Handle the stateChar, then proceed with this one. - self.debug('call clearStateChar %j', stateChar) - clearStateChar() - stateChar = c - // if extglob is disabled, then +(asdf|foo) isn't a thing. - // just clear the statechar *now*, rather than even diving into - // the patternList stuff. - if (options.noext) clearStateChar() - continue +"use strict"; - case '(': - if (inClass) { - re += '(' - continue - } +var LIBRARY = __webpack_require__(69); +var $export = __webpack_require__(41); +var redefine = __webpack_require__(197); +var hide = __webpack_require__(31); +var Iterators = __webpack_require__(35); +var $iterCreate = __webpack_require__(188); +var setToStringTag = __webpack_require__(71); +var getPrototypeOf = __webpack_require__(194); +var ITERATOR = __webpack_require__(13)('iterator'); +var BUGGY = !([].keys && 'next' in [].keys()); // Safari has buggy iterators w/o `next` +var FF_ITERATOR = '@@iterator'; +var KEYS = 'keys'; +var VALUES = 'values'; - if (!stateChar) { - re += '\\(' - continue - } +var returnThis = function () { return this; }; - patternListStack.push({ - type: stateChar, - start: i - 1, - reStart: re.length, - open: plTypes[stateChar].open, - close: plTypes[stateChar].close - }) - // negation is (?:(?!js)[^/]*) - re += stateChar === '!' ? '(?:(?!(?:' : '(?:' - this.debug('plType %j %j', stateChar, re) - stateChar = false - continue +module.exports = function (Base, NAME, Constructor, next, DEFAULT, IS_SET, FORCED) { + $iterCreate(Constructor, NAME, next); + var getMethod = function (kind) { + if (!BUGGY && kind in proto) return proto[kind]; + switch (kind) { + case KEYS: return function keys() { return new Constructor(this, kind); }; + case VALUES: return function values() { return new Constructor(this, kind); }; + } return function entries() { return new Constructor(this, kind); }; + }; + var TAG = NAME + ' Iterator'; + var DEF_VALUES = DEFAULT == VALUES; + var VALUES_BUG = false; + var proto = Base.prototype; + var $native = proto[ITERATOR] || proto[FF_ITERATOR] || DEFAULT && proto[DEFAULT]; + var $default = $native || getMethod(DEFAULT); + var $entries = DEFAULT ? !DEF_VALUES ? $default : getMethod('entries') : undefined; + var $anyNative = NAME == 'Array' ? proto.entries || $native : $native; + var methods, key, IteratorPrototype; + // Fix native + if ($anyNative) { + IteratorPrototype = getPrototypeOf($anyNative.call(new Base())); + if (IteratorPrototype !== Object.prototype && IteratorPrototype.next) { + // Set @@toStringTag to native iterators + setToStringTag(IteratorPrototype, TAG, true); + // fix for some old engines + if (!LIBRARY && typeof IteratorPrototype[ITERATOR] != 'function') hide(IteratorPrototype, ITERATOR, returnThis); + } + } + // fix Array#{values, @@iterator}.name in V8 / FF + if (DEF_VALUES && $native && $native.name !== VALUES) { + VALUES_BUG = true; + $default = function values() { return $native.call(this); }; + } + // Define iterator + if ((!LIBRARY || FORCED) && (BUGGY || VALUES_BUG || !proto[ITERATOR])) { + hide(proto, ITERATOR, $default); + } + // Plug for library + Iterators[NAME] = $default; + Iterators[TAG] = returnThis; + if (DEFAULT) { + methods = { + values: DEF_VALUES ? $default : getMethod(VALUES), + keys: IS_SET ? $default : getMethod(KEYS), + entries: $entries + }; + if (FORCED) for (key in methods) { + if (!(key in proto)) redefine(proto, key, methods[key]); + } else $export($export.P + $export.F * (BUGGY || VALUES_BUG), NAME, methods); + } + return methods; +}; - case ')': - if (inClass || !patternListStack.length) { - re += '\\)' - continue - } - clearStateChar() - hasMagic = true - var pl = patternListStack.pop() - // negation is (?:(?!js)[^/]*) - // The others are (?:) - re += pl.close - if (pl.type === '!') { - negativeLists.push(pl) - } - pl.reEnd = re.length - continue +/***/ }), +/* 104 */ +/***/ (function(module, exports) { - case '|': - if (inClass || !patternListStack.length || escaping) { - re += '\\|' - escaping = false - continue - } +module.exports = function (exec) { + try { + return { e: false, v: exec() }; + } catch (e) { + return { e: true, v: e }; + } +}; - clearStateChar() - re += '|' - continue - // these are mostly the same in regexp and glob - case '[': - // swallow any state-tracking char before the [ - clearStateChar() +/***/ }), +/* 105 */ +/***/ (function(module, exports, __webpack_require__) { - if (inClass) { - re += '\\' + c - continue - } +var anObject = __webpack_require__(27); +var isObject = __webpack_require__(34); +var newPromiseCapability = __webpack_require__(70); - inClass = true - classStart = i - reClassStart = re.length - re += c - continue +module.exports = function (C, x) { + anObject(C); + if (isObject(x) && x.constructor === C) return x; + var promiseCapability = newPromiseCapability.f(C); + var resolve = promiseCapability.resolve; + resolve(x); + return promiseCapability.promise; +}; - case ']': - // a right bracket shall lose its special - // meaning and represent itself in - // a bracket expression if it occurs - // first in the list. -- POSIX.2 2.8.3.2 - if (i === classStart + 1 || !inClass) { - re += '\\' + c - escaping = false - continue - } - // handle the case where we left a class open. - // "[z-a]" is valid, equivalent to "\[z-a\]" - if (inClass) { - // split where the last [ was, make sure we don't have - // an invalid re. if so, re-walk the contents of the - // would-be class to re-translate any characters that - // were passed through as-is - // TODO: It would probably be faster to determine this - // without a try/catch and a new RegExp, but it's tricky - // to do safely. For now, this is safe and works. - var cs = pattern.substring(classStart + 1, i) - try { - RegExp('[' + cs + ']') - } catch (er) { - // not a valid class! - var sp = this.parse(cs, SUBPARSE) - re = re.substr(0, reClassStart) + '\\[' + sp[0] + '\\]' - hasMagic = hasMagic || sp[1] - inClass = false - continue - } - } +/***/ }), +/* 106 */ +/***/ (function(module, exports) { - // finish up the class. - hasMagic = true - inClass = false - re += c - continue +module.exports = function (bitmap, value) { + return { + enumerable: !(bitmap & 1), + configurable: !(bitmap & 2), + writable: !(bitmap & 4), + value: value + }; +}; - default: - // swallow any state char that wasn't consumed - clearStateChar() - if (escaping) { - // no need - escaping = false - } else if (reSpecials[c] - && !(c === '^' && inClass)) { - re += '\\' - } +/***/ }), +/* 107 */ +/***/ (function(module, exports, __webpack_require__) { - re += c +var core = __webpack_require__(23); +var global = __webpack_require__(11); +var SHARED = '__core-js_shared__'; +var store = global[SHARED] || (global[SHARED] = {}); - } // switch - } // for +(module.exports = function (key, value) { + return store[key] || (store[key] = value !== undefined ? value : {}); +})('versions', []).push({ + version: core.version, + mode: __webpack_require__(69) ? 'pure' : 'global', + copyright: '© 2018 Denis Pushkarev (zloirock.ru)' +}); - // handle the case where we left a class open. - // "[abc" is valid, equivalent to "\[abc" - if (inClass) { - // split where the last [ was, and escape it - // this is a huge pita. We now have to re-walk - // the contents of the would-be class to re-translate - // any characters that were passed through as-is - cs = pattern.substr(classStart + 1) - sp = this.parse(cs, SUBPARSE) - re = re.substr(0, reClassStart) + '\\[' + sp[0] - hasMagic = hasMagic || sp[1] - } - // handle the case where we had a +( thing at the *end* - // of the pattern. - // each pattern list stack adds 3 chars, and we need to go through - // and escape any | chars that were passed through as-is for the regexp. - // Go through and escape them, taking care not to double-escape any - // | chars that were already escaped. - for (pl = patternListStack.pop(); pl; pl = patternListStack.pop()) { - var tail = re.slice(pl.reStart + pl.open.length) - this.debug('setting tail', re, pl) - // maybe some even number of \, then maybe 1 \, followed by a | - tail = tail.replace(/((?:\\{2}){0,64})(\\?)\|/g, function (_, $1, $2) { - if (!$2) { - // the | isn't already escaped, so escape it. - $2 = '\\' - } +/***/ }), +/* 108 */ +/***/ (function(module, exports, __webpack_require__) { - // need to escape all those slashes *again*, without escaping the - // one that we need for escaping the | character. As it works out, - // escaping an even number of slashes can be done by simply repeating - // it exactly after itself. That's why this trick works. - // - // I am sorry that you have to see this. - return $1 + $1 + $2 + '|' - }) +// 7.3.20 SpeciesConstructor(O, defaultConstructor) +var anObject = __webpack_require__(27); +var aFunction = __webpack_require__(46); +var SPECIES = __webpack_require__(13)('species'); +module.exports = function (O, D) { + var C = anObject(O).constructor; + var S; + return C === undefined || (S = anObject(C)[SPECIES]) == undefined ? D : aFunction(S); +}; - this.debug('tail=%j\n %s', tail, tail, pl, re) - var t = pl.type === '*' ? star - : pl.type === '?' ? qmark - : '\\' + pl.type - hasMagic = true - re = re.slice(0, pl.reStart) + t + '\\(' + tail - } +/***/ }), +/* 109 */ +/***/ (function(module, exports, __webpack_require__) { - // handle trailing things that only matter at the very end. - clearStateChar() - if (escaping) { - // trailing \\ - re += '\\\\' +var ctx = __webpack_require__(48); +var invoke = __webpack_require__(185); +var html = __webpack_require__(102); +var cel = __webpack_require__(68); +var global = __webpack_require__(11); +var process = global.process; +var setTask = global.setImmediate; +var clearTask = global.clearImmediate; +var MessageChannel = global.MessageChannel; +var Dispatch = global.Dispatch; +var counter = 0; +var queue = {}; +var ONREADYSTATECHANGE = 'onreadystatechange'; +var defer, channel, port; +var run = function () { + var id = +this; + // eslint-disable-next-line no-prototype-builtins + if (queue.hasOwnProperty(id)) { + var fn = queue[id]; + delete queue[id]; + fn(); } - - // only need to apply the nodot start if the re starts with - // something that could conceivably capture a dot - var addPatternStart = false - switch (re.charAt(0)) { - case '.': - case '[': - case '(': addPatternStart = true +}; +var listener = function (event) { + run.call(event.data); +}; +// Node.js 0.9+ & IE10+ has setImmediate, otherwise: +if (!setTask || !clearTask) { + setTask = function setImmediate(fn) { + var args = []; + var i = 1; + while (arguments.length > i) args.push(arguments[i++]); + queue[++counter] = function () { + // eslint-disable-next-line no-new-func + invoke(typeof fn == 'function' ? fn : Function(fn), args); + }; + defer(counter); + return counter; + }; + clearTask = function clearImmediate(id) { + delete queue[id]; + }; + // Node.js 0.8- + if (__webpack_require__(47)(process) == 'process') { + defer = function (id) { + process.nextTick(ctx(run, id, 1)); + }; + // Sphere (JS game engine) Dispatch API + } else if (Dispatch && Dispatch.now) { + defer = function (id) { + Dispatch.now(ctx(run, id, 1)); + }; + // Browsers with MessageChannel, includes WebWorkers + } else if (MessageChannel) { + channel = new MessageChannel(); + port = channel.port2; + channel.port1.onmessage = listener; + defer = ctx(port.postMessage, port, 1); + // Browsers with postMessage, skip WebWorkers + // IE8 has postMessage, but it's sync & typeof its postMessage is 'object' + } else if (global.addEventListener && typeof postMessage == 'function' && !global.importScripts) { + defer = function (id) { + global.postMessage(id + '', '*'); + }; + global.addEventListener('message', listener, false); + // IE8- + } else if (ONREADYSTATECHANGE in cel('script')) { + defer = function (id) { + html.appendChild(cel('script'))[ONREADYSTATECHANGE] = function () { + html.removeChild(this); + run.call(id); + }; + }; + // Rest old browsers + } else { + defer = function (id) { + setTimeout(ctx(run, id, 1), 0); + }; } +} +module.exports = { + set: setTask, + clear: clearTask +}; - // Hack to work around lack of negative lookbehind in JS - // A pattern like: *.!(x).!(y|z) needs to ensure that a name - // like 'a.xyz.yz' doesn't match. So, the first negative - // lookahead, has to look ALL the way ahead, to the end of - // the pattern. - for (var n = negativeLists.length - 1; n > -1; n--) { - var nl = negativeLists[n] - - var nlBefore = re.slice(0, nl.reStart) - var nlFirst = re.slice(nl.reStart, nl.reEnd - 8) - var nlLast = re.slice(nl.reEnd - 8, nl.reEnd) - var nlAfter = re.slice(nl.reEnd) - - nlLast += nlAfter - // Handle nested stuff like *(*.js|!(*.json)), where open parens - // mean that we should *not* include the ) in the bit that is considered - // "after" the negated section. - var openParensBefore = nlBefore.split('(').length - 1 - var cleanAfter = nlAfter - for (i = 0; i < openParensBefore; i++) { - cleanAfter = cleanAfter.replace(/\)[+*?]?/, '') - } - nlAfter = cleanAfter +/***/ }), +/* 110 */ +/***/ (function(module, exports, __webpack_require__) { - var dollar = '' - if (nlAfter === '' && isSub !== SUBPARSE) { - dollar = '$' - } - var newRe = nlBefore + nlFirst + nlAfter + dollar + nlLast - re = newRe - } +// 7.1.15 ToLength +var toInteger = __webpack_require__(73); +var min = Math.min; +module.exports = function (it) { + return it > 0 ? min(toInteger(it), 0x1fffffffffffff) : 0; // pow(2, 53) - 1 == 9007199254740991 +}; - // if the re is not "" at this point, then we need to make sure - // it doesn't match against an empty path part. - // Otherwise a/* will match a/, which it should not. - if (re !== '' && hasMagic) { - re = '(?=.)' + re - } - if (addPatternStart) { - re = patternStart + re - } +/***/ }), +/* 111 */ +/***/ (function(module, exports) { - // parsing just a piece of a larger pattern. - if (isSub === SUBPARSE) { - return [re, hasMagic] - } +var id = 0; +var px = Math.random(); +module.exports = function (key) { + return 'Symbol('.concat(key === undefined ? '' : key, ')_', (++id + px).toString(36)); +}; - // skip the regexp for non-magical patterns - // unescape anything in it, though, so that it'll be - // an exact match against a file etc. - if (!hasMagic) { - return globUnescape(pattern) - } - var flags = options.nocase ? 'i' : '' - try { - var regExp = new RegExp('^' + re + '$', flags) - } catch (er) { - // If it was an invalid regular expression, then it can't match - // anything. This trick looks for a character after the end of - // the string, which is of course impossible, except in multi-line - // mode, but it's not a /m regex. - return new RegExp('$.') - } +/***/ }), +/* 112 */ +/***/ (function(module, exports, __webpack_require__) { - regExp._glob = pattern - regExp._src = re - return regExp -} +/** + * This is the common logic for both the Node.js and web browser + * implementations of `debug()`. + * + * Expose `debug()` as the module. + */ -minimatch.makeRe = function (pattern, options) { - return new Minimatch(pattern, options || {}).makeRe() -} +exports = module.exports = createDebug.debug = createDebug['default'] = createDebug; +exports.coerce = coerce; +exports.disable = disable; +exports.enable = enable; +exports.enabled = enabled; +exports.humanize = __webpack_require__(229); -Minimatch.prototype.makeRe = makeRe -function makeRe () { - if (this.regexp || this.regexp === false) return this.regexp +/** + * Active `debug` instances. + */ +exports.instances = []; - // at this point, this.set is a 2d array of partial - // pattern strings, or "**". - // - // It's better to use .match(). This function shouldn't - // be used, really, but it's pretty convenient sometimes, - // when you just want to work with a regex. - var set = this.set +/** + * The currently active debug mode names, and names to skip. + */ - if (!set.length) { - this.regexp = false - return this.regexp - } - var options = this.options +exports.names = []; +exports.skips = []; - var twoStar = options.noglobstar ? star - : options.dot ? twoStarDot - : twoStarNoDot - var flags = options.nocase ? 'i' : '' +/** + * Map of special "%n" handling functions, for the debug "format" argument. + * + * Valid key names are a single, lower or upper-case letter, i.e. "n" and "N". + */ - var re = set.map(function (pattern) { - return pattern.map(function (p) { - return (p === GLOBSTAR) ? twoStar - : (typeof p === 'string') ? regExpEscape(p) - : p._src - }).join('\\\/') - }).join('|') +exports.formatters = {}; - // must match entire pattern - // ending in a * or ** will make it less strict. - re = '^(?:' + re + ')$' +/** + * Select a color. + * @param {String} namespace + * @return {Number} + * @api private + */ - // can match anything, as long as it's not this. - if (this.negate) re = '^(?!' + re + ').*$' +function selectColor(namespace) { + var hash = 0, i; - try { - this.regexp = new RegExp(re, flags) - } catch (ex) { - this.regexp = false + for (i in namespace) { + hash = ((hash << 5) - hash) + namespace.charCodeAt(i); + hash |= 0; // Convert to 32bit integer } - return this.regexp -} -minimatch.match = function (list, pattern, options) { - options = options || {} - var mm = new Minimatch(pattern, options) - list = list.filter(function (f) { - return mm.match(f) - }) - if (mm.options.nonull && !list.length) { - list.push(pattern) - } - return list + return exports.colors[Math.abs(hash) % exports.colors.length]; } -Minimatch.prototype.match = match -function match (f, partial) { - this.debug('match', f, this.pattern) - // short-circuit in the case of busted things. - // comments, etc. - if (this.comment) return false - if (this.empty) return f === '' +/** + * Create a debugger with the given `namespace`. + * + * @param {String} namespace + * @return {Function} + * @api public + */ - if (f === '/' && partial) return true +function createDebug(namespace) { - var options = this.options + var prevTime; - // windows: need to use /, not \ - if (path.sep !== '/') { - f = f.split(path.sep).join('/') - } + function debug() { + // disabled? + if (!debug.enabled) return; - // treat the test path as a set of pathparts. - f = f.split(slashSplit) - this.debug(this.pattern, 'split', f) + var self = debug; - // just ONE of the pattern sets in this.set needs to match - // in order for it to be valid. If negating, then just one - // match means that we have failed. - // Either way, return on the first hit. + // set `diff` timestamp + var curr = +new Date(); + var ms = curr - (prevTime || curr); + self.diff = ms; + self.prev = prevTime; + self.curr = curr; + prevTime = curr; - var set = this.set - this.debug(this.pattern, 'set', set) + // turn the `arguments` into a proper Array + var args = new Array(arguments.length); + for (var i = 0; i < args.length; i++) { + args[i] = arguments[i]; + } - // Find the basename of the path by looking for the last non-empty segment - var filename - var i - for (i = f.length - 1; i >= 0; i--) { - filename = f[i] - if (filename) break - } + args[0] = exports.coerce(args[0]); - for (i = 0; i < set.length; i++) { - var pattern = set[i] - var file = f - if (options.matchBase && pattern.length === 1) { - file = [filename] - } - var hit = this.matchOne(file, pattern, partial) - if (hit) { - if (options.flipNegate) return true - return !this.negate + if ('string' !== typeof args[0]) { + // anything else let's inspect with %O + args.unshift('%O'); } - } - // didn't get any hits. this is success if it's a negative - // pattern, failure otherwise. - if (options.flipNegate) return false - return this.negate -} - -// set partial to true to test if, for example, -// "/a/b" matches the start of "/*/b/*/d" -// Partial means, if you run out of file before you run -// out of pattern, then that's fine, as long as all -// the parts match. -Minimatch.prototype.matchOne = function (file, pattern, partial) { - var options = this.options + // apply any `formatters` transformations + var index = 0; + args[0] = args[0].replace(/%([a-zA-Z%])/g, function(match, format) { + // if we encounter an escaped % then don't increase the array index + if (match === '%%') return match; + index++; + var formatter = exports.formatters[format]; + if ('function' === typeof formatter) { + var val = args[index]; + match = formatter.call(self, val); - this.debug('matchOne', - { 'this': this, file: file, pattern: pattern }) + // now we need to remove `args[index]` since it's inlined in the `format` + args.splice(index, 1); + index--; + } + return match; + }); - this.debug('matchOne', file.length, pattern.length) + // apply env-specific formatting (colors, etc.) + exports.formatArgs.call(self, args); - for (var fi = 0, - pi = 0, - fl = file.length, - pl = pattern.length - ; (fi < fl) && (pi < pl) - ; fi++, pi++) { - this.debug('matchOne loop') - var p = pattern[pi] - var f = file[fi] + var logFn = debug.log || exports.log || console.log.bind(console); + logFn.apply(self, args); + } - this.debug(pattern, p, f) + debug.namespace = namespace; + debug.enabled = exports.enabled(namespace); + debug.useColors = exports.useColors(); + debug.color = selectColor(namespace); + debug.destroy = destroy; - // should be impossible. - // some invalid regexp stuff in the set. - if (p === false) return false + // env-specific initialization logic for debug instances + if ('function' === typeof exports.init) { + exports.init(debug); + } - if (p === GLOBSTAR) { - this.debug('GLOBSTAR', [pattern, p, f]) + exports.instances.push(debug); - // "**" - // a/**/b/**/c would match the following: - // a/b/x/y/z/c - // a/x/y/z/b/c - // a/b/x/b/x/c - // a/b/c - // To do this, take the rest of the pattern after - // the **, and see if it would match the file remainder. - // If so, return success. - // If not, the ** "swallows" a segment, and try again. - // This is recursively awful. - // - // a/**/b/**/c matching a/b/x/y/z/c - // - a matches a - // - doublestar - // - matchOne(b/x/y/z/c, b/**/c) - // - b matches b - // - doublestar - // - matchOne(x/y/z/c, c) -> no - // - matchOne(y/z/c, c) -> no - // - matchOne(z/c, c) -> no - // - matchOne(c, c) yes, hit - var fr = fi - var pr = pi + 1 - if (pr === pl) { - this.debug('** at the end') - // a ** at the end will just swallow the rest. - // We have found a match. - // however, it will not swallow /.x, unless - // options.dot is set. - // . and .. are *never* matched by **, for explosively - // exponential reasons. - for (; fi < fl; fi++) { - if (file[fi] === '.' || file[fi] === '..' || - (!options.dot && file[fi].charAt(0) === '.')) return false - } - return true - } + return debug; +} - // ok, let's see if we can swallow whatever we can. - while (fr < fl) { - var swallowee = file[fr] +function destroy () { + var index = exports.instances.indexOf(this); + if (index !== -1) { + exports.instances.splice(index, 1); + return true; + } else { + return false; + } +} - this.debug('\nglobstar while', file, fr, pattern, pr, swallowee) +/** + * Enables a debug mode by namespaces. This can include modes + * separated by a colon and wildcards. + * + * @param {String} namespaces + * @api public + */ - // XXX remove this slice. Just pass the start index. - if (this.matchOne(file.slice(fr), pattern.slice(pr), partial)) { - this.debug('globstar found match!', fr, fl, swallowee) - // found a match. - return true - } else { - // can't swallow "." or ".." ever. - // can only swallow ".foo" when explicitly asked. - if (swallowee === '.' || swallowee === '..' || - (!options.dot && swallowee.charAt(0) === '.')) { - this.debug('dot detected!', file, fr, pattern, pr) - break - } +function enable(namespaces) { + exports.save(namespaces); - // ** swallows a segment, and continue. - this.debug('globstar swallow a segment, and continue') - fr++ - } - } + exports.names = []; + exports.skips = []; - // no match was found. - // However, in partial mode, we can't say this is necessarily over. - // If there's more *pattern* left, then - if (partial) { - // ran out of file - this.debug('\n>>> no match, partial?', file, fr, pattern, pr) - if (fr === fl) return true - } - return false - } + var i; + var split = (typeof namespaces === 'string' ? namespaces : '').split(/[\s,]+/); + var len = split.length; - // something other than ** - // non-magic patterns just have to match exactly - // patterns with magic have been turned into regexps. - var hit - if (typeof p === 'string') { - if (options.nocase) { - hit = f.toLowerCase() === p.toLowerCase() - } else { - hit = f === p - } - this.debug('string match', p, f, hit) + for (i = 0; i < len; i++) { + if (!split[i]) continue; // ignore empty strings + namespaces = split[i].replace(/\*/g, '.*?'); + if (namespaces[0] === '-') { + exports.skips.push(new RegExp('^' + namespaces.substr(1) + '$')); } else { - hit = f.match(p) - this.debug('pattern match', p, f, hit) + exports.names.push(new RegExp('^' + namespaces + '$')); } + } - if (!hit) return false + for (i = 0; i < exports.instances.length; i++) { + var instance = exports.instances[i]; + instance.enabled = exports.enabled(instance.namespace); } +} - // Note: ending in / means that we'll get a final "" - // at the end of the pattern. This can only match a - // corresponding "" at the end of the file. - // If the file ends in /, then it can only match a - // a pattern that ends in /, unless the pattern just - // doesn't have any more for it. But, a/b/ should *not* - // match "a/b/*", even though "" matches against the - // [^/]*? pattern, except in partial mode, where it might - // simply not be reached yet. - // However, a/b/ should still satisfy a/* +/** + * Disable debug output. + * + * @api public + */ - // now either we fell off the end of the pattern, or we're done. - if (fi === fl && pi === pl) { - // ran out of pattern and filename at the same time. - // an exact hit! - return true - } else if (fi === fl) { - // ran out of file, but still had pattern left. - // this is ok if we're doing the match as part of - // a glob fs traversal. - return partial - } else if (pi === pl) { - // ran out of pattern, still have file left. - // this is only acceptable if we're on the very last - // empty segment of a file with a trailing slash. - // a/* should match a/b/ - var emptyFileEnd = (fi === fl - 1) && (file[fi] === '') - return emptyFileEnd - } - - // should be unreachable. - throw new Error('wtf?') +function disable() { + exports.enable(''); } -// replace stuff like \* with * -function globUnescape (s) { - return s.replace(/\\(.)/g, '$1') +/** + * Returns true if the given mode name is enabled, false otherwise. + * + * @param {String} name + * @return {Boolean} + * @api public + */ + +function enabled(name) { + if (name[name.length - 1] === '*') { + return true; + } + var i, len; + for (i = 0, len = exports.skips.length; i < len; i++) { + if (exports.skips[i].test(name)) { + return false; + } + } + for (i = 0, len = exports.names.length; i < len; i++) { + if (exports.names[i].test(name)) { + return true; + } + } + return false; } -function regExpEscape (s) { - return s.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&') +/** + * Coerce `val`. + * + * @param {Mixed} val + * @return {Mixed} + * @api private + */ + +function coerce(val) { + if (val instanceof Error) return val.stack || val.message; + return val; } /***/ }), -/* 61 */ +/* 113 */, +/* 114 */ /***/ (function(module, exports, __webpack_require__) { -var wrappy = __webpack_require__(123) -module.exports = wrappy(once) -module.exports.strict = wrappy(onceStrict) +module.exports = realpath +realpath.realpath = realpath +realpath.sync = realpathSync +realpath.realpathSync = realpathSync +realpath.monkeypatch = monkeypatch +realpath.unmonkeypatch = unmonkeypatch -once.proto = once(function () { - Object.defineProperty(Function.prototype, 'once', { - value: function () { - return once(this) - }, - configurable: true - }) +var fs = __webpack_require__(3) +var origRealpath = fs.realpath +var origRealpathSync = fs.realpathSync - Object.defineProperty(Function.prototype, 'onceStrict', { - value: function () { - return onceStrict(this) - }, - configurable: true - }) -}) +var version = process.version +var ok = /^v[0-5]\./.test(version) +var old = __webpack_require__(217) -function once (fn) { - var f = function () { - if (f.called) return f.value - f.called = true - return f.value = fn.apply(this, arguments) - } - f.called = false - return f +function newError (er) { + return er && er.syscall === 'realpath' && ( + er.code === 'ELOOP' || + er.code === 'ENOMEM' || + er.code === 'ENAMETOOLONG' + ) } -function onceStrict (fn) { - var f = function () { - if (f.called) - throw new Error(f.onceError) - f.called = true - return f.value = fn.apply(this, arguments) +function realpath (p, cache, cb) { + if (ok) { + return origRealpath(p, cache, cb) } - var name = fn.name || 'Function wrapped with `once`' - f.onceError = name + " shouldn't be called more than once" - f.called = false - return f -} + if (typeof cache === 'function') { + cb = cache + cache = null + } + origRealpath(p, cache, function (er, result) { + if (newError(er)) { + old.realpath(p, cache, cb) + } else { + cb(er, result) + } + }) +} -/***/ }), -/* 62 */, -/* 63 */ -/***/ (function(module, exports) { +function realpathSync (p, cache) { + if (ok) { + return origRealpathSync(p, cache) + } -module.exports = __webpack_require__(285); + try { + return origRealpathSync(p, cache) + } catch (er) { + if (newError(er)) { + return old.realpathSync(p, cache) + } else { + throw er + } + } +} -/***/ }), -/* 64 */, -/* 65 */, -/* 66 */, -/* 67 */ -/***/ (function(module, exports) { +function monkeypatch () { + fs.realpath = realpath + fs.realpathSync = realpathSync +} -// 7.2.1 RequireObjectCoercible(argument) -module.exports = function (it) { - if (it == undefined) throw TypeError("Can't call method on " + it); - return it; -}; +function unmonkeypatch () { + fs.realpath = origRealpath + fs.realpathSync = origRealpathSync +} /***/ }), -/* 68 */ +/* 115 */ /***/ (function(module, exports, __webpack_require__) { -var isObject = __webpack_require__(34); -var document = __webpack_require__(11).document; -// typeof document.createElement is 'object' in old IE -var is = isObject(document) && isObject(document.createElement); -module.exports = function (it) { - return is ? document.createElement(it) : {}; -}; - +exports.alphasort = alphasort +exports.alphasorti = alphasorti +exports.setopts = setopts +exports.ownProp = ownProp +exports.makeAbs = makeAbs +exports.finish = finish +exports.mark = mark +exports.isIgnored = isIgnored +exports.childrenIgnored = childrenIgnored -/***/ }), -/* 69 */ -/***/ (function(module, exports) { +function ownProp (obj, field) { + return Object.prototype.hasOwnProperty.call(obj, field) +} -module.exports = true; +var path = __webpack_require__(0) +var minimatch = __webpack_require__(60) +var isAbsolute = __webpack_require__(76) +var Minimatch = minimatch.Minimatch +function alphasorti (a, b) { + return a.toLowerCase().localeCompare(b.toLowerCase()) +} -/***/ }), -/* 70 */ -/***/ (function(module, exports, __webpack_require__) { +function alphasort (a, b) { + return a.localeCompare(b) +} -"use strict"; +function setupIgnores (self, options) { + self.ignore = options.ignore || [] -// 25.4.1.5 NewPromiseCapability(C) -var aFunction = __webpack_require__(46); + if (!Array.isArray(self.ignore)) + self.ignore = [self.ignore] -function PromiseCapability(C) { - var resolve, reject; - this.promise = new C(function ($$resolve, $$reject) { - if (resolve !== undefined || reject !== undefined) throw TypeError('Bad Promise constructor'); - resolve = $$resolve; - reject = $$reject; - }); - this.resolve = aFunction(resolve); - this.reject = aFunction(reject); + if (self.ignore.length) { + self.ignore = self.ignore.map(ignoreMap) + } } -module.exports.f = function (C) { - return new PromiseCapability(C); -}; +// ignore patterns are always in dot:true mode. +function ignoreMap (pattern) { + var gmatcher = null + if (pattern.slice(-3) === '/**') { + var gpattern = pattern.replace(/(\/\*\*)+$/, '') + gmatcher = new Minimatch(gpattern, { dot: true }) + } + return { + matcher: new Minimatch(pattern, { dot: true }), + gmatcher: gmatcher + } +} -/***/ }), -/* 71 */ -/***/ (function(module, exports, __webpack_require__) { +function setopts (self, pattern, options) { + if (!options) + options = {} -var def = __webpack_require__(50).f; -var has = __webpack_require__(49); -var TAG = __webpack_require__(13)('toStringTag'); + // base-matching: just use globstar for that. + if (options.matchBase && -1 === pattern.indexOf("/")) { + if (options.noglobstar) { + throw new Error("base matching requires globstar") + } + pattern = "**/" + pattern + } -module.exports = function (it, tag, stat) { - if (it && !has(it = stat ? it : it.prototype, TAG)) def(it, TAG, { configurable: true, value: tag }); -}; + self.silent = !!options.silent + self.pattern = pattern + self.strict = options.strict !== false + self.realpath = !!options.realpath + self.realpathCache = options.realpathCache || Object.create(null) + self.follow = !!options.follow + self.dot = !!options.dot + self.mark = !!options.mark + self.nodir = !!options.nodir + if (self.nodir) + self.mark = true + self.sync = !!options.sync + self.nounique = !!options.nounique + self.nonull = !!options.nonull + self.nosort = !!options.nosort + self.nocase = !!options.nocase + self.stat = !!options.stat + self.noprocess = !!options.noprocess + self.absolute = !!options.absolute + self.maxLength = options.maxLength || Infinity + self.cache = options.cache || Object.create(null) + self.statCache = options.statCache || Object.create(null) + self.symlinks = options.symlinks || Object.create(null) -/***/ }), -/* 72 */ -/***/ (function(module, exports, __webpack_require__) { + setupIgnores(self, options) -var shared = __webpack_require__(107)('keys'); -var uid = __webpack_require__(111); -module.exports = function (key) { - return shared[key] || (shared[key] = uid(key)); -}; + self.changedCwd = false + var cwd = process.cwd() + if (!ownProp(options, "cwd")) + self.cwd = cwd + else { + self.cwd = path.resolve(options.cwd) + self.changedCwd = self.cwd !== cwd + } + self.root = options.root || path.resolve(self.cwd, "/") + self.root = path.resolve(self.root) + if (process.platform === "win32") + self.root = self.root.replace(/\\/g, "/") -/***/ }), -/* 73 */ -/***/ (function(module, exports) { + // TODO: is an absolute `cwd` supposed to be resolved against `root`? + // e.g. { cwd: '/test', root: __dirname } === path.join(__dirname, '/test') + self.cwdAbs = isAbsolute(self.cwd) ? self.cwd : makeAbs(self, self.cwd) + if (process.platform === "win32") + self.cwdAbs = self.cwdAbs.replace(/\\/g, "/") + self.nomount = !!options.nomount -// 7.1.4 ToInteger -var ceil = Math.ceil; -var floor = Math.floor; -module.exports = function (it) { - return isNaN(it = +it) ? 0 : (it > 0 ? floor : ceil)(it); -}; + // disable comments and negation in Minimatch. + // Note that they are not supported in Glob itself anyway. + options.nonegate = true + options.nocomment = true + self.minimatch = new Minimatch(pattern, options) + self.options = self.minimatch.options +} -/***/ }), -/* 74 */ -/***/ (function(module, exports, __webpack_require__) { +function finish (self) { + var nou = self.nounique + var all = nou ? [] : Object.create(null) -// to indexed object, toObject with fallback for non-array-like ES3 strings -var IObject = __webpack_require__(131); -var defined = __webpack_require__(67); -module.exports = function (it) { - return IObject(defined(it)); -}; + for (var i = 0, l = self.matches.length; i < l; i ++) { + var matches = self.matches[i] + if (!matches || Object.keys(matches).length === 0) { + if (self.nonull) { + // do like the shell, and spit out the literal glob + var literal = self.minimatch.globSet[i] + if (nou) + all.push(literal) + else + all[literal] = true + } + } else { + // had matches + var m = Object.keys(matches) + if (nou) + all.push.apply(all, m) + else + m.forEach(function (m) { + all[m] = true + }) + } + } + if (!nou) + all = Object.keys(all) -/***/ }), -/* 75 */ -/***/ (function(module, exports, __webpack_require__) { + if (!self.nosort) + all = all.sort(self.nocase ? alphasorti : alphasort) -// Approach: -// -// 1. Get the minimatch set -// 2. For each pattern in the set, PROCESS(pattern, false) -// 3. Store matches per-set, then uniq them -// -// PROCESS(pattern, inGlobStar) -// Get the first [n] items from pattern that are all strings -// Join these together. This is PREFIX. -// If there is no more remaining, then stat(PREFIX) and -// add to matches if it succeeds. END. -// -// If inGlobStar and PREFIX is symlink and points to dir -// set ENTRIES = [] -// else readdir(PREFIX) as ENTRIES -// If fail, END -// -// with ENTRIES -// If pattern[n] is GLOBSTAR -// // handle the case where the globstar match is empty -// // by pruning it out, and testing the resulting pattern -// PROCESS(pattern[0..n] + pattern[n+1 .. $], false) -// // handle other cases. -// for ENTRY in ENTRIES (not dotfiles) -// // attach globstar + tail onto the entry -// // Mark that this entry is a globstar match -// PROCESS(pattern[0..n] + ENTRY + pattern[n .. $], true) -// -// else // not globstar -// for ENTRY in ENTRIES (not dotfiles, unless pattern[n] is dot) -// Test ENTRY against pattern[n] -// If fails, continue -// If passes, PROCESS(pattern[0..n] + item + pattern[n+1 .. $]) -// -// Caveat: -// Cache all stats and readdirs results to minimize syscall. Since all -// we ever care about is existence and directory-ness, we can just keep -// `true` for files, and [children,...] for directories, or `false` for -// things that don't exist. + // at *some* point we statted all of these + if (self.mark) { + for (var i = 0; i < all.length; i++) { + all[i] = self._mark(all[i]) + } + if (self.nodir) { + all = all.filter(function (e) { + var notDir = !(/\/$/.test(e)) + var c = self.cache[e] || self.cache[makeAbs(self, e)] + if (notDir && c) + notDir = c !== 'DIR' && !Array.isArray(c) + return notDir + }) + } + } -module.exports = glob + if (self.ignore.length) + all = all.filter(function(m) { + return !isIgnored(self, m) + }) -var fs = __webpack_require__(3) -var rp = __webpack_require__(114) -var minimatch = __webpack_require__(60) -var Minimatch = minimatch.Minimatch -var inherits = __webpack_require__(42) -var EE = __webpack_require__(54).EventEmitter -var path = __webpack_require__(0) -var assert = __webpack_require__(22) -var isAbsolute = __webpack_require__(76) -var globSync = __webpack_require__(218) -var common = __webpack_require__(115) -var alphasort = common.alphasort -var alphasorti = common.alphasorti -var setopts = common.setopts -var ownProp = common.ownProp -var inflight = __webpack_require__(223) -var util = __webpack_require__(2) -var childrenIgnored = common.childrenIgnored -var isIgnored = common.isIgnored + self.found = all +} -var once = __webpack_require__(61) +function mark (self, p) { + var abs = makeAbs(self, p) + var c = self.cache[abs] + var m = p + if (c) { + var isDir = c === 'DIR' || Array.isArray(c) + var slash = p.slice(-1) === '/' -function glob (pattern, options, cb) { - if (typeof options === 'function') cb = options, options = {} - if (!options) options = {} + if (isDir && !slash) + m += '/' + else if (!isDir && slash) + m = m.slice(0, -1) - if (options.sync) { - if (cb) - throw new TypeError('callback provided to sync glob') - return globSync(pattern, options) + if (m !== p) { + var mabs = makeAbs(self, m) + self.statCache[mabs] = self.statCache[abs] + self.cache[mabs] = self.cache[abs] + } } - return new Glob(pattern, options, cb) + return m } -glob.sync = globSync -var GlobSync = glob.GlobSync = globSync.GlobSync - -// old api surface -glob.glob = glob - -function extend (origin, add) { - if (add === null || typeof add !== 'object') { - return origin +// lotta situps... +function makeAbs (self, f) { + var abs = f + if (f.charAt(0) === '/') { + abs = path.join(self.root, f) + } else if (isAbsolute(f) || f === '') { + abs = f + } else if (self.changedCwd) { + abs = path.resolve(self.cwd, f) + } else { + abs = path.resolve(f) } - var keys = Object.keys(add) - var i = keys.length - while (i--) { - origin[keys[i]] = add[keys[i]] - } - return origin -} + if (process.platform === 'win32') + abs = abs.replace(/\\/g, '/') -glob.hasMagic = function (pattern, options_) { - var options = extend({}, options_) - options.noprocess = true + return abs +} - var g = new Glob(pattern, options) - var set = g.minimatch.set - if (!pattern) +// Return true, if pattern ends with globstar '**', for the accompanying parent directory. +// Ex:- If node_modules/** is the pattern, add 'node_modules' to ignore list along with it's contents +function isIgnored (self, path) { + if (!self.ignore.length) return false - if (set.length > 1) - return true - - for (var j = 0; j < set[0].length; j++) { - if (typeof set[0][j] !== 'string') - return true - } - - return false + return self.ignore.some(function(item) { + return item.matcher.match(path) || !!(item.gmatcher && item.gmatcher.match(path)) + }) } -glob.Glob = Glob -inherits(Glob, EE) -function Glob (pattern, options, cb) { - if (typeof options === 'function') { - cb = options - options = null - } - - if (options && options.sync) { - if (cb) - throw new TypeError('callback provided to sync glob') - return new GlobSync(pattern, options) - } - - if (!(this instanceof Glob)) - return new Glob(pattern, options, cb) +function childrenIgnored (self, path) { + if (!self.ignore.length) + return false - setopts(this, pattern, options) - this._didRealPath = false + return self.ignore.some(function(item) { + return !!(item.gmatcher && item.gmatcher.match(path)) + }) +} - // process each pattern in the minimatch set - var n = this.minimatch.set.length - // The matches are stored as {: true,...} so that - // duplicates are automagically pruned. - // Later, we do an Object.keys() on these. - // Keep them as a list so we can fill in when nonull is set. - this.matches = new Array(n) +/***/ }), +/* 116 */ +/***/ (function(module, exports, __webpack_require__) { - if (typeof cb === 'function') { - cb = once(cb) - this.on('error', cb) - this.on('end', function (matches) { - cb(null, matches) - }) - } +var path = __webpack_require__(0); +var fs = __webpack_require__(3); +var _0777 = parseInt('0777', 8); - var self = this - this._processing = 0 +module.exports = mkdirP.mkdirp = mkdirP.mkdirP = mkdirP; - this._emitQueue = [] - this._processQueue = [] - this.paused = false +function mkdirP (p, opts, f, made) { + if (typeof opts === 'function') { + f = opts; + opts = {}; + } + else if (!opts || typeof opts !== 'object') { + opts = { mode: opts }; + } + + var mode = opts.mode; + var xfs = opts.fs || fs; + + if (mode === undefined) { + mode = _0777 & (~process.umask()); + } + if (!made) made = null; + + var cb = f || function () {}; + p = path.resolve(p); + + xfs.mkdir(p, mode, function (er) { + if (!er) { + made = made || p; + return cb(null, made); + } + switch (er.code) { + case 'ENOENT': + mkdirP(path.dirname(p), opts, function (er, made) { + if (er) cb(er, made); + else mkdirP(p, opts, cb, made); + }); + break; - if (this.noprocess) - return this + // In the case of any other error, just see if there's a dir + // there already. If so, then hooray! If not, then something + // is borked. + default: + xfs.stat(p, function (er2, stat) { + // if the stat fails, then that's super weird. + // let the original error be the failure reason. + if (er2 || !stat.isDirectory()) cb(er, made) + else cb(null, made); + }); + break; + } + }); +} - if (n === 0) - return done() +mkdirP.sync = function sync (p, opts, made) { + if (!opts || typeof opts !== 'object') { + opts = { mode: opts }; + } + + var mode = opts.mode; + var xfs = opts.fs || fs; + + if (mode === undefined) { + mode = _0777 & (~process.umask()); + } + if (!made) made = null; - var sync = true - for (var i = 0; i < n; i ++) { - this._process(this.minimatch.set[i], i, false, done) - } - sync = false + p = path.resolve(p); - function done () { - --self._processing - if (self._processing <= 0) { - if (sync) { - process.nextTick(function () { - self._finish() - }) - } else { - self._finish() - } + try { + xfs.mkdirSync(p, mode); + made = made || p; } - } -} + catch (err0) { + switch (err0.code) { + case 'ENOENT' : + made = sync(path.dirname(p), opts, made); + sync(p, opts, made); + break; -Glob.prototype._finish = function () { - assert(this instanceof Glob) - if (this.aborted) - return + // In the case of any other error, just see if there's a dir + // there already. If so, then hooray! If not, then something + // is borked. + default: + var stat; + try { + stat = xfs.statSync(p); + } + catch (err1) { + throw err0; + } + if (!stat.isDirectory()) throw err0; + break; + } + } - if (this.realpath && !this._didRealpath) - return this._realpath() + return made; +}; - common.finish(this) - this.emit('end', this.found) -} -Glob.prototype._realpath = function () { - if (this._didRealpath) - return +/***/ }), +/* 117 */, +/* 118 */, +/* 119 */, +/* 120 */, +/* 121 */, +/* 122 */ +/***/ (function(module, exports, __webpack_require__) { - this._didRealpath = true +"use strict"; - var n = this.matches.length - if (n === 0) - return this._finish() +module.exports = x => { + if (typeof x !== 'string') { + throw new TypeError('Expected a string, got ' + typeof x); + } - var self = this - for (var i = 0; i < this.matches.length; i++) - this._realpathSet(i, next) + // Catches EFBBBF (UTF-8 BOM) because the buffer-to-string + // conversion translates it to FEFF (UTF-16 BOM) + if (x.charCodeAt(0) === 0xFEFF) { + return x.slice(1); + } - function next () { - if (--n === 0) - self._finish() - } -} + return x; +}; -Glob.prototype._realpathSet = function (index, cb) { - var matchset = this.matches[index] - if (!matchset) - return cb() - var found = Object.keys(matchset) - var self = this - var n = found.length +/***/ }), +/* 123 */ +/***/ (function(module, exports) { - if (n === 0) - return cb() +// Returns a wrapper function that returns a wrapped callback +// The wrapper function should do some stuff, and return a +// presumably different callback function. +// This makes sure that own properties are retained, so that +// decorations and such are not lost along the way. +module.exports = wrappy +function wrappy (fn, cb) { + if (fn && cb) return wrappy(fn)(cb) - var set = this.matches[index] = Object.create(null) - found.forEach(function (p, i) { - // If there's a problem with the stat, then it means that - // one or more of the links in the realpath couldn't be - // resolved. just return the abs value in that case. - p = self._makeAbs(p) - rp.realpath(p, self.realpathCache, function (er, real) { - if (!er) - set[real] = true - else if (er.syscall === 'stat') - set[p] = true - else - self.emit('error', er) // srsly wtf right here + if (typeof fn !== 'function') + throw new TypeError('need wrapper function') - if (--n === 0) { - self.matches[index] = set - cb() - } - }) + Object.keys(fn).forEach(function (k) { + wrapper[k] = fn[k] }) -} - -Glob.prototype._mark = function (p) { - return common.mark(this, p) -} - -Glob.prototype._makeAbs = function (f) { - return common.makeAbs(this, f) -} - -Glob.prototype.abort = function () { - this.aborted = true - this.emit('abort') -} -Glob.prototype.pause = function () { - if (!this.paused) { - this.paused = true - this.emit('pause') - } -} + return wrapper -Glob.prototype.resume = function () { - if (this.paused) { - this.emit('resume') - this.paused = false - if (this._emitQueue.length) { - var eq = this._emitQueue.slice(0) - this._emitQueue.length = 0 - for (var i = 0; i < eq.length; i ++) { - var e = eq[i] - this._emitMatch(e[0], e[1]) - } + function wrapper() { + var args = new Array(arguments.length) + for (var i = 0; i < args.length; i++) { + args[i] = arguments[i] } - if (this._processQueue.length) { - var pq = this._processQueue.slice(0) - this._processQueue.length = 0 - for (var i = 0; i < pq.length; i ++) { - var p = pq[i] - this._processing-- - this._process(p[0], p[1], p[2], p[3]) - } + var ret = fn.apply(this, args) + var cb = args[args.length-1] + if (typeof ret === 'function' && ret !== cb) { + Object.keys(cb).forEach(function (k) { + ret[k] = cb[k] + }) } + return ret } } -Glob.prototype._process = function (pattern, index, inGlobStar, cb) { - assert(this instanceof Glob) - assert(typeof cb === 'function') - if (this.aborted) - return +/***/ }), +/* 124 */, +/* 125 */, +/* 126 */, +/* 127 */, +/* 128 */, +/* 129 */, +/* 130 */, +/* 131 */ +/***/ (function(module, exports, __webpack_require__) { - this._processing++ - if (this.paused) { - this._processQueue.push([pattern, index, inGlobStar, cb]) - return - } +// fallback for non-array-like ES3 and non-enumerable old V8 strings +var cof = __webpack_require__(47); +// eslint-disable-next-line no-prototype-builtins +module.exports = Object('z').propertyIsEnumerable(0) ? Object : function (it) { + return cof(it) == 'String' ? it.split('') : Object(it); +}; - //console.error('PROCESS %d', this._processing, pattern) - // Get the first [n] parts of pattern that are all strings. - var n = 0 - while (typeof pattern[n] === 'string') { - n ++ - } - // now n is the index of the first one that is *not* a string. +/***/ }), +/* 132 */ +/***/ (function(module, exports, __webpack_require__) { - // see if there's anything else - var prefix - switch (n) { - // if not, then this is rather simple - case pattern.length: - this._processSimple(pattern.join('/'), index, cb) - return +// 19.1.2.14 / 15.2.3.14 Object.keys(O) +var $keys = __webpack_require__(195); +var enumBugKeys = __webpack_require__(101); - case 0: - // pattern *starts* with some non-trivial item. - // going to readdir(cwd), but not include the prefix in matches. - prefix = null - break +module.exports = Object.keys || function keys(O) { + return $keys(O, enumBugKeys); +}; - default: - // pattern has some string bits in the front. - // whatever it starts with, whether that's 'absolute' like /foo/bar, - // or 'relative' like '../baz' - prefix = pattern.slice(0, n).join('/') - break - } - var remain = pattern.slice(n) +/***/ }), +/* 133 */ +/***/ (function(module, exports, __webpack_require__) { - // get the list of entries. - var read - if (prefix === null) - read = '.' - else if (isAbsolute(prefix) || isAbsolute(pattern.join('/'))) { - if (!prefix || !isAbsolute(prefix)) - prefix = '/' + prefix - read = prefix - } else - read = prefix +// 7.1.13 ToObject(argument) +var defined = __webpack_require__(67); +module.exports = function (it) { + return Object(defined(it)); +}; - var abs = this._makeAbs(read) - //if ignored, skip _processing - if (childrenIgnored(this, read)) - return cb() +/***/ }), +/* 134 */, +/* 135 */, +/* 136 */, +/* 137 */, +/* 138 */, +/* 139 */, +/* 140 */, +/* 141 */, +/* 142 */, +/* 143 */, +/* 144 */, +/* 145 */ +/***/ (function(module, exports) { - var isGlobStar = remain[0] === minimatch.GLOBSTAR - if (isGlobStar) - this._processGlobStar(prefix, read, abs, remain, index, inGlobStar, cb) - else - this._processReaddir(prefix, read, abs, remain, index, inGlobStar, cb) -} +module.exports = {"name":"yarn","installationMethod":"unknown","version":"1.10.0-0","license":"BSD-2-Clause","preferGlobal":true,"description":"📦🐈 Fast, reliable, and secure dependency management.","dependencies":{"@zkochan/cmd-shim":"^2.2.4","babel-runtime":"^6.26.0","bytes":"^3.0.0","camelcase":"^4.0.0","chalk":"^2.1.0","commander":"^2.9.0","death":"^1.0.0","debug":"^3.0.0","deep-equal":"^1.0.1","detect-indent":"^5.0.0","dnscache":"^1.0.1","glob":"^7.1.1","gunzip-maybe":"^1.4.0","hash-for-dep":"^1.2.3","imports-loader":"^0.8.0","ini":"^1.3.4","inquirer":"^3.0.1","invariant":"^2.2.0","is-builtin-module":"^2.0.0","is-ci":"^1.0.10","is-webpack-bundle":"^1.0.0","leven":"^2.0.0","loud-rejection":"^1.2.0","micromatch":"^2.3.11","mkdirp":"^0.5.1","node-emoji":"^1.6.1","normalize-url":"^2.0.0","npm-logical-tree":"^1.2.1","object-path":"^0.11.2","proper-lockfile":"^2.0.0","puka":"^1.0.0","read":"^1.0.7","request":"^2.87.0","request-capture-har":"^1.2.2","rimraf":"^2.5.0","semver":"^5.1.0","ssri":"^5.3.0","strip-ansi":"^4.0.0","strip-bom":"^3.0.0","tar-fs":"^1.16.0","tar-stream":"^1.6.1","uuid":"^3.0.1","v8-compile-cache":"^2.0.0","validate-npm-package-license":"^3.0.3","yn":"^2.0.0"},"devDependencies":{"babel-core":"^6.26.0","babel-eslint":"^7.2.3","babel-loader":"^6.2.5","babel-plugin-array-includes":"^2.0.3","babel-plugin-transform-builtin-extend":"^1.1.2","babel-plugin-transform-inline-imports-commonjs":"^1.0.0","babel-plugin-transform-runtime":"^6.4.3","babel-preset-env":"^1.6.0","babel-preset-flow":"^6.23.0","babel-preset-stage-0":"^6.0.0","babylon":"^6.5.0","commitizen":"^2.9.6","cz-conventional-changelog":"^2.0.0","eslint":"^4.3.0","eslint-config-fb-strict":"^22.0.0","eslint-plugin-babel":"^5.0.0","eslint-plugin-flowtype":"^2.35.0","eslint-plugin-jasmine":"^2.6.2","eslint-plugin-jest":"^21.0.0","eslint-plugin-jsx-a11y":"^6.0.2","eslint-plugin-prefer-object-spread":"^1.2.1","eslint-plugin-prettier":"^2.1.2","eslint-plugin-react":"^7.1.0","eslint-plugin-relay":"^0.0.24","eslint-plugin-yarn-internal":"file:scripts/eslint-rules","execa":"^0.10.0","flow-bin":"^0.66.0","git-release-notes":"^3.0.0","gulp":"^3.9.0","gulp-babel":"^7.0.0","gulp-if":"^2.0.1","gulp-newer":"^1.0.0","gulp-plumber":"^1.0.1","gulp-sourcemaps":"^2.2.0","gulp-util":"^3.0.7","gulp-watch":"^5.0.0","jest":"^22.4.4","jsinspect":"^0.12.6","minimatch":"^3.0.4","mock-stdin":"^0.3.0","prettier":"^1.5.2","temp":"^0.8.3","webpack":"^2.1.0-beta.25","yargs":"^6.3.0"},"resolutions":{"sshpk":"^1.14.2"},"engines":{"node":">=4.0.0"},"repository":"yarnpkg/yarn","bin":{"yarn":"./bin/yarn.js","yarnpkg":"./bin/yarn.js"},"scripts":{"build":"gulp build","build-bundle":"node ./scripts/build-webpack.js","build-chocolatey":"powershell ./scripts/build-chocolatey.ps1","build-deb":"./scripts/build-deb.sh","build-dist":"bash ./scripts/build-dist.sh","build-win-installer":"scripts\\build-windows-installer.bat","changelog":"git-release-notes $(git describe --tags --abbrev=0 $(git describe --tags --abbrev=0)^)..$(git describe --tags --abbrev=0) scripts/changelog.md","dupe-check":"yarn jsinspect ./src","lint":"eslint . && flow check","pkg-tests":"yarn --cwd packages/pkg-tests jest yarn.test.js","prettier":"eslint src __tests__ --fix","release-branch":"./scripts/release-branch.sh","test":"yarn lint && yarn test-only","test-only":"node --max_old_space_size=4096 node_modules/jest/bin/jest.js --verbose","test-only-debug":"node --inspect-brk --max_old_space_size=4096 node_modules/jest/bin/jest.js --runInBand --verbose","test-coverage":"node --max_old_space_size=4096 node_modules/jest/bin/jest.js --coverage --verbose","watch":"gulp watch","commit":"git-cz"},"jest":{"collectCoverageFrom":["src/**/*.js"],"testEnvironment":"node","modulePathIgnorePatterns":["__tests__/fixtures/","packages/pkg-tests/pkg-tests-fixtures","dist/"],"testPathIgnorePatterns":["__tests__/(fixtures|__mocks__)/","updates/","_(temp|mock|install|init|helpers).js$","packages/pkg-tests"]},"config":{"commitizen":{"path":"./node_modules/cz-conventional-changelog"}}} -Glob.prototype._processReaddir = function (prefix, read, abs, remain, index, inGlobStar, cb) { - var self = this - this._readdir(abs, inGlobStar, function (er, entries) { - return self._processReaddir2(prefix, read, abs, remain, index, inGlobStar, entries, cb) - }) -} +/***/ }), +/* 146 */, +/* 147 */, +/* 148 */, +/* 149 */, +/* 150 */ +/***/ (function(module, exports, __webpack_require__) { -Glob.prototype._processReaddir2 = function (prefix, read, abs, remain, index, inGlobStar, entries, cb) { +"use strict"; - // if the abs isn't a dir, then nothing can match! - if (!entries) - return cb() - // It will only match dot entries if it starts with a dot, or if - // dot is set. Stuff like @(.foo|.bar) isn't allowed. - var pn = remain[0] - var negate = !!this.minimatch.negate - var rawGlob = pn._glob - var dotOk = this.dot || rawGlob.charAt(0) === '.' +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = stringify; - var matchedEntries = [] - for (var i = 0; i < entries.length; i++) { - var e = entries[i] - if (e.charAt(0) !== '.' || dotOk) { - var m - if (negate && !prefix) { - m = !e.match(pn) - } else { - m = e.match(pn) - } - if (m) - matchedEntries.push(e) - } - } +var _misc; - //console.error('prd2', prefix, entries, remain[0]._glob, matchedEntries) +function _load_misc() { + return _misc = __webpack_require__(12); +} - var len = matchedEntries.length - // If there are no matched entries, then nothing matches. - if (len === 0) - return cb() +var _constants; - // if this is the last remaining pattern bit, then no need for - // an additional stat *unless* the user has specified mark or - // stat explicitly. We know they exist, since readdir returned - // them. +function _load_constants() { + return _constants = __webpack_require__(6); +} - if (remain.length === 1 && !this.mark && !this.stat) { - if (!this.matches[index]) - this.matches[index] = Object.create(null) +var _package; - for (var i = 0; i < len; i ++) { - var e = matchedEntries[i] - if (prefix) { - if (prefix !== '/') - e = prefix + '/' + e - else - e = prefix + e - } +function _load_package() { + return _package = __webpack_require__(145); +} - if (e.charAt(0) === '/' && !this.nomount) { - e = path.join(this.root, e) - } - this._emitMatch(index, e) - } - // This was the last one, and no stats were needed - return cb() - } +const NODE_VERSION = process.version; - // now test all matched entries as stand-ins for that part - // of the pattern. - remain.shift() - for (var i = 0; i < len; i ++) { - var e = matchedEntries[i] - var newPattern - if (prefix) { - if (prefix !== '/') - e = prefix + '/' + e - else - e = prefix + e - } - this._process([e].concat(remain), index, inGlobStar, cb) +function shouldWrapKey(str) { + return str.indexOf('true') === 0 || str.indexOf('false') === 0 || /[:\s\n\\",\[\]]/g.test(str) || /^[0-9]/g.test(str) || !/^[a-zA-Z]/g.test(str); +} + +function maybeWrap(str) { + if (typeof str === 'boolean' || typeof str === 'number' || shouldWrapKey(str)) { + return JSON.stringify(str); + } else { + return str; } - cb() } -Glob.prototype._emitMatch = function (index, e) { - if (this.aborted) - return - - if (isIgnored(this, e)) - return - - if (this.paused) { - this._emitQueue.push([index, e]) - return - } - - var abs = isAbsolute(e) ? e : this._makeAbs(e) - - if (this.mark) - e = this._mark(e) - - if (this.absolute) - e = abs - - if (this.matches[index][e]) - return +const priorities = { + name: 1, + version: 2, + uid: 3, + resolved: 4, + integrity: 5, + registry: 6, + dependencies: 7 +}; - if (this.nodir) { - var c = this.cache[abs] - if (c === 'DIR' || Array.isArray(c)) - return +function priorityThenAlphaSort(a, b) { + if (priorities[a] || priorities[b]) { + return (priorities[a] || 100) > (priorities[b] || 100) ? 1 : -1; + } else { + return (0, (_misc || _load_misc()).sortAlpha)(a, b); } - - this.matches[index][e] = true - - var st = this.statCache[abs] - if (st) - this.emit('stat', e, st) - - this.emit('match', e) } -Glob.prototype._readdirInGlobStar = function (abs, cb) { - if (this.aborted) - return - - // follow all symlinked directories forever - // just proceed as if this is a non-globstar situation - if (this.follow) - return this._readdir(abs, false, cb) - - var lstatkey = 'lstat\0' + abs - var self = this - var lstatcb = inflight(lstatkey, lstatcb_) +function _stringify(obj, options) { + if (typeof obj !== 'object') { + throw new TypeError(); + } - if (lstatcb) - fs.lstat(abs, lstatcb) + const indent = options.indent; + const lines = []; - function lstatcb_ (er, lstat) { - if (er && er.code === 'ENOENT') - return cb() + // Sorting order needs to be consistent between runs, we run native sort by name because there are no + // problems with it being unstable because there are no to keys the same + // However priorities can be duplicated and native sort can shuffle things from run to run + const keys = Object.keys(obj).sort(priorityThenAlphaSort); - var isSym = lstat && lstat.isSymbolicLink() - self.symlinks[abs] = isSym + let addedKeys = []; - // If it's not a symlink or a dir, then it's definitely a regular file. - // don't bother doing a readdir in that case. - if (!isSym && lstat && !lstat.isDirectory()) { - self.cache[abs] = 'FILE' - cb() - } else - self._readdir(abs, false, cb) - } -} + for (let i = 0; i < keys.length; i++) { + const key = keys[i]; + const val = obj[key]; + if (val == null || addedKeys.indexOf(key) >= 0) { + continue; + } -Glob.prototype._readdir = function (abs, inGlobStar, cb) { - if (this.aborted) - return + const valKeys = [key]; - cb = inflight('readdir\0'+abs+'\0'+inGlobStar, cb) - if (!cb) - return + // get all keys that have the same value equality, we only want this for objects + if (typeof val === 'object') { + for (let j = i + 1; j < keys.length; j++) { + const key = keys[j]; + if (val === obj[key]) { + valKeys.push(key); + } + } + } - //console.error('RD %j %j', +inGlobStar, abs) - if (inGlobStar && !ownProp(this.symlinks, abs)) - return this._readdirInGlobStar(abs, cb) + const keyLine = valKeys.sort((_misc || _load_misc()).sortAlpha).map(maybeWrap).join(', '); - if (ownProp(this.cache, abs)) { - var c = this.cache[abs] - if (!c || c === 'FILE') - return cb() + if (typeof val === 'string' || typeof val === 'boolean' || typeof val === 'number') { + lines.push(`${keyLine} ${maybeWrap(val)}`); + } else if (typeof val === 'object') { + lines.push(`${keyLine}:\n${_stringify(val, { indent: indent + ' ' })}` + (options.topLevel ? '\n' : '')); + } else { + throw new TypeError(); + } - if (Array.isArray(c)) - return cb(null, c) + addedKeys = addedKeys.concat(valKeys); } - var self = this - fs.readdir(abs, readdirCb(this, abs, cb)) + return indent + lines.join(`\n${indent}`); } -function readdirCb (self, abs, cb) { - return function (er, entries) { - if (er) - self._readdirError(abs, er, cb) - else - self._readdirEntries(abs, entries, cb) +function stringify(obj, noHeader, enableVersions) { + const val = _stringify(obj, { + indent: '', + topLevel: true + }); + if (noHeader) { + return val; } -} -Glob.prototype._readdirEntries = function (abs, entries, cb) { - if (this.aborted) - return - - // if we haven't asked to stat everything, then just - // assume that everything in there exists, so we can avoid - // having to stat it a second time. - if (!this.mark && !this.stat) { - for (var i = 0; i < entries.length; i ++) { - var e = entries[i] - if (abs === '/') - e = abs + e - else - e = abs + '/' + e - this.cache[e] = true - } + const lines = []; + lines.push('# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.'); + lines.push(`# yarn lockfile v${(_constants || _load_constants()).LOCKFILE_VERSION}`); + if (enableVersions) { + lines.push(`# yarn v${(_package || _load_package()).version}`); + lines.push(`# node ${NODE_VERSION}`); } + lines.push('\n'); + lines.push(val); - this.cache[abs] = entries - return cb(null, entries) + return lines.join('\n'); } -Glob.prototype._readdirError = function (f, er, cb) { - if (this.aborted) - return +/***/ }), +/* 151 */, +/* 152 */, +/* 153 */, +/* 154 */, +/* 155 */, +/* 156 */, +/* 157 */, +/* 158 */, +/* 159 */, +/* 160 */, +/* 161 */, +/* 162 */, +/* 163 */, +/* 164 */ +/***/ (function(module, exports, __webpack_require__) { - // handle errors, and cache the information - switch (er.code) { - case 'ENOTSUP': // https://github.com/isaacs/node-glob/issues/205 - case 'ENOTDIR': // totally normal. means it *does* exist. - var abs = this._makeAbs(f) - this.cache[abs] = 'FILE' - if (abs === this.cwdAbs) { - var error = new Error(er.code + ' invalid cwd ' + this.cwd) - error.path = this.cwd - error.code = er.code - this.emit('error', error) - this.abort() - } - break +"use strict"; - case 'ENOENT': // not terribly unusual - case 'ELOOP': - case 'ENAMETOOLONG': - case 'UNKNOWN': - this.cache[this._makeAbs(f)] = false - break - default: // some unusual error. Treat as failure. - this.cache[this._makeAbs(f)] = false - if (this.strict) { - this.emit('error', er) - // If the error is handled, then we abort - // if not, we threw out of here - this.abort() - } - if (!this.silent) - console.error('glob error', er) - break - } +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.fileDatesEqual = exports.copyFile = exports.unlink = undefined; - return cb() -} +var _asyncToGenerator2; -Glob.prototype._processGlobStar = function (prefix, read, abs, remain, index, inGlobStar, cb) { - var self = this - this._readdir(abs, inGlobStar, function (er, entries) { - self._processGlobStar2(prefix, read, abs, remain, index, inGlobStar, entries, cb) - }) +function _load_asyncToGenerator() { + return _asyncToGenerator2 = _interopRequireDefault(__webpack_require__(1)); } +// We want to preserve file timestamps when copying a file, since yarn uses them to decide if a file has +// changed compared to the cache. +// There are some OS specific cases here: +// * On linux, fs.copyFile does not preserve timestamps, but does on OSX and Win. +// * On windows, you must open a file with write permissions to call `fs.futimes`. +// * On OSX you can open with read permissions and still call `fs.futimes`. +let fixTimes = (() => { + var _ref3 = (0, (_asyncToGenerator2 || _load_asyncToGenerator()).default)(function* (fd, dest, data) { + const doOpen = fd === undefined; + let openfd = fd ? fd : -1; -Glob.prototype._processGlobStar2 = function (prefix, read, abs, remain, index, inGlobStar, entries, cb) { - //console.error('pgs2', prefix, remain[0], entries) - - // no entries means not a dir, so it can never have matches - // foo.txt/** doesn't match foo.txt - if (!entries) - return cb() - - // test without the globstar, and with every child both below - // and replacing the globstar. - var remainWithoutGlobStar = remain.slice(1) - var gspref = prefix ? [ prefix ] : [] - var noGlobStar = gspref.concat(remainWithoutGlobStar) + if (disableTimestampCorrection === undefined) { + // if timestamps match already, no correction is needed. + // the need to correct timestamps varies based on OS and node versions. + const destStat = yield lstat(dest); + disableTimestampCorrection = fileDatesEqual(destStat.mtime, data.mtime); + } - // the noGlobStar pattern exits the inGlobStar state - this._process(noGlobStar, index, false, cb) + if (disableTimestampCorrection) { + return; + } - var isSym = this.symlinks[abs] - var len = entries.length + if (doOpen) { + try { + openfd = yield open(dest, 'a', data.mode); + } catch (er) { + // file is likely read-only + try { + openfd = yield open(dest, 'r', data.mode); + } catch (err) { + // We can't even open this file for reading. + return; + } + } + } - // If it's a symlink, and we're in a globstar, then stop - if (isSym && inGlobStar) - return cb() + try { + if (openfd) { + yield futimes(openfd, data.atime, data.mtime); + } + } catch (er) { + // If `futimes` throws an exception, we probably have a case of a read-only file on Windows. + // In this case we can just return. The incorrect timestamp will just cause that file to be recopied + // on subsequent installs, which will effect yarn performance but not break anything. + } finally { + if (doOpen && openfd) { + yield close(openfd); + } + } + }); - for (var i = 0; i < len; i++) { - var e = entries[i] - if (e.charAt(0) === '.' && !this.dot) - continue + return function fixTimes(_x7, _x8, _x9) { + return _ref3.apply(this, arguments); + }; +})(); - // these two cases enter the inGlobStar state - var instead = gspref.concat(entries[i], remainWithoutGlobStar) - this._process(instead, index, true, cb) +// Compare file timestamps. +// Some versions of Node on windows zero the milliseconds when utime is used. - var below = gspref.concat(entries[i], remain) - this._process(below, index, true, cb) - } - cb() -} +var _fs; -Glob.prototype._processSimple = function (prefix, index, cb) { - // XXX review this. Shouldn't it be doing the mounting etc - // before doing stat? kinda weird? - var self = this - this._stat(prefix, function (er, exists) { - self._processSimple2(prefix, index, er, exists, cb) - }) +function _load_fs() { + return _fs = _interopRequireDefault(__webpack_require__(3)); } -Glob.prototype._processSimple2 = function (prefix, index, er, exists, cb) { - - //console.error('ps2', prefix, exists) - - if (!this.matches[index]) - this.matches[index] = Object.create(null) - // If it doesn't exist, then just mark the lack of results - if (!exists) - return cb() +var _promise; - if (prefix && isAbsolute(prefix) && !this.nomount) { - var trail = /[\/\\]$/.test(prefix) - if (prefix.charAt(0) === '/') { - prefix = path.join(this.root, prefix) - } else { - prefix = path.resolve(this.root, prefix) - if (trail) - prefix += '/' - } - } +function _load_promise() { + return _promise = __webpack_require__(40); +} - if (process.platform === 'win32') - prefix = prefix.replace(/\\/g, '/') +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - // Mark this as a match - this._emitMatch(index, prefix) - cb() -} +// This module serves as a wrapper for file operations that are inconsistant across node and OS versions. -// Returns either 'DIR', 'FILE', or false -Glob.prototype._stat = function (f, cb) { - var abs = this._makeAbs(f) - var needDir = f.slice(-1) === '/' +let disableTimestampCorrection = undefined; // OS dependent. will be detected on first file copy. - if (f.length > this.maxLength) - return cb() +const readFileBuffer = (0, (_promise || _load_promise()).promisify)((_fs || _load_fs()).default.readFile); +const close = (0, (_promise || _load_promise()).promisify)((_fs || _load_fs()).default.close); +const lstat = (0, (_promise || _load_promise()).promisify)((_fs || _load_fs()).default.lstat); +const open = (0, (_promise || _load_promise()).promisify)((_fs || _load_fs()).default.open); +const futimes = (0, (_promise || _load_promise()).promisify)((_fs || _load_fs()).default.futimes); - if (!this.stat && ownProp(this.cache, abs)) { - var c = this.cache[abs] +const write = (0, (_promise || _load_promise()).promisify)((_fs || _load_fs()).default.write); - if (Array.isArray(c)) - c = 'DIR' +const unlink = exports.unlink = (0, (_promise || _load_promise()).promisify)(__webpack_require__(233)); - // It exists, but maybe not how we need it - if (!needDir || c === 'DIR') - return cb(null, c) +/** + * Unlinks the destination to force a recreation. This is needed on case-insensitive file systems + * to force the correct naming when the filename has changed only in character-casing. (Jest -> jest). + */ +const copyFile = exports.copyFile = (() => { + var _ref = (0, (_asyncToGenerator2 || _load_asyncToGenerator()).default)(function* (data, cleanup) { + try { + yield unlink(data.dest); + yield copyFilePoly(data.src, data.dest, 0, data); + } finally { + if (cleanup) { + cleanup(); + } + } + }); - if (needDir && c === 'FILE') - return cb() + return function copyFile(_x, _x2) { + return _ref.apply(this, arguments); + }; +})(); - // otherwise we have to stat, because maybe c=true - // if we know it exists, but not what it is. +// Node 8.5.0 introduced `fs.copyFile` which is much faster, so use that when available. +// Otherwise we fall back to reading and writing files as buffers. +const copyFilePoly = (src, dest, flags, data) => { + if ((_fs || _load_fs()).default.copyFile) { + return new Promise((resolve, reject) => (_fs || _load_fs()).default.copyFile(src, dest, flags, err => { + if (err) { + reject(err); + } else { + fixTimes(undefined, dest, data).then(() => resolve()).catch(ex => reject(ex)); + } + })); + } else { + return copyWithBuffer(src, dest, flags, data); } +}; - var exists - var stat = this.statCache[abs] - if (stat !== undefined) { - if (stat === false) - return cb(null, stat) - else { - var type = stat.isDirectory() ? 'DIR' : 'FILE' - if (needDir && type === 'FILE') - return cb() - else - return cb(null, type, stat) +const copyWithBuffer = (() => { + var _ref2 = (0, (_asyncToGenerator2 || _load_asyncToGenerator()).default)(function* (src, dest, flags, data) { + // Use open -> write -> futimes -> close sequence to avoid opening the file twice: + // one with writeFile and one with utimes + const fd = yield open(dest, 'w', data.mode); + try { + const buffer = yield readFileBuffer(src); + yield write(fd, buffer, 0, buffer.length); + yield fixTimes(fd, dest, data); + } finally { + yield close(fd); } - } + }); - var self = this - var statcb = inflight('stat\0' + abs, lstatcb_) - if (statcb) - fs.lstat(abs, statcb) + return function copyWithBuffer(_x3, _x4, _x5, _x6) { + return _ref2.apply(this, arguments); + }; +})();const fileDatesEqual = exports.fileDatesEqual = (a, b) => { + const aTime = a.getTime(); + const bTime = b.getTime(); - function lstatcb_ (er, lstat) { - if (lstat && lstat.isSymbolicLink()) { - // If it's a symlink, then treat it as the target, unless - // the target does not exist, then treat it as a file. - return fs.stat(abs, function (er, stat) { - if (er) - self._stat2(f, abs, null, lstat, cb) - else - self._stat2(f, abs, er, stat, cb) - }) - } else { - self._stat2(f, abs, er, lstat, cb) - } + if (process.platform !== 'win32') { + return aTime === bTime; } -} -Glob.prototype._stat2 = function (f, abs, er, stat, cb) { - if (er && (er.code === 'ENOENT' || er.code === 'ENOTDIR')) { - this.statCache[abs] = false - return cb() + // See https://github.com/nodejs/node/pull/12607 + // Submillisecond times from stat and utimes are truncated on Windows, + // causing a file with mtime 8.0079998 and 8.0081144 to become 8.007 and 8.008 + // and making it impossible to update these files to their correct timestamps. + if (Math.abs(aTime - bTime) <= 1) { + return true; } - var needDir = f.slice(-1) === '/' - this.statCache[abs] = stat - - if (abs.slice(-1) === '/' && stat && !stat.isDirectory()) - return cb(null, false, stat) - - var c = true - if (stat) - c = stat.isDirectory() ? 'DIR' : 'FILE' - this.cache[abs] = this.cache[abs] || c - - if (needDir && c === 'FILE') - return cb() + const aTimeSec = Math.floor(aTime / 1000); + const bTimeSec = Math.floor(bTime / 1000); - return cb(null, c, stat) -} + // See https://github.com/nodejs/node/issues/2069 + // Some versions of Node on windows zero the milliseconds when utime is used + // So if any of the time has a milliseconds part of zero we suspect that the + // bug is present and compare only seconds. + if (aTime - aTimeSec * 1000 === 0 || bTime - bTimeSec * 1000 === 0) { + return aTimeSec === bTimeSec; + } + return aTime === bTime; +}; /***/ }), -/* 76 */ +/* 165 */, +/* 166 */, +/* 167 */, +/* 168 */, +/* 169 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -function posix(path) { - return path.charAt(0) === '/'; +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.isFakeRoot = isFakeRoot; +exports.isRootUser = isRootUser; +function getUid() { + if (process.platform !== 'win32' && process.getuid) { + return process.getuid(); + } + return null; } -function win32(path) { - // https://github.com/nodejs/node/blob/b3fcc245fb25539909ef1d5eaa01dbf92e168633/lib/path.js#L56 - var splitDeviceRe = /^([a-zA-Z]:|[\\\/]{2}[^\\\/]+[\\\/]+[^\\\/]+)?([\\\/])?([\s\S]*?)$/; - var result = splitDeviceRe.exec(path); - var device = result[1] || ''; - var isUnc = Boolean(device && device.charAt(1) !== ':'); - - // UNC paths are always absolute - return Boolean(result[2] || isUnc); +exports.default = isRootUser(getUid()) && !isFakeRoot(); +function isFakeRoot() { + return Boolean(process.env.FAKEROOTKEY); } -module.exports = process.platform === 'win32' ? win32 : posix; -module.exports.posix = posix; -module.exports.win32 = win32; - - -/***/ }), -/* 77 */, -/* 78 */, -/* 79 */ -/***/ (function(module, exports) { - -module.exports = __webpack_require__(121); +function isRootUser(uid) { + return uid === 0; +} /***/ }), -/* 80 */, -/* 81 */ +/* 170 */, +/* 171 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -34000,14465 +34502,14512 @@ module.exports = __webpack_require__(121); Object.defineProperty(exports, "__esModule", { value: true }); +exports.getDataDir = getDataDir; +exports.getCacheDir = getCacheDir; +exports.getConfigDir = getConfigDir; +const path = __webpack_require__(0); +const userHome = __webpack_require__(45).default; -exports.default = function (str, fileLoc = 'lockfile') { - str = (0, (_stripBom || _load_stripBom()).default)(str); - return hasMergeConflicts(str) ? parseWithConflict(str, fileLoc) : { type: 'success', object: parse(str, fileLoc) }; -}; +const FALLBACK_CONFIG_DIR = path.join(userHome, '.config', 'yarn'); +const FALLBACK_CACHE_DIR = path.join(userHome, '.cache', 'yarn'); -var _util; +function getDataDir() { + if (process.platform === 'win32') { + const WIN32_APPDATA_DIR = getLocalAppDataDir(); + return WIN32_APPDATA_DIR == null ? FALLBACK_CONFIG_DIR : path.join(WIN32_APPDATA_DIR, 'Data'); + } else if (process.env.XDG_DATA_HOME) { + return path.join(process.env.XDG_DATA_HOME, 'yarn'); + } else { + // This could arguably be ~/Library/Application Support/Yarn on Macs, + // but that feels unintuitive for a cli tool -function _load_util() { - return _util = _interopRequireDefault(__webpack_require__(2)); + // Instead, use our prior fallback. Some day this could be + // path.join(userHome, '.local', 'share', 'yarn') + // or return path.join(WIN32_APPDATA_DIR, 'Data') on win32 + return FALLBACK_CONFIG_DIR; + } } -var _invariant; - -function _load_invariant() { - return _invariant = _interopRequireDefault(__webpack_require__(7)); +function getCacheDir() { + if (process.platform === 'win32') { + // process.env.TEMP also exists, but most apps put caches here + return path.join(getLocalAppDataDir() || path.join(userHome, 'AppData', 'Local', 'Yarn'), 'Cache'); + } else if (process.env.XDG_CACHE_HOME) { + return path.join(process.env.XDG_CACHE_HOME, 'yarn'); + } else if (process.platform === 'darwin') { + return path.join(userHome, 'Library', 'Caches', 'Yarn'); + } else { + return FALLBACK_CACHE_DIR; + } } -var _stripBom; +function getConfigDir() { + if (process.platform === 'win32') { + // Use our prior fallback. Some day this could be + // return path.join(WIN32_APPDATA_DIR, 'Config') + const WIN32_APPDATA_DIR = getLocalAppDataDir(); + return WIN32_APPDATA_DIR == null ? FALLBACK_CONFIG_DIR : path.join(WIN32_APPDATA_DIR, 'Config'); + } else if (process.env.XDG_CONFIG_HOME) { + return path.join(process.env.XDG_CONFIG_HOME, 'yarn'); + } else { + return FALLBACK_CONFIG_DIR; + } +} -function _load_stripBom() { - return _stripBom = _interopRequireDefault(__webpack_require__(122)); +function getLocalAppDataDir() { + return process.env.LOCALAPPDATA ? path.join(process.env.LOCALAPPDATA, 'Yarn') : null; } -var _constants; +/***/ }), +/* 172 */, +/* 173 */ +/***/ (function(module, exports, __webpack_require__) { -function _load_constants() { - return _constants = __webpack_require__(6); -} +module.exports = { "default": __webpack_require__(179), __esModule: true }; -var _errors; +/***/ }), +/* 174 */ +/***/ (function(module, exports, __webpack_require__) { -function _load_errors() { - return _errors = __webpack_require__(4); -} +"use strict"; -var _map; +module.exports = balanced; +function balanced(a, b, str) { + if (a instanceof RegExp) a = maybeMatch(a, str); + if (b instanceof RegExp) b = maybeMatch(b, str); -function _load_map() { - return _map = _interopRequireDefault(__webpack_require__(20)); + var r = range(a, b, str); + + return r && { + start: r[0], + end: r[1], + pre: str.slice(0, r[0]), + body: str.slice(r[0] + a.length, r[1]), + post: str.slice(r[1] + b.length) + }; } -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } +function maybeMatch(reg, str) { + var m = str.match(reg); + return m ? m[0] : null; +} -/* eslint quotes: 0 */ +balanced.range = range; +function range(a, b, str) { + var begs, beg, left, right, result; + var ai = str.indexOf(a); + var bi = str.indexOf(b, ai + 1); + var i = ai; -const VERSION_REGEX = /^yarn lockfile v(\d+)$/; + if (ai >= 0 && bi > 0) { + begs = []; + left = str.length; -const TOKEN_TYPES = { - boolean: 'BOOLEAN', - string: 'STRING', - identifier: 'IDENTIFIER', - eof: 'EOF', - colon: 'COLON', - newline: 'NEWLINE', - comment: 'COMMENT', - indent: 'INDENT', - invalid: 'INVALID', - number: 'NUMBER', - comma: 'COMMA' -}; + while (i >= 0 && !result) { + if (i == ai) { + begs.push(i); + ai = str.indexOf(a, i + 1); + } else if (begs.length == 1) { + result = [ begs.pop(), bi ]; + } else { + beg = begs.pop(); + if (beg < left) { + left = beg; + right = bi; + } -const VALID_PROP_VALUE_TOKENS = [TOKEN_TYPES.boolean, TOKEN_TYPES.string, TOKEN_TYPES.number]; + bi = str.indexOf(b, i + 1); + } -function isValidPropValueToken(token) { - return VALID_PROP_VALUE_TOKENS.indexOf(token.type) >= 0; + i = ai < bi && ai >= 0 ? ai : bi; + } + + if (begs.length) { + result = [ left, right ]; + } + } + + return result; } -function* tokenise(input) { - let lastNewline = false; - let line = 1; - let col = 0; - function buildToken(type, value) { - return { line, col, type, value }; - } +/***/ }), +/* 175 */ +/***/ (function(module, exports, __webpack_require__) { - while (input.length) { - let chop = 0; +var concatMap = __webpack_require__(178); +var balanced = __webpack_require__(174); - if (input[0] === '\n' || input[0] === '\r') { - chop++; - // If this is a \r\n line, ignore both chars but only add one new line - if (input[1] === '\n') { - chop++; - } - line++; - col = 0; - yield buildToken(TOKEN_TYPES.newline); - } else if (input[0] === '#') { - chop++; +module.exports = expandTop; - let val = ''; - while (input[chop] !== '\n') { - val += input[chop]; - chop++; - } - yield buildToken(TOKEN_TYPES.comment, val); - } else if (input[0] === ' ') { - if (lastNewline) { - let indent = ''; - for (let i = 0; input[i] === ' '; i++) { - indent += input[i]; - } +var escSlash = '\0SLASH'+Math.random()+'\0'; +var escOpen = '\0OPEN'+Math.random()+'\0'; +var escClose = '\0CLOSE'+Math.random()+'\0'; +var escComma = '\0COMMA'+Math.random()+'\0'; +var escPeriod = '\0PERIOD'+Math.random()+'\0'; - if (indent.length % 2) { - throw new TypeError('Invalid number of spaces'); - } else { - chop = indent.length; - yield buildToken(TOKEN_TYPES.indent, indent.length / 2); - } - } else { - chop++; - } - } else if (input[0] === '"') { - let val = ''; +function numeric(str) { + return parseInt(str, 10) == str + ? parseInt(str, 10) + : str.charCodeAt(0); +} - for (let i = 0;; i++) { - const currentChar = input[i]; - val += currentChar; +function escapeBraces(str) { + return str.split('\\\\').join(escSlash) + .split('\\{').join(escOpen) + .split('\\}').join(escClose) + .split('\\,').join(escComma) + .split('\\.').join(escPeriod); +} - if (i > 0 && currentChar === '"') { - const isEscaped = input[i - 1] === '\\' && input[i - 2] !== '\\'; - if (!isEscaped) { - break; - } - } - } +function unescapeBraces(str) { + return str.split(escSlash).join('\\') + .split(escOpen).join('{') + .split(escClose).join('}') + .split(escComma).join(',') + .split(escPeriod).join('.'); +} - chop = val.length; - try { - yield buildToken(TOKEN_TYPES.string, JSON.parse(val)); - } catch (err) { - if (err instanceof SyntaxError) { - yield buildToken(TOKEN_TYPES.invalid); - } else { - throw err; - } - } - } else if (/^[0-9]/.test(input)) { - let val = ''; - for (let i = 0; /^[0-9]$/.test(input[i]); i++) { - val += input[i]; - } - chop = val.length; +// Basically just str.split(","), but handling cases +// where we have nested braced sections, which should be +// treated as individual members, like {a,{b,c},d} +function parseCommaParts(str) { + if (!str) + return ['']; - yield buildToken(TOKEN_TYPES.number, +val); - } else if (/^true/.test(input)) { - yield buildToken(TOKEN_TYPES.boolean, true); - chop = 4; - } else if (/^false/.test(input)) { - yield buildToken(TOKEN_TYPES.boolean, false); - chop = 5; - } else if (input[0] === ':') { - yield buildToken(TOKEN_TYPES.colon); - chop++; - } else if (input[0] === ',') { - yield buildToken(TOKEN_TYPES.comma); - chop++; - } else if (/^[a-zA-Z\/-]/g.test(input)) { - let name = ''; - for (let i = 0; i < input.length; i++) { - const char = input[i]; - if (char === ':' || char === ' ' || char === '\n' || char === '\r' || char === ',') { - break; - } else { - name += char; - } - } - chop = name.length; + var parts = []; + var m = balanced('{', '}', str); - yield buildToken(TOKEN_TYPES.string, name); - } else { - yield buildToken(TOKEN_TYPES.invalid); - } + if (!m) + return str.split(','); - if (!chop) { - // will trigger infinite recursion - yield buildToken(TOKEN_TYPES.invalid); - } + var pre = m.pre; + var body = m.body; + var post = m.post; + var p = pre.split(','); - col += chop; - lastNewline = input[0] === '\n' || input[0] === '\r' && input[1] === '\n'; - input = input.slice(chop); + p[p.length-1] += '{' + body + '}'; + var postParts = parseCommaParts(post); + if (post.length) { + p[p.length-1] += postParts.shift(); + p.push.apply(p, postParts); } - yield buildToken(TOKEN_TYPES.eof); + parts.push.apply(parts, p); + + return parts; } -class Parser { - constructor(input, fileLoc = 'lockfile') { - this.comments = []; - this.tokens = tokenise(input); - this.fileLoc = fileLoc; +function expandTop(str) { + if (!str) + return []; + + // I don't know why Bash 4.3 does this, but it does. + // Anything starting with {} will have the first two bytes preserved + // but *only* at the top level, so {},a}b will not expand to anything, + // but a{},b}c will be expanded to [a}c,abc]. + // One could argue that this is a bug in Bash, but since the goal of + // this module is to match Bash's rules, we escape a leading {} + if (str.substr(0, 2) === '{}') { + str = '\\{\\}' + str.substr(2); } - onComment(token) { - const value = token.value; - (0, (_invariant || _load_invariant()).default)(typeof value === 'string', 'expected token value to be a string'); + return expand(escapeBraces(str), true).map(unescapeBraces); +} - const comment = value.trim(); +function identity(e) { + return e; +} - const versionMatch = comment.match(VERSION_REGEX); - if (versionMatch) { - const version = +versionMatch[1]; - if (version > (_constants || _load_constants()).LOCKFILE_VERSION) { - throw new (_errors || _load_errors()).MessageError(`Can't install from a lockfile of version ${version} as you're on an old yarn version that only supports ` + `versions up to ${(_constants || _load_constants()).LOCKFILE_VERSION}. Run \`$ yarn self-update\` to upgrade to the latest version.`); - } - } +function embrace(str) { + return '{' + str + '}'; +} +function isPadded(el) { + return /^-?0\d/.test(el); +} - this.comments.push(comment); - } +function lte(i, y) { + return i <= y; +} +function gte(i, y) { + return i >= y; +} - next() { - const item = this.tokens.next(); - (0, (_invariant || _load_invariant()).default)(item, 'expected a token'); +function expand(str, isTop) { + var expansions = []; - const done = item.done, - value = item.value; + var m = balanced('{', '}', str); + if (!m || /\$$/.test(m.pre)) return [str]; - if (done || !value) { - throw new Error('No more tokens'); - } else if (value.type === TOKEN_TYPES.comment) { - this.onComment(value); - return this.next(); - } else { - return this.token = value; + var isNumericSequence = /^-?\d+\.\.-?\d+(?:\.\.-?\d+)?$/.test(m.body); + var isAlphaSequence = /^[a-zA-Z]\.\.[a-zA-Z](?:\.\.-?\d+)?$/.test(m.body); + var isSequence = isNumericSequence || isAlphaSequence; + var isOptions = m.body.indexOf(',') >= 0; + if (!isSequence && !isOptions) { + // {a},b} + if (m.post.match(/,.*\}/)) { + str = m.pre + '{' + m.body + escClose + m.post; + return expand(str); } + return [str]; } - unexpected(msg = 'Unexpected token') { - throw new SyntaxError(`${msg} ${this.token.line}:${this.token.col} in ${this.fileLoc}`); + var n; + if (isSequence) { + n = m.body.split(/\.\./); + } else { + n = parseCommaParts(m.body); + if (n.length === 1) { + // x{{a,b}}y ==> x{a}y x{b}y + n = expand(n[0], false).map(embrace); + if (n.length === 1) { + var post = m.post.length + ? expand(m.post, false) + : ['']; + return post.map(function(p) { + return m.pre + n[0] + p; + }); + } + } } - expect(tokType) { - if (this.token.type === tokType) { - this.next(); - } else { - this.unexpected(); + // at this point, n is the parts, and we know it's not a comma set + // with a single entry. + + // no need to expand pre, since it is guaranteed to be free of brace-sets + var pre = m.pre; + var post = m.post.length + ? expand(m.post, false) + : ['']; + + var N; + + if (isSequence) { + var x = numeric(n[0]); + var y = numeric(n[1]); + var width = Math.max(n[0].length, n[1].length) + var incr = n.length == 3 + ? Math.abs(numeric(n[2])) + : 1; + var test = lte; + var reverse = y < x; + if (reverse) { + incr *= -1; + test = gte; + } + var pad = n.some(isPadded); + + N = []; + + for (var i = x; test(i, y); i += incr) { + var c; + if (isAlphaSequence) { + c = String.fromCharCode(i); + if (c === '\\') + c = ''; + } else { + c = String(i); + if (pad) { + var need = width - c.length; + if (need > 0) { + var z = new Array(need + 1).join('0'); + if (i < 0) + c = '-' + z + c.slice(1); + else + c = z + c; + } + } + } + N.push(c); } + } else { + N = concatMap(n, function(el) { return expand(el, false) }); } - eat(tokType) { - if (this.token.type === tokType) { - this.next(); - return true; - } else { - return false; + for (var j = 0; j < N.length; j++) { + for (var k = 0; k < post.length; k++) { + var expansion = pre + N[j] + post[k]; + if (!isTop || isSequence || expansion) + expansions.push(expansion); } } - parse(indent = 0) { - const obj = (0, (_map || _load_map()).default)(); + return expansions; +} - while (true) { - const propToken = this.token; - if (propToken.type === TOKEN_TYPES.newline) { - const nextToken = this.next(); - if (!indent) { - // if we have 0 indentation then the next token doesn't matter - continue; - } - - if (nextToken.type !== TOKEN_TYPES.indent) { - // if we have no indentation after a newline then we've gone down a level - break; - } - if (nextToken.value === indent) { - // all is good, the indent is on our level - this.next(); - } else { - // the indentation is less than our level - break; - } - } else if (propToken.type === TOKEN_TYPES.indent) { - if (propToken.value === indent) { - this.next(); - } else { - break; - } - } else if (propToken.type === TOKEN_TYPES.eof) { - break; - } else if (propToken.type === TOKEN_TYPES.string) { - // property key - const key = propToken.value; - (0, (_invariant || _load_invariant()).default)(key, 'Expected a key'); +/***/ }), +/* 176 */ +/***/ (function(module, exports, __webpack_require__) { - const keys = [key]; - this.next(); +"use strict"; - // support multiple keys - while (this.token.type === TOKEN_TYPES.comma) { - this.next(); // skip comma - const keyToken = this.token; - if (keyToken.type !== TOKEN_TYPES.string) { - this.unexpected('Expected string'); - } +function preserveCamelCase(str) { + let isLastCharLower = false; + let isLastCharUpper = false; + let isLastLastCharUpper = false; - const key = keyToken.value; - (0, (_invariant || _load_invariant()).default)(key, 'Expected a key'); - keys.push(key); - this.next(); - } + for (let i = 0; i < str.length; i++) { + const c = str[i]; - const valToken = this.token; + if (isLastCharLower && /[a-zA-Z]/.test(c) && c.toUpperCase() === c) { + str = str.substr(0, i) + '-' + str.substr(i); + isLastCharLower = false; + isLastLastCharUpper = isLastCharUpper; + isLastCharUpper = true; + i++; + } else if (isLastCharUpper && isLastLastCharUpper && /[a-zA-Z]/.test(c) && c.toLowerCase() === c) { + str = str.substr(0, i - 1) + '-' + str.substr(i - 1); + isLastLastCharUpper = isLastCharUpper; + isLastCharUpper = false; + isLastCharLower = true; + } else { + isLastCharLower = c.toLowerCase() === c; + isLastLastCharUpper = isLastCharUpper; + isLastCharUpper = c.toUpperCase() === c; + } + } - if (valToken.type === TOKEN_TYPES.colon) { - // object - this.next(); + return str; +} - // parse object - const val = this.parse(indent + 1); +module.exports = function (str) { + if (arguments.length > 1) { + str = Array.from(arguments) + .map(x => x.trim()) + .filter(x => x.length) + .join('-'); + } else { + str = str.trim(); + } - for (var _iterator = keys, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : _iterator[Symbol.iterator]();;) { - var _ref; + if (str.length === 0) { + return ''; + } - if (_isArray) { - if (_i >= _iterator.length) break; - _ref = _iterator[_i++]; - } else { - _i = _iterator.next(); - if (_i.done) break; - _ref = _i.value; - } + if (str.length === 1) { + return str.toLowerCase(); + } - const key = _ref; + if (/^[a-z0-9]+$/.test(str)) { + return str; + } - obj[key] = val; - } + const hasUpperCase = str !== str.toLowerCase(); - if (indent && this.token.type !== TOKEN_TYPES.indent) { - break; - } - } else if (isValidPropValueToken(valToken)) { - // plain value - for (var _iterator2 = keys, _isArray2 = Array.isArray(_iterator2), _i2 = 0, _iterator2 = _isArray2 ? _iterator2 : _iterator2[Symbol.iterator]();;) { - var _ref2; + if (hasUpperCase) { + str = preserveCamelCase(str); + } - if (_isArray2) { - if (_i2 >= _iterator2.length) break; - _ref2 = _iterator2[_i2++]; - } else { - _i2 = _iterator2.next(); - if (_i2.done) break; - _ref2 = _i2.value; - } + return str + .replace(/^[_.\- ]+/, '') + .toLowerCase() + .replace(/[_.\- ]+(\w|$)/g, (m, p1) => p1.toUpperCase()); +}; - const key = _ref2; - obj[key] = valToken.value; - } +/***/ }), +/* 177 */, +/* 178 */ +/***/ (function(module, exports) { - this.next(); - } else { - this.unexpected('Invalid value type'); - } - } else { - this.unexpected(`Unknown token: ${(_util || _load_util()).default.inspect(propToken)}`); - } +module.exports = function (xs, fn) { + var res = []; + for (var i = 0; i < xs.length; i++) { + var x = fn(xs[i], i); + if (isArray(x)) res.push.apply(res, x); + else res.push(x); } + return res; +}; - return obj; - } -} +var isArray = Array.isArray || function (xs) { + return Object.prototype.toString.call(xs) === '[object Array]'; +}; -const MERGE_CONFLICT_ANCESTOR = '|||||||'; -const MERGE_CONFLICT_END = '>>>>>>>'; -const MERGE_CONFLICT_SEP = '======='; -const MERGE_CONFLICT_START = '<<<<<<<'; -/** - * Extract the two versions of the lockfile from a merge conflict. - */ -function extractConflictVariants(str) { - const variants = [[], []]; - const lines = str.split(/\r?\n/g); - let skip = false; +/***/ }), +/* 179 */ +/***/ (function(module, exports, __webpack_require__) { - while (lines.length) { - const line = lines.shift(); - if (line.startsWith(MERGE_CONFLICT_START)) { - // get the first variant - while (lines.length) { - const conflictLine = lines.shift(); - if (conflictLine === MERGE_CONFLICT_SEP) { - skip = false; - break; - } else if (skip || conflictLine.startsWith(MERGE_CONFLICT_ANCESTOR)) { - skip = true; - continue; - } else { - variants[0].push(conflictLine); - } - } +__webpack_require__(205); +__webpack_require__(207); +__webpack_require__(210); +__webpack_require__(206); +__webpack_require__(208); +__webpack_require__(209); +module.exports = __webpack_require__(23).Promise; - // get the second variant - while (lines.length) { - const conflictLine = lines.shift(); - if (conflictLine.startsWith(MERGE_CONFLICT_END)) { - break; - } else { - variants[1].push(conflictLine); - } - } - } else { - variants[0].push(line); - variants[1].push(line); - } - } - return [variants[0].join('\n'), variants[1].join('\n')]; -} +/***/ }), +/* 180 */ +/***/ (function(module, exports) { -/** - * Check if a lockfile has merge conflicts. - */ -function hasMergeConflicts(str) { - return str.includes(MERGE_CONFLICT_START) && str.includes(MERGE_CONFLICT_SEP) && str.includes(MERGE_CONFLICT_END); -} +module.exports = function () { /* empty */ }; -/** - * Parse the lockfile. - */ -function parse(str, fileLoc) { - const parser = new Parser(str, fileLoc); - parser.next(); - return parser.parse(); -} -/** - * Parse and merge the two variants in a conflicted lockfile. - */ -function parseWithConflict(str, fileLoc) { - const variants = extractConflictVariants(str); - try { - return { type: 'merge', object: Object.assign({}, parse(variants[0], fileLoc), parse(variants[1], fileLoc)) }; - } catch (err) { - if (err instanceof SyntaxError) { - return { type: 'conflict', object: {} }; - } else { - throw err; - } - } -} +/***/ }), +/* 181 */ +/***/ (function(module, exports) { + +module.exports = function (it, Constructor, name, forbiddenField) { + if (!(it instanceof Constructor) || (forbiddenField !== undefined && forbiddenField in it)) { + throw TypeError(name + ': incorrect invocation!'); + } return it; +}; + /***/ }), -/* 82 */, -/* 83 */, -/* 84 */ +/* 182 */ /***/ (function(module, exports, __webpack_require__) { -"use strict"; +// false -> Array#indexOf +// true -> Array#includes +var toIObject = __webpack_require__(74); +var toLength = __webpack_require__(110); +var toAbsoluteIndex = __webpack_require__(200); +module.exports = function (IS_INCLUDES) { + return function ($this, el, fromIndex) { + var O = toIObject($this); + var length = toLength(O.length); + var index = toAbsoluteIndex(fromIndex, length); + var value; + // Array#includes uses SameValueZero equality algorithm + // eslint-disable-next-line no-self-compare + if (IS_INCLUDES && el != el) while (length > index) { + value = O[index++]; + // eslint-disable-next-line no-self-compare + if (value != value) return true; + // Array#indexOf ignores holes, Array#includes - not + } else for (;length > index; index++) if (IS_INCLUDES || index in O) { + if (O[index] === el) return IS_INCLUDES || index || 0; + } return !IS_INCLUDES && -1; + }; +}; -Object.defineProperty(exports, "__esModule", { - value: true -}); +/***/ }), +/* 183 */ +/***/ (function(module, exports, __webpack_require__) { -var _map; +var ctx = __webpack_require__(48); +var call = __webpack_require__(187); +var isArrayIter = __webpack_require__(186); +var anObject = __webpack_require__(27); +var toLength = __webpack_require__(110); +var getIterFn = __webpack_require__(203); +var BREAK = {}; +var RETURN = {}; +var exports = module.exports = function (iterable, entries, fn, that, ITERATOR) { + var iterFn = ITERATOR ? function () { return iterable; } : getIterFn(iterable); + var f = ctx(fn, that, entries ? 2 : 1); + var index = 0; + var length, step, iterator, result; + if (typeof iterFn != 'function') throw TypeError(iterable + ' is not iterable!'); + // fast case for arrays with default iterator + if (isArrayIter(iterFn)) for (length = toLength(iterable.length); length > index; index++) { + result = entries ? f(anObject(step = iterable[index])[0], step[1]) : f(iterable[index]); + if (result === BREAK || result === RETURN) return result; + } else for (iterator = iterFn.call(iterable); !(step = iterator.next()).done;) { + result = call(iterator, f, step.value, entries); + if (result === BREAK || result === RETURN) return result; + } +}; +exports.BREAK = BREAK; +exports.RETURN = RETURN; -function _load_map() { - return _map = _interopRequireDefault(__webpack_require__(20)); -} -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } +/***/ }), +/* 184 */ +/***/ (function(module, exports, __webpack_require__) { -const debug = __webpack_require__(212)('yarn'); +module.exports = !__webpack_require__(33) && !__webpack_require__(85)(function () { + return Object.defineProperty(__webpack_require__(68)('div'), 'a', { get: function () { return 7; } }).a != 7; +}); -class BlockingQueue { - constructor(alias, maxConcurrency = Infinity) { - this.concurrencyQueue = []; - this.maxConcurrency = maxConcurrency; - this.runningCount = 0; - this.warnedStuck = false; - this.alias = alias; - this.first = true; - this.running = (0, (_map || _load_map()).default)(); - this.queue = (0, (_map || _load_map()).default)(); +/***/ }), +/* 185 */ +/***/ (function(module, exports) { - this.stuckTick = this.stuckTick.bind(this); - } +// fast apply, http://jsperf.lnkit.com/fast-apply/5 +module.exports = function (fn, args, that) { + var un = that === undefined; + switch (args.length) { + case 0: return un ? fn() + : fn.call(that); + case 1: return un ? fn(args[0]) + : fn.call(that, args[0]); + case 2: return un ? fn(args[0], args[1]) + : fn.call(that, args[0], args[1]); + case 3: return un ? fn(args[0], args[1], args[2]) + : fn.call(that, args[0], args[1], args[2]); + case 4: return un ? fn(args[0], args[1], args[2], args[3]) + : fn.call(that, args[0], args[1], args[2], args[3]); + } return fn.apply(that, args); +}; - stillActive() { - if (this.stuckTimer) { - clearTimeout(this.stuckTimer); - } - this.stuckTimer = setTimeout(this.stuckTick, 5000); +/***/ }), +/* 186 */ +/***/ (function(module, exports, __webpack_require__) { - // We need to check the existence of unref because of https://github.com/facebook/jest/issues/4559 - // $FlowFixMe: Node's setInterval returns a Timeout, not a Number - this.stuckTimer.unref && this.stuckTimer.unref(); - } +// check on default Array iterator +var Iterators = __webpack_require__(35); +var ITERATOR = __webpack_require__(13)('iterator'); +var ArrayProto = Array.prototype; - stuckTick() { - if (this.runningCount === 1) { - this.warnedStuck = true; - debug(`The ${JSON.stringify(this.alias)} blocking queue may be stuck. 5 seconds ` + `without any activity with 1 worker: ${Object.keys(this.running)[0]}`); - } - } +module.exports = function (it) { + return it !== undefined && (Iterators.Array === it || ArrayProto[ITERATOR] === it); +}; - push(key, factory) { - if (this.first) { - this.first = false; - } else { - this.stillActive(); - } - return new Promise((resolve, reject) => { - // we're already running so push ourselves to the queue - const queue = this.queue[key] = this.queue[key] || []; - queue.push({ factory, resolve, reject }); +/***/ }), +/* 187 */ +/***/ (function(module, exports, __webpack_require__) { - if (!this.running[key]) { - this.shift(key); - } - }); +// call something on iterator step with safe closing on error +var anObject = __webpack_require__(27); +module.exports = function (iterator, fn, value, entries) { + try { + return entries ? fn(anObject(value)[0], value[1]) : fn(value); + // 7.4.6 IteratorClose(iterator, completion) + } catch (e) { + var ret = iterator['return']; + if (ret !== undefined) anObject(ret.call(iterator)); + throw e; } +}; - shift(key) { - if (this.running[key]) { - delete this.running[key]; - this.runningCount--; - - if (this.stuckTimer) { - clearTimeout(this.stuckTimer); - this.stuckTimer = null; - } - if (this.warnedStuck) { - this.warnedStuck = false; - debug(`${JSON.stringify(this.alias)} blocking queue finally resolved. Nothing to worry about.`); - } - } +/***/ }), +/* 188 */ +/***/ (function(module, exports, __webpack_require__) { - const queue = this.queue[key]; - if (!queue) { - return; - } +"use strict"; - var _queue$shift = queue.shift(); +var create = __webpack_require__(192); +var descriptor = __webpack_require__(106); +var setToStringTag = __webpack_require__(71); +var IteratorPrototype = {}; - const resolve = _queue$shift.resolve, - reject = _queue$shift.reject, - factory = _queue$shift.factory; +// 25.1.2.1.1 %IteratorPrototype%[@@iterator]() +__webpack_require__(31)(IteratorPrototype, __webpack_require__(13)('iterator'), function () { return this; }); - if (!queue.length) { - delete this.queue[key]; - } +module.exports = function (Constructor, NAME, next) { + Constructor.prototype = create(IteratorPrototype, { next: descriptor(1, next) }); + setToStringTag(Constructor, NAME + ' Iterator'); +}; - const next = () => { - this.shift(key); - this.shiftConcurrencyQueue(); - }; - const run = () => { - this.running[key] = true; - this.runningCount++; +/***/ }), +/* 189 */ +/***/ (function(module, exports, __webpack_require__) { - factory().then(function (val) { - resolve(val); - next(); - return null; - }).catch(function (err) { - reject(err); - next(); - }); - }; +var ITERATOR = __webpack_require__(13)('iterator'); +var SAFE_CLOSING = false; - this.maybePushConcurrencyQueue(run); - } +try { + var riter = [7][ITERATOR](); + riter['return'] = function () { SAFE_CLOSING = true; }; + // eslint-disable-next-line no-throw-literal + Array.from(riter, function () { throw 2; }); +} catch (e) { /* empty */ } - maybePushConcurrencyQueue(run) { - if (this.runningCount < this.maxConcurrency) { - run(); - } else { - this.concurrencyQueue.push(run); - } - } +module.exports = function (exec, skipClosing) { + if (!skipClosing && !SAFE_CLOSING) return false; + var safe = false; + try { + var arr = [7]; + var iter = arr[ITERATOR](); + iter.next = function () { return { done: safe = true }; }; + arr[ITERATOR] = function () { return iter; }; + exec(arr); + } catch (e) { /* empty */ } + return safe; +}; - shiftConcurrencyQueue() { - if (this.runningCount < this.maxConcurrency) { - const fn = this.concurrencyQueue.shift(); - if (fn) { - fn(); - } - } - } -} -exports.default = BlockingQueue; /***/ }), -/* 85 */ +/* 190 */ /***/ (function(module, exports) { -module.exports = function (exec) { - try { - return !!exec(); - } catch (e) { - return true; - } +module.exports = function (done, value) { + return { value: value, done: !!done }; }; /***/ }), -/* 86 */, -/* 87 */, -/* 88 */, -/* 89 */, -/* 90 */, -/* 91 */, -/* 92 */, -/* 93 */, -/* 94 */, -/* 95 */, -/* 96 */, -/* 97 */, -/* 98 */, -/* 99 */, -/* 100 */ +/* 191 */ /***/ (function(module, exports, __webpack_require__) { -// getting tag from 19.1.3.6 Object.prototype.toString() -var cof = __webpack_require__(47); -var TAG = __webpack_require__(13)('toStringTag'); -// ES3 wrong here -var ARG = cof(function () { return arguments; }()) == 'Arguments'; - -// fallback for IE11 Script Access Denied error -var tryGet = function (it, key) { - try { - return it[key]; - } catch (e) { /* empty */ } -}; +var global = __webpack_require__(11); +var macrotask = __webpack_require__(109).set; +var Observer = global.MutationObserver || global.WebKitMutationObserver; +var process = global.process; +var Promise = global.Promise; +var isNode = __webpack_require__(47)(process) == 'process'; -module.exports = function (it) { - var O, T, B; - return it === undefined ? 'Undefined' : it === null ? 'Null' - // @@toStringTag case - : typeof (T = tryGet(O = Object(it), TAG)) == 'string' ? T - // builtinTag case - : ARG ? cof(O) - // ES3 arguments fallback - : (B = cof(O)) == 'Object' && typeof O.callee == 'function' ? 'Arguments' : B; -}; +module.exports = function () { + var head, last, notify; + var flush = function () { + var parent, fn; + if (isNode && (parent = process.domain)) parent.exit(); + while (head) { + fn = head.fn; + head = head.next; + try { + fn(); + } catch (e) { + if (head) notify(); + else last = undefined; + throw e; + } + } last = undefined; + if (parent) parent.enter(); + }; -/***/ }), -/* 101 */ -/***/ (function(module, exports) { + // Node.js + if (isNode) { + notify = function () { + process.nextTick(flush); + }; + // browsers with MutationObserver, except iOS Safari - https://github.com/zloirock/core-js/issues/339 + } else if (Observer && !(global.navigator && global.navigator.standalone)) { + var toggle = true; + var node = document.createTextNode(''); + new Observer(flush).observe(node, { characterData: true }); // eslint-disable-line no-new + notify = function () { + node.data = toggle = !toggle; + }; + // environments with maybe non-completely correct, but existent Promise + } else if (Promise && Promise.resolve) { + // Promise.resolve without an argument throws an error in LG WebOS 2 + var promise = Promise.resolve(undefined); + notify = function () { + promise.then(flush); + }; + // for other environments - macrotask based on: + // - setImmediate + // - MessageChannel + // - window.postMessag + // - onreadystatechange + // - setTimeout + } else { + notify = function () { + // strange IE + webpack dev server bug - use .call(global) + macrotask.call(global, flush); + }; + } -// IE 8- don't enum bug keys -module.exports = ( - 'constructor,hasOwnProperty,isPrototypeOf,propertyIsEnumerable,toLocaleString,toString,valueOf' -).split(','); + return function (fn) { + var task = { fn: fn, next: undefined }; + if (last) last.next = task; + if (!head) { + head = task; + notify(); + } last = task; + }; +}; /***/ }), -/* 102 */ +/* 192 */ /***/ (function(module, exports, __webpack_require__) { -var document = __webpack_require__(11).document; -module.exports = document && document.documentElement; +// 19.1.2.2 / 15.2.3.5 Object.create(O [, Properties]) +var anObject = __webpack_require__(27); +var dPs = __webpack_require__(193); +var enumBugKeys = __webpack_require__(101); +var IE_PROTO = __webpack_require__(72)('IE_PROTO'); +var Empty = function () { /* empty */ }; +var PROTOTYPE = 'prototype'; +// Create object with fake `null` prototype: use iframe Object with cleared prototype +var createDict = function () { + // Thrash, waste and sodomy: IE GC bug + var iframe = __webpack_require__(68)('iframe'); + var i = enumBugKeys.length; + var lt = '<'; + var gt = '>'; + var iframeDocument; + iframe.style.display = 'none'; + __webpack_require__(102).appendChild(iframe); + iframe.src = 'javascript:'; // eslint-disable-line no-script-url + // createDict = iframe.contentWindow.Object; + // html.removeChild(iframe); + iframeDocument = iframe.contentWindow.document; + iframeDocument.open(); + iframeDocument.write(lt + 'script' + gt + 'document.F=Object' + lt + '/script' + gt); + iframeDocument.close(); + createDict = iframeDocument.F; + while (i--) delete createDict[PROTOTYPE][enumBugKeys[i]]; + return createDict(); +}; -/***/ }), -/* 103 */ -/***/ (function(module, exports, __webpack_require__) { +module.exports = Object.create || function create(O, Properties) { + var result; + if (O !== null) { + Empty[PROTOTYPE] = anObject(O); + result = new Empty(); + Empty[PROTOTYPE] = null; + // add "__proto__" for Object.getPrototypeOf polyfill + result[IE_PROTO] = O; + } else result = createDict(); + return Properties === undefined ? result : dPs(result, Properties); +}; -"use strict"; -var LIBRARY = __webpack_require__(69); -var $export = __webpack_require__(41); -var redefine = __webpack_require__(197); -var hide = __webpack_require__(31); -var Iterators = __webpack_require__(35); -var $iterCreate = __webpack_require__(188); -var setToStringTag = __webpack_require__(71); -var getPrototypeOf = __webpack_require__(194); -var ITERATOR = __webpack_require__(13)('iterator'); -var BUGGY = !([].keys && 'next' in [].keys()); // Safari has buggy iterators w/o `next` -var FF_ITERATOR = '@@iterator'; -var KEYS = 'keys'; -var VALUES = 'values'; +/***/ }), +/* 193 */ +/***/ (function(module, exports, __webpack_require__) { -var returnThis = function () { return this; }; +var dP = __webpack_require__(50); +var anObject = __webpack_require__(27); +var getKeys = __webpack_require__(132); -module.exports = function (Base, NAME, Constructor, next, DEFAULT, IS_SET, FORCED) { - $iterCreate(Constructor, NAME, next); - var getMethod = function (kind) { - if (!BUGGY && kind in proto) return proto[kind]; - switch (kind) { - case KEYS: return function keys() { return new Constructor(this, kind); }; - case VALUES: return function values() { return new Constructor(this, kind); }; - } return function entries() { return new Constructor(this, kind); }; - }; - var TAG = NAME + ' Iterator'; - var DEF_VALUES = DEFAULT == VALUES; - var VALUES_BUG = false; - var proto = Base.prototype; - var $native = proto[ITERATOR] || proto[FF_ITERATOR] || DEFAULT && proto[DEFAULT]; - var $default = $native || getMethod(DEFAULT); - var $entries = DEFAULT ? !DEF_VALUES ? $default : getMethod('entries') : undefined; - var $anyNative = NAME == 'Array' ? proto.entries || $native : $native; - var methods, key, IteratorPrototype; - // Fix native - if ($anyNative) { - IteratorPrototype = getPrototypeOf($anyNative.call(new Base())); - if (IteratorPrototype !== Object.prototype && IteratorPrototype.next) { - // Set @@toStringTag to native iterators - setToStringTag(IteratorPrototype, TAG, true); - // fix for some old engines - if (!LIBRARY && typeof IteratorPrototype[ITERATOR] != 'function') hide(IteratorPrototype, ITERATOR, returnThis); - } - } - // fix Array#{values, @@iterator}.name in V8 / FF - if (DEF_VALUES && $native && $native.name !== VALUES) { - VALUES_BUG = true; - $default = function values() { return $native.call(this); }; - } - // Define iterator - if ((!LIBRARY || FORCED) && (BUGGY || VALUES_BUG || !proto[ITERATOR])) { - hide(proto, ITERATOR, $default); - } - // Plug for library - Iterators[NAME] = $default; - Iterators[TAG] = returnThis; - if (DEFAULT) { - methods = { - values: DEF_VALUES ? $default : getMethod(VALUES), - keys: IS_SET ? $default : getMethod(KEYS), - entries: $entries - }; - if (FORCED) for (key in methods) { - if (!(key in proto)) redefine(proto, key, methods[key]); - } else $export($export.P + $export.F * (BUGGY || VALUES_BUG), NAME, methods); - } - return methods; +module.exports = __webpack_require__(33) ? Object.defineProperties : function defineProperties(O, Properties) { + anObject(O); + var keys = getKeys(Properties); + var length = keys.length; + var i = 0; + var P; + while (length > i) dP.f(O, P = keys[i++], Properties[P]); + return O; }; /***/ }), -/* 104 */ -/***/ (function(module, exports) { +/* 194 */ +/***/ (function(module, exports, __webpack_require__) { -module.exports = function (exec) { - try { - return { e: false, v: exec() }; - } catch (e) { - return { e: true, v: e }; - } +// 19.1.2.9 / 15.2.3.2 Object.getPrototypeOf(O) +var has = __webpack_require__(49); +var toObject = __webpack_require__(133); +var IE_PROTO = __webpack_require__(72)('IE_PROTO'); +var ObjectProto = Object.prototype; + +module.exports = Object.getPrototypeOf || function (O) { + O = toObject(O); + if (has(O, IE_PROTO)) return O[IE_PROTO]; + if (typeof O.constructor == 'function' && O instanceof O.constructor) { + return O.constructor.prototype; + } return O instanceof Object ? ObjectProto : null; }; /***/ }), -/* 105 */ +/* 195 */ /***/ (function(module, exports, __webpack_require__) { -var anObject = __webpack_require__(27); -var isObject = __webpack_require__(34); -var newPromiseCapability = __webpack_require__(70); +var has = __webpack_require__(49); +var toIObject = __webpack_require__(74); +var arrayIndexOf = __webpack_require__(182)(false); +var IE_PROTO = __webpack_require__(72)('IE_PROTO'); -module.exports = function (C, x) { - anObject(C); - if (isObject(x) && x.constructor === C) return x; - var promiseCapability = newPromiseCapability.f(C); - var resolve = promiseCapability.resolve; - resolve(x); - return promiseCapability.promise; +module.exports = function (object, names) { + var O = toIObject(object); + var i = 0; + var result = []; + var key; + for (key in O) if (key != IE_PROTO) has(O, key) && result.push(key); + // Don't enum bug & hidden keys + while (names.length > i) if (has(O, key = names[i++])) { + ~arrayIndexOf(result, key) || result.push(key); + } + return result; }; /***/ }), -/* 106 */ -/***/ (function(module, exports) { +/* 196 */ +/***/ (function(module, exports, __webpack_require__) { -module.exports = function (bitmap, value) { - return { - enumerable: !(bitmap & 1), - configurable: !(bitmap & 2), - writable: !(bitmap & 4), - value: value - }; +var hide = __webpack_require__(31); +module.exports = function (target, src, safe) { + for (var key in src) { + if (safe && target[key]) target[key] = src[key]; + else hide(target, key, src[key]); + } return target; }; /***/ }), -/* 107 */ +/* 197 */ /***/ (function(module, exports, __webpack_require__) { -var core = __webpack_require__(23); -var global = __webpack_require__(11); -var SHARED = '__core-js_shared__'; -var store = global[SHARED] || (global[SHARED] = {}); - -(module.exports = function (key, value) { - return store[key] || (store[key] = value !== undefined ? value : {}); -})('versions', []).push({ - version: core.version, - mode: __webpack_require__(69) ? 'pure' : 'global', - copyright: '© 2018 Denis Pushkarev (zloirock.ru)' -}); +module.exports = __webpack_require__(31); /***/ }), -/* 108 */ +/* 198 */ /***/ (function(module, exports, __webpack_require__) { -// 7.3.20 SpeciesConstructor(O, defaultConstructor) -var anObject = __webpack_require__(27); -var aFunction = __webpack_require__(46); +"use strict"; + +var global = __webpack_require__(11); +var core = __webpack_require__(23); +var dP = __webpack_require__(50); +var DESCRIPTORS = __webpack_require__(33); var SPECIES = __webpack_require__(13)('species'); -module.exports = function (O, D) { - var C = anObject(O).constructor; - var S; - return C === undefined || (S = anObject(C)[SPECIES]) == undefined ? D : aFunction(S); + +module.exports = function (KEY) { + var C = typeof core[KEY] == 'function' ? core[KEY] : global[KEY]; + if (DESCRIPTORS && C && !C[SPECIES]) dP.f(C, SPECIES, { + configurable: true, + get: function () { return this; } + }); }; /***/ }), -/* 109 */ +/* 199 */ /***/ (function(module, exports, __webpack_require__) { -var ctx = __webpack_require__(48); -var invoke = __webpack_require__(185); -var html = __webpack_require__(102); -var cel = __webpack_require__(68); -var global = __webpack_require__(11); -var process = global.process; -var setTask = global.setImmediate; -var clearTask = global.clearImmediate; -var MessageChannel = global.MessageChannel; -var Dispatch = global.Dispatch; -var counter = 0; -var queue = {}; -var ONREADYSTATECHANGE = 'onreadystatechange'; -var defer, channel, port; -var run = function () { - var id = +this; - // eslint-disable-next-line no-prototype-builtins - if (queue.hasOwnProperty(id)) { - var fn = queue[id]; - delete queue[id]; - fn(); - } -}; -var listener = function (event) { - run.call(event.data); -}; -// Node.js 0.9+ & IE10+ has setImmediate, otherwise: -if (!setTask || !clearTask) { - setTask = function setImmediate(fn) { - var args = []; - var i = 1; - while (arguments.length > i) args.push(arguments[i++]); - queue[++counter] = function () { - // eslint-disable-next-line no-new-func - invoke(typeof fn == 'function' ? fn : Function(fn), args); - }; - defer(counter); - return counter; - }; - clearTask = function clearImmediate(id) { - delete queue[id]; +var toInteger = __webpack_require__(73); +var defined = __webpack_require__(67); +// true -> String#at +// false -> String#codePointAt +module.exports = function (TO_STRING) { + return function (that, pos) { + var s = String(defined(that)); + var i = toInteger(pos); + var l = s.length; + var a, b; + if (i < 0 || i >= l) return TO_STRING ? '' : undefined; + a = s.charCodeAt(i); + return a < 0xd800 || a > 0xdbff || i + 1 === l || (b = s.charCodeAt(i + 1)) < 0xdc00 || b > 0xdfff + ? TO_STRING ? s.charAt(i) : a + : TO_STRING ? s.slice(i, i + 2) : (a - 0xd800 << 10) + (b - 0xdc00) + 0x10000; }; - // Node.js 0.8- - if (__webpack_require__(47)(process) == 'process') { - defer = function (id) { - process.nextTick(ctx(run, id, 1)); - }; - // Sphere (JS game engine) Dispatch API - } else if (Dispatch && Dispatch.now) { - defer = function (id) { - Dispatch.now(ctx(run, id, 1)); - }; - // Browsers with MessageChannel, includes WebWorkers - } else if (MessageChannel) { - channel = new MessageChannel(); - port = channel.port2; - channel.port1.onmessage = listener; - defer = ctx(port.postMessage, port, 1); - // Browsers with postMessage, skip WebWorkers - // IE8 has postMessage, but it's sync & typeof its postMessage is 'object' - } else if (global.addEventListener && typeof postMessage == 'function' && !global.importScripts) { - defer = function (id) { - global.postMessage(id + '', '*'); - }; - global.addEventListener('message', listener, false); - // IE8- - } else if (ONREADYSTATECHANGE in cel('script')) { - defer = function (id) { - html.appendChild(cel('script'))[ONREADYSTATECHANGE] = function () { - html.removeChild(this); - run.call(id); - }; - }; - // Rest old browsers - } else { - defer = function (id) { - setTimeout(ctx(run, id, 1), 0); - }; - } -} -module.exports = { - set: setTask, - clear: clearTask }; /***/ }), -/* 110 */ +/* 200 */ /***/ (function(module, exports, __webpack_require__) { -// 7.1.15 ToLength var toInteger = __webpack_require__(73); +var max = Math.max; var min = Math.min; -module.exports = function (it) { - return it > 0 ? min(toInteger(it), 0x1fffffffffffff) : 0; // pow(2, 53) - 1 == 9007199254740991 +module.exports = function (index, length) { + index = toInteger(index); + return index < 0 ? max(index + length, 0) : min(index, length); }; /***/ }), -/* 111 */ -/***/ (function(module, exports) { +/* 201 */ +/***/ (function(module, exports, __webpack_require__) { -var id = 0; -var px = Math.random(); -module.exports = function (key) { - return 'Symbol('.concat(key === undefined ? '' : key, ')_', (++id + px).toString(36)); +// 7.1.1 ToPrimitive(input [, PreferredType]) +var isObject = __webpack_require__(34); +// instead of the ES6 spec version, we didn't implement @@toPrimitive case +// and the second argument - flag - preferred type is a string +module.exports = function (it, S) { + if (!isObject(it)) return it; + var fn, val; + if (S && typeof (fn = it.toString) == 'function' && !isObject(val = fn.call(it))) return val; + if (typeof (fn = it.valueOf) == 'function' && !isObject(val = fn.call(it))) return val; + if (!S && typeof (fn = it.toString) == 'function' && !isObject(val = fn.call(it))) return val; + throw TypeError("Can't convert object to primitive value"); }; /***/ }), -/* 112 */ +/* 202 */ /***/ (function(module, exports, __webpack_require__) { +var global = __webpack_require__(11); +var navigator = global.navigator; -/** - * This is the common logic for both the Node.js and web browser - * implementations of `debug()`. - * - * Expose `debug()` as the module. - */ +module.exports = navigator && navigator.userAgent || ''; -exports = module.exports = createDebug.debug = createDebug['default'] = createDebug; -exports.coerce = coerce; -exports.disable = disable; -exports.enable = enable; -exports.enabled = enabled; -exports.humanize = __webpack_require__(229); -/** - * Active `debug` instances. - */ -exports.instances = []; +/***/ }), +/* 203 */ +/***/ (function(module, exports, __webpack_require__) { -/** - * The currently active debug mode names, and names to skip. - */ +var classof = __webpack_require__(100); +var ITERATOR = __webpack_require__(13)('iterator'); +var Iterators = __webpack_require__(35); +module.exports = __webpack_require__(23).getIteratorMethod = function (it) { + if (it != undefined) return it[ITERATOR] + || it['@@iterator'] + || Iterators[classof(it)]; +}; -exports.names = []; -exports.skips = []; -/** - * Map of special "%n" handling functions, for the debug "format" argument. - * - * Valid key names are a single, lower or upper-case letter, i.e. "n" and "N". - */ - -exports.formatters = {}; +/***/ }), +/* 204 */ +/***/ (function(module, exports, __webpack_require__) { -/** - * Select a color. - * @param {String} namespace - * @return {Number} - * @api private - */ +"use strict"; -function selectColor(namespace) { - var hash = 0, i; +var addToUnscopables = __webpack_require__(180); +var step = __webpack_require__(190); +var Iterators = __webpack_require__(35); +var toIObject = __webpack_require__(74); - for (i in namespace) { - hash = ((hash << 5) - hash) + namespace.charCodeAt(i); - hash |= 0; // Convert to 32bit integer +// 22.1.3.4 Array.prototype.entries() +// 22.1.3.13 Array.prototype.keys() +// 22.1.3.29 Array.prototype.values() +// 22.1.3.30 Array.prototype[@@iterator]() +module.exports = __webpack_require__(103)(Array, 'Array', function (iterated, kind) { + this._t = toIObject(iterated); // target + this._i = 0; // next index + this._k = kind; // kind +// 22.1.5.2.1 %ArrayIteratorPrototype%.next() +}, function () { + var O = this._t; + var kind = this._k; + var index = this._i++; + if (!O || index >= O.length) { + this._t = undefined; + return step(1); } + if (kind == 'keys') return step(0, index); + if (kind == 'values') return step(0, O[index]); + return step(0, [index, O[index]]); +}, 'values'); - return exports.colors[Math.abs(hash) % exports.colors.length]; -} +// argumentsList[@@iterator] is %ArrayProto_values% (9.4.4.6, 9.4.4.7) +Iterators.Arguments = Iterators.Array; -/** - * Create a debugger with the given `namespace`. - * - * @param {String} namespace - * @return {Function} - * @api public - */ +addToUnscopables('keys'); +addToUnscopables('values'); +addToUnscopables('entries'); -function createDebug(namespace) { - var prevTime; +/***/ }), +/* 205 */ +/***/ (function(module, exports) { - function debug() { - // disabled? - if (!debug.enabled) return; - var self = debug; - // set `diff` timestamp - var curr = +new Date(); - var ms = curr - (prevTime || curr); - self.diff = ms; - self.prev = prevTime; - self.curr = curr; - prevTime = curr; +/***/ }), +/* 206 */ +/***/ (function(module, exports, __webpack_require__) { - // turn the `arguments` into a proper Array - var args = new Array(arguments.length); - for (var i = 0; i < args.length; i++) { - args[i] = arguments[i]; - } +"use strict"; - args[0] = exports.coerce(args[0]); +var LIBRARY = __webpack_require__(69); +var global = __webpack_require__(11); +var ctx = __webpack_require__(48); +var classof = __webpack_require__(100); +var $export = __webpack_require__(41); +var isObject = __webpack_require__(34); +var aFunction = __webpack_require__(46); +var anInstance = __webpack_require__(181); +var forOf = __webpack_require__(183); +var speciesConstructor = __webpack_require__(108); +var task = __webpack_require__(109).set; +var microtask = __webpack_require__(191)(); +var newPromiseCapabilityModule = __webpack_require__(70); +var perform = __webpack_require__(104); +var userAgent = __webpack_require__(202); +var promiseResolve = __webpack_require__(105); +var PROMISE = 'Promise'; +var TypeError = global.TypeError; +var process = global.process; +var versions = process && process.versions; +var v8 = versions && versions.v8 || ''; +var $Promise = global[PROMISE]; +var isNode = classof(process) == 'process'; +var empty = function () { /* empty */ }; +var Internal, newGenericPromiseCapability, OwnPromiseCapability, Wrapper; +var newPromiseCapability = newGenericPromiseCapability = newPromiseCapabilityModule.f; - if ('string' !== typeof args[0]) { - // anything else let's inspect with %O - args.unshift('%O'); +var USE_NATIVE = !!function () { + try { + // correct subclassing with @@species support + var promise = $Promise.resolve(1); + var FakePromise = (promise.constructor = {})[__webpack_require__(13)('species')] = function (exec) { + exec(empty, empty); + }; + // unhandled rejections tracking support, NodeJS Promise without it fails @@species test + return (isNode || typeof PromiseRejectionEvent == 'function') + && promise.then(empty) instanceof FakePromise + // v8 6.6 (Node 10 and Chrome 66) have a bug with resolving custom thenables + // https://bugs.chromium.org/p/chromium/issues/detail?id=830565 + // we can't detect it synchronously, so just check versions + && v8.indexOf('6.6') !== 0 + && userAgent.indexOf('Chrome/66') === -1; + } catch (e) { /* empty */ } +}(); + +// helpers +var isThenable = function (it) { + var then; + return isObject(it) && typeof (then = it.then) == 'function' ? then : false; +}; +var notify = function (promise, isReject) { + if (promise._n) return; + promise._n = true; + var chain = promise._c; + microtask(function () { + var value = promise._v; + var ok = promise._s == 1; + var i = 0; + var run = function (reaction) { + var handler = ok ? reaction.ok : reaction.fail; + var resolve = reaction.resolve; + var reject = reaction.reject; + var domain = reaction.domain; + var result, then, exited; + try { + if (handler) { + if (!ok) { + if (promise._h == 2) onHandleUnhandled(promise); + promise._h = 1; + } + if (handler === true) result = value; + else { + if (domain) domain.enter(); + result = handler(value); // may throw + if (domain) { + domain.exit(); + exited = true; + } + } + if (result === reaction.promise) { + reject(TypeError('Promise-chain cycle')); + } else if (then = isThenable(result)) { + then.call(result, resolve, reject); + } else resolve(result); + } else reject(value); + } catch (e) { + if (domain && !exited) domain.exit(); + reject(e); + } + }; + while (chain.length > i) run(chain[i++]); // variable length - can't use forEach + promise._c = []; + promise._n = false; + if (isReject && !promise._h) onUnhandled(promise); + }); +}; +var onUnhandled = function (promise) { + task.call(global, function () { + var value = promise._v; + var unhandled = isUnhandled(promise); + var result, handler, console; + if (unhandled) { + result = perform(function () { + if (isNode) { + process.emit('unhandledRejection', value, promise); + } else if (handler = global.onunhandledrejection) { + handler({ promise: promise, reason: value }); + } else if ((console = global.console) && console.error) { + console.error('Unhandled promise rejection', value); + } + }); + // Browsers should not trigger `rejectionHandled` event if it was handled here, NodeJS - should + promise._h = isNode || isUnhandled(promise) ? 2 : 1; + } promise._a = undefined; + if (unhandled && result.e) throw result.v; + }); +}; +var isUnhandled = function (promise) { + return promise._h !== 1 && (promise._a || promise._c).length === 0; +}; +var onHandleUnhandled = function (promise) { + task.call(global, function () { + var handler; + if (isNode) { + process.emit('rejectionHandled', promise); + } else if (handler = global.onrejectionhandled) { + handler({ promise: promise, reason: promise._v }); + } + }); +}; +var $reject = function (value) { + var promise = this; + if (promise._d) return; + promise._d = true; + promise = promise._w || promise; // unwrap + promise._v = value; + promise._s = 2; + if (!promise._a) promise._a = promise._c.slice(); + notify(promise, true); +}; +var $resolve = function (value) { + var promise = this; + var then; + if (promise._d) return; + promise._d = true; + promise = promise._w || promise; // unwrap + try { + if (promise === value) throw TypeError("Promise can't be resolved itself"); + if (then = isThenable(value)) { + microtask(function () { + var wrapper = { _w: promise, _d: false }; // wrap + try { + then.call(value, ctx($resolve, wrapper, 1), ctx($reject, wrapper, 1)); + } catch (e) { + $reject.call(wrapper, e); + } + }); + } else { + promise._v = value; + promise._s = 1; + notify(promise, false); } + } catch (e) { + $reject.call({ _w: promise, _d: false }, e); // wrap + } +}; - // apply any `formatters` transformations - var index = 0; - args[0] = args[0].replace(/%([a-zA-Z%])/g, function(match, format) { - // if we encounter an escaped % then don't increase the array index - if (match === '%%') return match; - index++; - var formatter = exports.formatters[format]; - if ('function' === typeof formatter) { - var val = args[index]; - match = formatter.call(self, val); +// constructor polyfill +if (!USE_NATIVE) { + // 25.4.3.1 Promise(executor) + $Promise = function Promise(executor) { + anInstance(this, $Promise, PROMISE, '_h'); + aFunction(executor); + Internal.call(this); + try { + executor(ctx($resolve, this, 1), ctx($reject, this, 1)); + } catch (err) { + $reject.call(this, err); + } + }; + // eslint-disable-next-line no-unused-vars + Internal = function Promise(executor) { + this._c = []; // <- awaiting reactions + this._a = undefined; // <- checked in isUnhandled reactions + this._s = 0; // <- state + this._d = false; // <- done + this._v = undefined; // <- value + this._h = 0; // <- rejection state, 0 - default, 1 - handled, 2 - unhandled + this._n = false; // <- notify + }; + Internal.prototype = __webpack_require__(196)($Promise.prototype, { + // 25.4.5.3 Promise.prototype.then(onFulfilled, onRejected) + then: function then(onFulfilled, onRejected) { + var reaction = newPromiseCapability(speciesConstructor(this, $Promise)); + reaction.ok = typeof onFulfilled == 'function' ? onFulfilled : true; + reaction.fail = typeof onRejected == 'function' && onRejected; + reaction.domain = isNode ? process.domain : undefined; + this._c.push(reaction); + if (this._a) this._a.push(reaction); + if (this._s) notify(this, false); + return reaction.promise; + }, + // 25.4.5.1 Promise.prototype.catch(onRejected) + 'catch': function (onRejected) { + return this.then(undefined, onRejected); + } + }); + OwnPromiseCapability = function () { + var promise = new Internal(); + this.promise = promise; + this.resolve = ctx($resolve, promise, 1); + this.reject = ctx($reject, promise, 1); + }; + newPromiseCapabilityModule.f = newPromiseCapability = function (C) { + return C === $Promise || C === Wrapper + ? new OwnPromiseCapability(C) + : newGenericPromiseCapability(C); + }; +} - // now we need to remove `args[index]` since it's inlined in the `format` - args.splice(index, 1); - index--; - } - return match; +$export($export.G + $export.W + $export.F * !USE_NATIVE, { Promise: $Promise }); +__webpack_require__(71)($Promise, PROMISE); +__webpack_require__(198)(PROMISE); +Wrapper = __webpack_require__(23)[PROMISE]; + +// statics +$export($export.S + $export.F * !USE_NATIVE, PROMISE, { + // 25.4.4.5 Promise.reject(r) + reject: function reject(r) { + var capability = newPromiseCapability(this); + var $$reject = capability.reject; + $$reject(r); + return capability.promise; + } +}); +$export($export.S + $export.F * (LIBRARY || !USE_NATIVE), PROMISE, { + // 25.4.4.6 Promise.resolve(x) + resolve: function resolve(x) { + return promiseResolve(LIBRARY && this === Wrapper ? $Promise : this, x); + } +}); +$export($export.S + $export.F * !(USE_NATIVE && __webpack_require__(189)(function (iter) { + $Promise.all(iter)['catch'](empty); +})), PROMISE, { + // 25.4.4.1 Promise.all(iterable) + all: function all(iterable) { + var C = this; + var capability = newPromiseCapability(C); + var resolve = capability.resolve; + var reject = capability.reject; + var result = perform(function () { + var values = []; + var index = 0; + var remaining = 1; + forOf(iterable, false, function (promise) { + var $index = index++; + var alreadyCalled = false; + values.push(undefined); + remaining++; + C.resolve(promise).then(function (value) { + if (alreadyCalled) return; + alreadyCalled = true; + values[$index] = value; + --remaining || resolve(values); + }, reject); + }); + --remaining || resolve(values); + }); + if (result.e) reject(result.v); + return capability.promise; + }, + // 25.4.4.4 Promise.race(iterable) + race: function race(iterable) { + var C = this; + var capability = newPromiseCapability(C); + var reject = capability.reject; + var result = perform(function () { + forOf(iterable, false, function (promise) { + C.resolve(promise).then(capability.resolve, reject); + }); }); + if (result.e) reject(result.v); + return capability.promise; + } +}); - // apply env-specific formatting (colors, etc.) - exports.formatArgs.call(self, args); - var logFn = debug.log || exports.log || console.log.bind(console); - logFn.apply(self, args); - } +/***/ }), +/* 207 */ +/***/ (function(module, exports, __webpack_require__) { - debug.namespace = namespace; - debug.enabled = exports.enabled(namespace); - debug.useColors = exports.useColors(); - debug.color = selectColor(namespace); - debug.destroy = destroy; +"use strict"; - // env-specific initialization logic for debug instances - if ('function' === typeof exports.init) { - exports.init(debug); - } +var $at = __webpack_require__(199)(true); - exports.instances.push(debug); +// 21.1.3.27 String.prototype[@@iterator]() +__webpack_require__(103)(String, 'String', function (iterated) { + this._t = String(iterated); // target + this._i = 0; // next index +// 21.1.5.2.1 %StringIteratorPrototype%.next() +}, function () { + var O = this._t; + var index = this._i; + var point; + if (index >= O.length) return { value: undefined, done: true }; + point = $at(O, index); + this._i += point.length; + return { value: point, done: false }; +}); - return debug; -} -function destroy () { - var index = exports.instances.indexOf(this); - if (index !== -1) { - exports.instances.splice(index, 1); - return true; - } else { - return false; - } -} +/***/ }), +/* 208 */ +/***/ (function(module, exports, __webpack_require__) { -/** - * Enables a debug mode by namespaces. This can include modes - * separated by a colon and wildcards. - * - * @param {String} namespaces - * @api public - */ +"use strict"; +// https://github.com/tc39/proposal-promise-finally -function enable(namespaces) { - exports.save(namespaces); +var $export = __webpack_require__(41); +var core = __webpack_require__(23); +var global = __webpack_require__(11); +var speciesConstructor = __webpack_require__(108); +var promiseResolve = __webpack_require__(105); - exports.names = []; - exports.skips = []; +$export($export.P + $export.R, 'Promise', { 'finally': function (onFinally) { + var C = speciesConstructor(this, core.Promise || global.Promise); + var isFunction = typeof onFinally == 'function'; + return this.then( + isFunction ? function (x) { + return promiseResolve(C, onFinally()).then(function () { return x; }); + } : onFinally, + isFunction ? function (e) { + return promiseResolve(C, onFinally()).then(function () { throw e; }); + } : onFinally + ); +} }); - var i; - var split = (typeof namespaces === 'string' ? namespaces : '').split(/[\s,]+/); - var len = split.length; - for (i = 0; i < len; i++) { - if (!split[i]) continue; // ignore empty strings - namespaces = split[i].replace(/\*/g, '.*?'); - if (namespaces[0] === '-') { - exports.skips.push(new RegExp('^' + namespaces.substr(1) + '$')); - } else { - exports.names.push(new RegExp('^' + namespaces + '$')); - } - } +/***/ }), +/* 209 */ +/***/ (function(module, exports, __webpack_require__) { - for (i = 0; i < exports.instances.length; i++) { - var instance = exports.instances[i]; - instance.enabled = exports.enabled(instance.namespace); - } -} +"use strict"; -/** - * Disable debug output. - * - * @api public - */ +// https://github.com/tc39/proposal-promise-try +var $export = __webpack_require__(41); +var newPromiseCapability = __webpack_require__(70); +var perform = __webpack_require__(104); -function disable() { - exports.enable(''); -} +$export($export.S, 'Promise', { 'try': function (callbackfn) { + var promiseCapability = newPromiseCapability.f(this); + var result = perform(callbackfn); + (result.e ? promiseCapability.reject : promiseCapability.resolve)(result.v); + return promiseCapability.promise; +} }); -/** - * Returns true if the given mode name is enabled, false otherwise. - * - * @param {String} name - * @return {Boolean} - * @api public - */ -function enabled(name) { - if (name[name.length - 1] === '*') { - return true; - } - var i, len; - for (i = 0, len = exports.skips.length; i < len; i++) { - if (exports.skips[i].test(name)) { - return false; - } - } - for (i = 0, len = exports.names.length; i < len; i++) { - if (exports.names[i].test(name)) { - return true; - } - } - return false; -} +/***/ }), +/* 210 */ +/***/ (function(module, exports, __webpack_require__) { -/** - * Coerce `val`. - * - * @param {Mixed} val - * @return {Mixed} - * @api private - */ +__webpack_require__(204); +var global = __webpack_require__(11); +var hide = __webpack_require__(31); +var Iterators = __webpack_require__(35); +var TO_STRING_TAG = __webpack_require__(13)('toStringTag'); -function coerce(val) { - if (val instanceof Error) return val.stack || val.message; - return val; +var DOMIterables = ('CSSRuleList,CSSStyleDeclaration,CSSValueList,ClientRectList,DOMRectList,DOMStringList,' + + 'DOMTokenList,DataTransferItemList,FileList,HTMLAllCollection,HTMLCollection,HTMLFormElement,HTMLSelectElement,' + + 'MediaList,MimeTypeArray,NamedNodeMap,NodeList,PaintRequestList,Plugin,PluginArray,SVGLengthList,SVGNumberList,' + + 'SVGPathSegList,SVGPointList,SVGStringList,SVGTransformList,SourceBufferList,StyleSheetList,TextTrackCueList,' + + 'TextTrackList,TouchList').split(','); + +for (var i = 0; i < DOMIterables.length; i++) { + var NAME = DOMIterables[i]; + var Collection = global[NAME]; + var proto = Collection && Collection.prototype; + if (proto && !proto[TO_STRING_TAG]) hide(proto, TO_STRING_TAG, NAME); + Iterators[NAME] = Iterators.Array; } /***/ }), -/* 113 */, -/* 114 */ +/* 211 */ /***/ (function(module, exports, __webpack_require__) { -module.exports = realpath -realpath.realpath = realpath -realpath.sync = realpathSync -realpath.realpathSync = realpathSync -realpath.monkeypatch = monkeypatch -realpath.unmonkeypatch = unmonkeypatch +/** + * This is the web browser implementation of `debug()`. + * + * Expose `debug()` as the module. + */ -var fs = __webpack_require__(3) -var origRealpath = fs.realpath -var origRealpathSync = fs.realpathSync +exports = module.exports = __webpack_require__(112); +exports.log = log; +exports.formatArgs = formatArgs; +exports.save = save; +exports.load = load; +exports.useColors = useColors; +exports.storage = 'undefined' != typeof chrome + && 'undefined' != typeof chrome.storage + ? chrome.storage.local + : localstorage(); -var version = process.version -var ok = /^v[0-5]\./.test(version) -var old = __webpack_require__(217) +/** + * Colors. + */ -function newError (er) { - return er && er.syscall === 'realpath' && ( - er.code === 'ELOOP' || - er.code === 'ENOMEM' || - er.code === 'ENAMETOOLONG' - ) -} +exports.colors = [ + '#0000CC', '#0000FF', '#0033CC', '#0033FF', '#0066CC', '#0066FF', '#0099CC', + '#0099FF', '#00CC00', '#00CC33', '#00CC66', '#00CC99', '#00CCCC', '#00CCFF', + '#3300CC', '#3300FF', '#3333CC', '#3333FF', '#3366CC', '#3366FF', '#3399CC', + '#3399FF', '#33CC00', '#33CC33', '#33CC66', '#33CC99', '#33CCCC', '#33CCFF', + '#6600CC', '#6600FF', '#6633CC', '#6633FF', '#66CC00', '#66CC33', '#9900CC', + '#9900FF', '#9933CC', '#9933FF', '#99CC00', '#99CC33', '#CC0000', '#CC0033', + '#CC0066', '#CC0099', '#CC00CC', '#CC00FF', '#CC3300', '#CC3333', '#CC3366', + '#CC3399', '#CC33CC', '#CC33FF', '#CC6600', '#CC6633', '#CC9900', '#CC9933', + '#CCCC00', '#CCCC33', '#FF0000', '#FF0033', '#FF0066', '#FF0099', '#FF00CC', + '#FF00FF', '#FF3300', '#FF3333', '#FF3366', '#FF3399', '#FF33CC', '#FF33FF', + '#FF6600', '#FF6633', '#FF9900', '#FF9933', '#FFCC00', '#FFCC33' +]; -function realpath (p, cache, cb) { - if (ok) { - return origRealpath(p, cache, cb) +/** + * Currently only WebKit-based Web Inspectors, Firefox >= v31, + * and the Firebug extension (any Firefox version) are known + * to support "%c" CSS customizations. + * + * TODO: add a `localStorage` variable to explicitly enable/disable colors + */ + +function useColors() { + // NB: In an Electron preload script, document will be defined but not fully + // initialized. Since we know we're in Chrome, we'll just detect this case + // explicitly + if (typeof window !== 'undefined' && window.process && window.process.type === 'renderer') { + return true; } - if (typeof cache === 'function') { - cb = cache - cache = null + // Internet Explorer and Edge do not support colors. + if (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/(edge|trident)\/(\d+)/)) { + return false; } - origRealpath(p, cache, function (er, result) { - if (newError(er)) { - old.realpath(p, cache, cb) - } else { - cb(er, result) - } - }) + + // is webkit? http://stackoverflow.com/a/16459606/376773 + // document is undefined in react-native: https://github.com/facebook/react-native/pull/1632 + return (typeof document !== 'undefined' && document.documentElement && document.documentElement.style && document.documentElement.style.WebkitAppearance) || + // is firebug? http://stackoverflow.com/a/398120/376773 + (typeof window !== 'undefined' && window.console && (window.console.firebug || (window.console.exception && window.console.table))) || + // is firefox >= v31? + // https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages + (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/) && parseInt(RegExp.$1, 10) >= 31) || + // double check webkit in userAgent just in case we are in a worker + (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/applewebkit\/(\d+)/)); } -function realpathSync (p, cache) { - if (ok) { - return origRealpathSync(p, cache) - } +/** + * Map %j to `JSON.stringify()`, since no Web Inspectors do that by default. + */ +exports.formatters.j = function(v) { try { - return origRealpathSync(p, cache) - } catch (er) { - if (newError(er)) { - return old.realpathSync(p, cache) - } else { - throw er - } + return JSON.stringify(v); + } catch (err) { + return '[UnexpectedJSONParseError]: ' + err.message; } -} +}; -function monkeypatch () { - fs.realpath = realpath - fs.realpathSync = realpathSync -} -function unmonkeypatch () { - fs.realpath = origRealpath - fs.realpathSync = origRealpathSync -} +/** + * Colorize log arguments if enabled. + * + * @api public + */ +function formatArgs(args) { + var useColors = this.useColors; -/***/ }), -/* 115 */ -/***/ (function(module, exports, __webpack_require__) { + args[0] = (useColors ? '%c' : '') + + this.namespace + + (useColors ? ' %c' : ' ') + + args[0] + + (useColors ? '%c ' : ' ') + + '+' + exports.humanize(this.diff); -exports.alphasort = alphasort -exports.alphasorti = alphasorti -exports.setopts = setopts -exports.ownProp = ownProp -exports.makeAbs = makeAbs -exports.finish = finish -exports.mark = mark -exports.isIgnored = isIgnored -exports.childrenIgnored = childrenIgnored + if (!useColors) return; -function ownProp (obj, field) { - return Object.prototype.hasOwnProperty.call(obj, field) + var c = 'color: ' + this.color; + args.splice(1, 0, c, 'color: inherit') + + // the final "%c" is somewhat tricky, because there could be other + // arguments passed either before or after the %c, so we need to + // figure out the correct index to insert the CSS into + var index = 0; + var lastC = 0; + args[0].replace(/%[a-zA-Z%]/g, function(match) { + if ('%%' === match) return; + index++; + if ('%c' === match) { + // we only are interested in the *last* %c + // (the user may have provided their own) + lastC = index; + } + }); + + args.splice(lastC, 0, c); } -var path = __webpack_require__(0) -var minimatch = __webpack_require__(60) -var isAbsolute = __webpack_require__(76) -var Minimatch = minimatch.Minimatch +/** + * Invokes `console.log()` when available. + * No-op when `console.log` is not a "function". + * + * @api public + */ -function alphasorti (a, b) { - return a.toLowerCase().localeCompare(b.toLowerCase()) +function log() { + // this hackery is required for IE8/9, where + // the `console.log` function doesn't have 'apply' + return 'object' === typeof console + && console.log + && Function.prototype.apply.call(console.log, console, arguments); } -function alphasort (a, b) { - return a.localeCompare(b) +/** + * Save `namespaces`. + * + * @param {String} namespaces + * @api private + */ + +function save(namespaces) { + try { + if (null == namespaces) { + exports.storage.removeItem('debug'); + } else { + exports.storage.debug = namespaces; + } + } catch(e) {} } -function setupIgnores (self, options) { - self.ignore = options.ignore || [] +/** + * Load `namespaces`. + * + * @return {String} returns the previously persisted debug modes + * @api private + */ - if (!Array.isArray(self.ignore)) - self.ignore = [self.ignore] +function load() { + var r; + try { + r = exports.storage.debug; + } catch(e) {} - if (self.ignore.length) { - self.ignore = self.ignore.map(ignoreMap) + // If debug isn't set in LS, and we're in Electron, try to load $DEBUG + if (!r && typeof process !== 'undefined' && 'env' in process) { + r = process.env.DEBUG; } + + return r; } -// ignore patterns are always in dot:true mode. -function ignoreMap (pattern) { - var gmatcher = null - if (pattern.slice(-3) === '/**') { - var gpattern = pattern.replace(/(\/\*\*)+$/, '') - gmatcher = new Minimatch(gpattern, { dot: true }) - } +/** + * Enable namespaces listed in `localStorage.debug` initially. + */ - return { - matcher: new Minimatch(pattern, { dot: true }), - gmatcher: gmatcher - } -} +exports.enable(load()); -function setopts (self, pattern, options) { - if (!options) - options = {} +/** + * Localstorage attempts to return the localstorage. + * + * This is necessary because safari throws + * when a user disables cookies/localstorage + * and you attempt to access it. + * + * @return {LocalStorage} + * @api private + */ - // base-matching: just use globstar for that. - if (options.matchBase && -1 === pattern.indexOf("/")) { - if (options.noglobstar) { - throw new Error("base matching requires globstar") - } - pattern = "**/" + pattern - } +function localstorage() { + try { + return window.localStorage; + } catch (e) {} +} - self.silent = !!options.silent - self.pattern = pattern - self.strict = options.strict !== false - self.realpath = !!options.realpath - self.realpathCache = options.realpathCache || Object.create(null) - self.follow = !!options.follow - self.dot = !!options.dot - self.mark = !!options.mark - self.nodir = !!options.nodir - if (self.nodir) - self.mark = true - self.sync = !!options.sync - self.nounique = !!options.nounique - self.nonull = !!options.nonull - self.nosort = !!options.nosort - self.nocase = !!options.nocase - self.stat = !!options.stat - self.noprocess = !!options.noprocess - self.absolute = !!options.absolute - self.maxLength = options.maxLength || Infinity - self.cache = options.cache || Object.create(null) - self.statCache = options.statCache || Object.create(null) - self.symlinks = options.symlinks || Object.create(null) +/***/ }), +/* 212 */ +/***/ (function(module, exports, __webpack_require__) { - setupIgnores(self, options) +/** + * Detect Electron renderer process, which is node, but we should + * treat as a browser. + */ - self.changedCwd = false - var cwd = process.cwd() - if (!ownProp(options, "cwd")) - self.cwd = cwd - else { - self.cwd = path.resolve(options.cwd) - self.changedCwd = self.cwd !== cwd - } +if (typeof process === 'undefined' || process.type === 'renderer') { + module.exports = __webpack_require__(211); +} else { + module.exports = __webpack_require__(213); +} - self.root = options.root || path.resolve(self.cwd, "/") - self.root = path.resolve(self.root) - if (process.platform === "win32") - self.root = self.root.replace(/\\/g, "/") - // TODO: is an absolute `cwd` supposed to be resolved against `root`? - // e.g. { cwd: '/test', root: __dirname } === path.join(__dirname, '/test') - self.cwdAbs = isAbsolute(self.cwd) ? self.cwd : makeAbs(self, self.cwd) - if (process.platform === "win32") - self.cwdAbs = self.cwdAbs.replace(/\\/g, "/") - self.nomount = !!options.nomount +/***/ }), +/* 213 */ +/***/ (function(module, exports, __webpack_require__) { - // disable comments and negation in Minimatch. - // Note that they are not supported in Glob itself anyway. - options.nonegate = true - options.nocomment = true +/** + * Module dependencies. + */ - self.minimatch = new Minimatch(pattern, options) - self.options = self.minimatch.options -} +var tty = __webpack_require__(79); +var util = __webpack_require__(2); -function finish (self) { - var nou = self.nounique - var all = nou ? [] : Object.create(null) +/** + * This is the Node.js implementation of `debug()`. + * + * Expose `debug()` as the module. + */ - for (var i = 0, l = self.matches.length; i < l; i ++) { - var matches = self.matches[i] - if (!matches || Object.keys(matches).length === 0) { - if (self.nonull) { - // do like the shell, and spit out the literal glob - var literal = self.minimatch.globSet[i] - if (nou) - all.push(literal) - else - all[literal] = true - } - } else { - // had matches - var m = Object.keys(matches) - if (nou) - all.push.apply(all, m) - else - m.forEach(function (m) { - all[m] = true - }) - } - } +exports = module.exports = __webpack_require__(112); +exports.init = init; +exports.log = log; +exports.formatArgs = formatArgs; +exports.save = save; +exports.load = load; +exports.useColors = useColors; - if (!nou) - all = Object.keys(all) +/** + * Colors. + */ - if (!self.nosort) - all = all.sort(self.nocase ? alphasorti : alphasort) +exports.colors = [ 6, 2, 3, 4, 5, 1 ]; - // at *some* point we statted all of these - if (self.mark) { - for (var i = 0; i < all.length; i++) { - all[i] = self._mark(all[i]) - } - if (self.nodir) { - all = all.filter(function (e) { - var notDir = !(/\/$/.test(e)) - var c = self.cache[e] || self.cache[makeAbs(self, e)] - if (notDir && c) - notDir = c !== 'DIR' && !Array.isArray(c) - return notDir - }) - } +try { + var supportsColor = __webpack_require__(239); + if (supportsColor && supportsColor.level >= 2) { + exports.colors = [ + 20, 21, 26, 27, 32, 33, 38, 39, 40, 41, 42, 43, 44, 45, 56, 57, 62, 63, 68, + 69, 74, 75, 76, 77, 78, 79, 80, 81, 92, 93, 98, 99, 112, 113, 128, 129, 134, + 135, 148, 149, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, + 172, 173, 178, 179, 184, 185, 196, 197, 198, 199, 200, 201, 202, 203, 204, + 205, 206, 207, 208, 209, 214, 215, 220, 221 + ]; } +} catch (err) { + // swallow - we only care if `supports-color` is available; it doesn't have to be. +} - if (self.ignore.length) - all = all.filter(function(m) { - return !isIgnored(self, m) - }) +/** + * Build up the default `inspectOpts` object from the environment variables. + * + * $ DEBUG_COLORS=no DEBUG_DEPTH=10 DEBUG_SHOW_HIDDEN=enabled node script.js + */ - self.found = all -} +exports.inspectOpts = Object.keys(process.env).filter(function (key) { + return /^debug_/i.test(key); +}).reduce(function (obj, key) { + // camel-case + var prop = key + .substring(6) + .toLowerCase() + .replace(/_([a-z])/g, function (_, k) { return k.toUpperCase() }); -function mark (self, p) { - var abs = makeAbs(self, p) - var c = self.cache[abs] - var m = p - if (c) { - var isDir = c === 'DIR' || Array.isArray(c) - var slash = p.slice(-1) === '/' + // coerce string value into JS value + var val = process.env[key]; + if (/^(yes|on|true|enabled)$/i.test(val)) val = true; + else if (/^(no|off|false|disabled)$/i.test(val)) val = false; + else if (val === 'null') val = null; + else val = Number(val); - if (isDir && !slash) - m += '/' - else if (!isDir && slash) - m = m.slice(0, -1) + obj[prop] = val; + return obj; +}, {}); - if (m !== p) { - var mabs = makeAbs(self, m) - self.statCache[mabs] = self.statCache[abs] - self.cache[mabs] = self.cache[abs] - } - } +/** + * Is stdout a TTY? Colored output is enabled when `true`. + */ - return m +function useColors() { + return 'colors' in exports.inspectOpts + ? Boolean(exports.inspectOpts.colors) + : tty.isatty(process.stderr.fd); } -// lotta situps... -function makeAbs (self, f) { - var abs = f - if (f.charAt(0) === '/') { - abs = path.join(self.root, f) - } else if (isAbsolute(f) || f === '') { - abs = f - } else if (self.changedCwd) { - abs = path.resolve(self.cwd, f) - } else { - abs = path.resolve(f) - } +/** + * Map %o to `util.inspect()`, all on a single line. + */ - if (process.platform === 'win32') - abs = abs.replace(/\\/g, '/') +exports.formatters.o = function(v) { + this.inspectOpts.colors = this.useColors; + return util.inspect(v, this.inspectOpts) + .split('\n').map(function(str) { + return str.trim() + }).join(' '); +}; - return abs -} +/** + * Map %o to `util.inspect()`, allowing multiple lines if needed. + */ +exports.formatters.O = function(v) { + this.inspectOpts.colors = this.useColors; + return util.inspect(v, this.inspectOpts); +}; -// Return true, if pattern ends with globstar '**', for the accompanying parent directory. -// Ex:- If node_modules/** is the pattern, add 'node_modules' to ignore list along with it's contents -function isIgnored (self, path) { - if (!self.ignore.length) - return false +/** + * Adds ANSI color escape codes if enabled. + * + * @api public + */ - return self.ignore.some(function(item) { - return item.matcher.match(path) || !!(item.gmatcher && item.gmatcher.match(path)) - }) -} +function formatArgs(args) { + var name = this.namespace; + var useColors = this.useColors; -function childrenIgnored (self, path) { - if (!self.ignore.length) - return false + if (useColors) { + var c = this.color; + var colorCode = '\u001b[3' + (c < 8 ? c : '8;5;' + c); + var prefix = ' ' + colorCode + ';1m' + name + ' ' + '\u001b[0m'; - return self.ignore.some(function(item) { - return !!(item.gmatcher && item.gmatcher.match(path)) - }) + args[0] = prefix + args[0].split('\n').join('\n' + prefix); + args.push(colorCode + 'm+' + exports.humanize(this.diff) + '\u001b[0m'); + } else { + args[0] = getDate() + name + ' ' + args[0]; + } } +function getDate() { + if (exports.inspectOpts.hideDate) { + return ''; + } else { + return new Date().toISOString() + ' '; + } +} -/***/ }), -/* 116 */ -/***/ (function(module, exports, __webpack_require__) { +/** + * Invokes `util.format()` with the specified arguments and writes to stderr. + */ -var path = __webpack_require__(0); -var fs = __webpack_require__(3); -var _0777 = parseInt('0777', 8); +function log() { + return process.stderr.write(util.format.apply(util, arguments) + '\n'); +} -module.exports = mkdirP.mkdirp = mkdirP.mkdirP = mkdirP; +/** + * Save `namespaces`. + * + * @param {String} namespaces + * @api private + */ -function mkdirP (p, opts, f, made) { - if (typeof opts === 'function') { - f = opts; - opts = {}; - } - else if (!opts || typeof opts !== 'object') { - opts = { mode: opts }; - } - - var mode = opts.mode; - var xfs = opts.fs || fs; - - if (mode === undefined) { - mode = _0777 & (~process.umask()); - } - if (!made) made = null; - - var cb = f || function () {}; - p = path.resolve(p); - - xfs.mkdir(p, mode, function (er) { - if (!er) { - made = made || p; - return cb(null, made); - } - switch (er.code) { - case 'ENOENT': - mkdirP(path.dirname(p), opts, function (er, made) { - if (er) cb(er, made); - else mkdirP(p, opts, cb, made); - }); - break; +function save(namespaces) { + if (null == namespaces) { + // If you set a process.env field to null or undefined, it gets cast to the + // string 'null' or 'undefined'. Just delete instead. + delete process.env.DEBUG; + } else { + process.env.DEBUG = namespaces; + } +} - // In the case of any other error, just see if there's a dir - // there already. If so, then hooray! If not, then something - // is borked. - default: - xfs.stat(p, function (er2, stat) { - // if the stat fails, then that's super weird. - // let the original error be the failure reason. - if (er2 || !stat.isDirectory()) cb(er, made) - else cb(null, made); - }); - break; - } - }); +/** + * Load `namespaces`. + * + * @return {String} returns the previously persisted debug modes + * @api private + */ + +function load() { + return process.env.DEBUG; } -mkdirP.sync = function sync (p, opts, made) { - if (!opts || typeof opts !== 'object') { - opts = { mode: opts }; - } - - var mode = opts.mode; - var xfs = opts.fs || fs; - - if (mode === undefined) { - mode = _0777 & (~process.umask()); - } - if (!made) made = null; +/** + * Init logic for `debug` instances. + * + * Create a new `inspectOpts` object in case `useColors` is set + * differently for a particular `debug` instance. + */ - p = path.resolve(p); +function init (debug) { + debug.inspectOpts = {}; - try { - xfs.mkdirSync(p, mode); - made = made || p; - } - catch (err0) { - switch (err0.code) { - case 'ENOENT' : - made = sync(path.dirname(p), opts, made); - sync(p, opts, made); - break; + var keys = Object.keys(exports.inspectOpts); + for (var i = 0; i < keys.length; i++) { + debug.inspectOpts[keys[i]] = exports.inspectOpts[keys[i]]; + } +} - // In the case of any other error, just see if there's a dir - // there already. If so, then hooray! If not, then something - // is borked. - default: - var stat; - try { - stat = xfs.statSync(p); - } - catch (err1) { - throw err0; - } - if (!stat.isDirectory()) throw err0; - break; - } - } +/** + * Enable namespaces listed in `process.env.DEBUG` initially. + */ - return made; -}; +exports.enable(load()); /***/ }), -/* 117 */, -/* 118 */, -/* 119 */, -/* 120 */, -/* 121 */, -/* 122 */ +/* 214 */, +/* 215 */, +/* 216 */, +/* 217 */ /***/ (function(module, exports, __webpack_require__) { -"use strict"; - -module.exports = x => { - if (typeof x !== 'string') { - throw new TypeError('Expected a string, got ' + typeof x); - } - - // Catches EFBBBF (UTF-8 BOM) because the buffer-to-string - // conversion translates it to FEFF (UTF-16 BOM) - if (x.charCodeAt(0) === 0xFEFF) { - return x.slice(1); - } - - return x; -}; - +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. -/***/ }), -/* 123 */ -/***/ (function(module, exports) { +var pathModule = __webpack_require__(0); +var isWindows = process.platform === 'win32'; +var fs = __webpack_require__(3); -// Returns a wrapper function that returns a wrapped callback -// The wrapper function should do some stuff, and return a -// presumably different callback function. -// This makes sure that own properties are retained, so that -// decorations and such are not lost along the way. -module.exports = wrappy -function wrappy (fn, cb) { - if (fn && cb) return wrappy(fn)(cb) +// JavaScript implementation of realpath, ported from node pre-v6 - if (typeof fn !== 'function') - throw new TypeError('need wrapper function') +var DEBUG = process.env.NODE_DEBUG && /fs/.test(process.env.NODE_DEBUG); - Object.keys(fn).forEach(function (k) { - wrapper[k] = fn[k] - }) +function rethrow() { + // Only enable in debug mode. A backtrace uses ~1000 bytes of heap space and + // is fairly slow to generate. + var callback; + if (DEBUG) { + var backtrace = new Error; + callback = debugCallback; + } else + callback = missingCallback; - return wrapper + return callback; - function wrapper() { - var args = new Array(arguments.length) - for (var i = 0; i < args.length; i++) { - args[i] = arguments[i] + function debugCallback(err) { + if (err) { + backtrace.message = err.message; + err = backtrace; + missingCallback(err); } - var ret = fn.apply(this, args) - var cb = args[args.length-1] - if (typeof ret === 'function' && ret !== cb) { - Object.keys(cb).forEach(function (k) { - ret[k] = cb[k] - }) + } + + function missingCallback(err) { + if (err) { + if (process.throwDeprecation) + throw err; // Forgot a callback but don't know where? Use NODE_DEBUG=fs + else if (!process.noDeprecation) { + var msg = 'fs: missing callback ' + (err.stack || err.message); + if (process.traceDeprecation) + console.trace(msg); + else + console.error(msg); + } } - return ret } } +function maybeCallback(cb) { + return typeof cb === 'function' ? cb : rethrow(); +} -/***/ }), -/* 124 */, -/* 125 */, -/* 126 */, -/* 127 */, -/* 128 */, -/* 129 */, -/* 130 */, -/* 131 */ -/***/ (function(module, exports, __webpack_require__) { +var normalize = pathModule.normalize; -// fallback for non-array-like ES3 and non-enumerable old V8 strings -var cof = __webpack_require__(47); -// eslint-disable-next-line no-prototype-builtins -module.exports = Object('z').propertyIsEnumerable(0) ? Object : function (it) { - return cof(it) == 'String' ? it.split('') : Object(it); -}; +// Regexp that finds the next partion of a (partial) path +// result is [base_with_slash, base], e.g. ['somedir/', 'somedir'] +if (isWindows) { + var nextPartRe = /(.*?)(?:[\/\\]+|$)/g; +} else { + var nextPartRe = /(.*?)(?:[\/]+|$)/g; +} +// Regex to find the device root, including trailing slash. E.g. 'c:\\'. +if (isWindows) { + var splitRootRe = /^(?:[a-zA-Z]:|[\\\/]{2}[^\\\/]+[\\\/][^\\\/]+)?[\\\/]*/; +} else { + var splitRootRe = /^[\/]*/; +} -/***/ }), -/* 132 */ -/***/ (function(module, exports, __webpack_require__) { +exports.realpathSync = function realpathSync(p, cache) { + // make p is absolute + p = pathModule.resolve(p); -// 19.1.2.14 / 15.2.3.14 Object.keys(O) -var $keys = __webpack_require__(195); -var enumBugKeys = __webpack_require__(101); + if (cache && Object.prototype.hasOwnProperty.call(cache, p)) { + return cache[p]; + } -module.exports = Object.keys || function keys(O) { - return $keys(O, enumBugKeys); -}; + var original = p, + seenLinks = {}, + knownHard = {}; + // current character position in p + var pos; + // the partial path so far, including a trailing slash if any + var current; + // the partial path without a trailing slash (except when pointing at a root) + var base; + // the partial path scanned in the previous round, with slash + var previous; -/***/ }), -/* 133 */ -/***/ (function(module, exports, __webpack_require__) { + start(); -// 7.1.13 ToObject(argument) -var defined = __webpack_require__(67); -module.exports = function (it) { - return Object(defined(it)); -}; + function start() { + // Skip over roots + var m = splitRootRe.exec(p); + pos = m[0].length; + current = m[0]; + base = m[0]; + previous = ''; + // On windows, check that the root exists. On unix there is no need. + if (isWindows && !knownHard[base]) { + fs.lstatSync(base); + knownHard[base] = true; + } + } -/***/ }), -/* 134 */, -/* 135 */, -/* 136 */, -/* 137 */, -/* 138 */, -/* 139 */, -/* 140 */, -/* 141 */, -/* 142 */, -/* 143 */, -/* 144 */, -/* 145 */ -/***/ (function(module, exports) { + // walk down the path, swapping out linked pathparts for their real + // values + // NB: p.length changes. + while (pos < p.length) { + // find the next part + nextPartRe.lastIndex = pos; + var result = nextPartRe.exec(p); + previous = current; + current += result[0]; + base = previous + result[1]; + pos = nextPartRe.lastIndex; -module.exports = {"name":"yarn","installationMethod":"unknown","version":"1.10.0-0","license":"BSD-2-Clause","preferGlobal":true,"description":"📦🐈 Fast, reliable, and secure dependency management.","dependencies":{"@zkochan/cmd-shim":"^2.2.4","babel-runtime":"^6.26.0","bytes":"^3.0.0","camelcase":"^4.0.0","chalk":"^2.1.0","commander":"^2.9.0","death":"^1.0.0","debug":"^3.0.0","deep-equal":"^1.0.1","detect-indent":"^5.0.0","dnscache":"^1.0.1","glob":"^7.1.1","gunzip-maybe":"^1.4.0","hash-for-dep":"^1.2.3","imports-loader":"^0.8.0","ini":"^1.3.4","inquirer":"^3.0.1","invariant":"^2.2.0","is-builtin-module":"^2.0.0","is-ci":"^1.0.10","is-webpack-bundle":"^1.0.0","leven":"^2.0.0","loud-rejection":"^1.2.0","micromatch":"^2.3.11","mkdirp":"^0.5.1","node-emoji":"^1.6.1","normalize-url":"^2.0.0","npm-logical-tree":"^1.2.1","object-path":"^0.11.2","proper-lockfile":"^2.0.0","puka":"^1.0.0","read":"^1.0.7","request":"^2.87.0","request-capture-har":"^1.2.2","rimraf":"^2.5.0","semver":"^5.1.0","ssri":"^5.3.0","strip-ansi":"^4.0.0","strip-bom":"^3.0.0","tar-fs":"^1.16.0","tar-stream":"^1.6.1","uuid":"^3.0.1","v8-compile-cache":"^2.0.0","validate-npm-package-license":"^3.0.3","yn":"^2.0.0"},"devDependencies":{"babel-core":"^6.26.0","babel-eslint":"^7.2.3","babel-loader":"^6.2.5","babel-plugin-array-includes":"^2.0.3","babel-plugin-transform-builtin-extend":"^1.1.2","babel-plugin-transform-inline-imports-commonjs":"^1.0.0","babel-plugin-transform-runtime":"^6.4.3","babel-preset-env":"^1.6.0","babel-preset-flow":"^6.23.0","babel-preset-stage-0":"^6.0.0","babylon":"^6.5.0","commitizen":"^2.9.6","cz-conventional-changelog":"^2.0.0","eslint":"^4.3.0","eslint-config-fb-strict":"^22.0.0","eslint-plugin-babel":"^5.0.0","eslint-plugin-flowtype":"^2.35.0","eslint-plugin-jasmine":"^2.6.2","eslint-plugin-jest":"^21.0.0","eslint-plugin-jsx-a11y":"^6.0.2","eslint-plugin-prefer-object-spread":"^1.2.1","eslint-plugin-prettier":"^2.1.2","eslint-plugin-react":"^7.1.0","eslint-plugin-relay":"^0.0.24","eslint-plugin-yarn-internal":"file:scripts/eslint-rules","execa":"^0.10.0","flow-bin":"^0.66.0","git-release-notes":"^3.0.0","gulp":"^3.9.0","gulp-babel":"^7.0.0","gulp-if":"^2.0.1","gulp-newer":"^1.0.0","gulp-plumber":"^1.0.1","gulp-sourcemaps":"^2.2.0","gulp-util":"^3.0.7","gulp-watch":"^5.0.0","jest":"^22.4.4","jsinspect":"^0.12.6","minimatch":"^3.0.4","mock-stdin":"^0.3.0","prettier":"^1.5.2","temp":"^0.8.3","webpack":"^2.1.0-beta.25","yargs":"^6.3.0"},"resolutions":{"sshpk":"^1.14.2"},"engines":{"node":">=4.0.0"},"repository":"yarnpkg/yarn","bin":{"yarn":"./bin/yarn.js","yarnpkg":"./bin/yarn.js"},"scripts":{"build":"gulp build","build-bundle":"node ./scripts/build-webpack.js","build-chocolatey":"powershell ./scripts/build-chocolatey.ps1","build-deb":"./scripts/build-deb.sh","build-dist":"bash ./scripts/build-dist.sh","build-win-installer":"scripts\\build-windows-installer.bat","changelog":"git-release-notes $(git describe --tags --abbrev=0 $(git describe --tags --abbrev=0)^)..$(git describe --tags --abbrev=0) scripts/changelog.md","dupe-check":"yarn jsinspect ./src","lint":"eslint . && flow check","pkg-tests":"yarn --cwd packages/pkg-tests jest yarn.test.js","prettier":"eslint src __tests__ --fix","release-branch":"./scripts/release-branch.sh","test":"yarn lint && yarn test-only","test-only":"node --max_old_space_size=4096 node_modules/jest/bin/jest.js --verbose","test-only-debug":"node --inspect-brk --max_old_space_size=4096 node_modules/jest/bin/jest.js --runInBand --verbose","test-coverage":"node --max_old_space_size=4096 node_modules/jest/bin/jest.js --coverage --verbose","watch":"gulp watch","commit":"git-cz"},"jest":{"collectCoverageFrom":["src/**/*.js"],"testEnvironment":"node","modulePathIgnorePatterns":["__tests__/fixtures/","packages/pkg-tests/pkg-tests-fixtures","dist/"],"testPathIgnorePatterns":["__tests__/(fixtures|__mocks__)/","updates/","_(temp|mock|install|init|helpers).js$","packages/pkg-tests"]},"config":{"commitizen":{"path":"./node_modules/cz-conventional-changelog"}}} + // continue if not a symlink + if (knownHard[base] || (cache && cache[base] === base)) { + continue; + } -/***/ }), -/* 146 */, -/* 147 */, -/* 148 */, -/* 149 */, -/* 150 */ -/***/ (function(module, exports, __webpack_require__) { + var resolvedLink; + if (cache && Object.prototype.hasOwnProperty.call(cache, base)) { + // some known symbolic link. no need to stat again. + resolvedLink = cache[base]; + } else { + var stat = fs.lstatSync(base); + if (!stat.isSymbolicLink()) { + knownHard[base] = true; + if (cache) cache[base] = base; + continue; + } -"use strict"; + // read the link if it wasn't read before + // dev/ino always return 0 on windows, so skip the check. + var linkTarget = null; + if (!isWindows) { + var id = stat.dev.toString(32) + ':' + stat.ino.toString(32); + if (seenLinks.hasOwnProperty(id)) { + linkTarget = seenLinks[id]; + } + } + if (linkTarget === null) { + fs.statSync(base); + linkTarget = fs.readlinkSync(base); + } + resolvedLink = pathModule.resolve(previous, linkTarget); + // track this, if given a cache. + if (cache) cache[base] = resolvedLink; + if (!isWindows) seenLinks[id] = linkTarget; + } + // resolve the link, then start over + p = pathModule.resolve(resolvedLink, p.slice(pos)); + start(); + } -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.default = stringify; + if (cache) cache[original] = p; -var _misc; + return p; +}; -function _load_misc() { - return _misc = __webpack_require__(12); -} -var _constants; +exports.realpath = function realpath(p, cache, cb) { + if (typeof cb !== 'function') { + cb = maybeCallback(cache); + cache = null; + } -function _load_constants() { - return _constants = __webpack_require__(6); -} + // make p is absolute + p = pathModule.resolve(p); -var _package; + if (cache && Object.prototype.hasOwnProperty.call(cache, p)) { + return process.nextTick(cb.bind(null, null, cache[p])); + } -function _load_package() { - return _package = __webpack_require__(145); -} + var original = p, + seenLinks = {}, + knownHard = {}; -const NODE_VERSION = process.version; + // current character position in p + var pos; + // the partial path so far, including a trailing slash if any + var current; + // the partial path without a trailing slash (except when pointing at a root) + var base; + // the partial path scanned in the previous round, with slash + var previous; -function shouldWrapKey(str) { - return str.indexOf('true') === 0 || str.indexOf('false') === 0 || /[:\s\n\\",\[\]]/g.test(str) || /^[0-9]/g.test(str) || !/^[a-zA-Z]/g.test(str); -} + start(); -function maybeWrap(str) { - if (typeof str === 'boolean' || typeof str === 'number' || shouldWrapKey(str)) { - return JSON.stringify(str); - } else { - return str; - } -} - -const priorities = { - name: 1, - version: 2, - uid: 3, - resolved: 4, - integrity: 5, - registry: 6, - dependencies: 7 -}; - -function priorityThenAlphaSort(a, b) { - if (priorities[a] || priorities[b]) { - return (priorities[a] || 100) > (priorities[b] || 100) ? 1 : -1; - } else { - return (0, (_misc || _load_misc()).sortAlpha)(a, b); - } -} + function start() { + // Skip over roots + var m = splitRootRe.exec(p); + pos = m[0].length; + current = m[0]; + base = m[0]; + previous = ''; -function _stringify(obj, options) { - if (typeof obj !== 'object') { - throw new TypeError(); + // On windows, check that the root exists. On unix there is no need. + if (isWindows && !knownHard[base]) { + fs.lstat(base, function(err) { + if (err) return cb(err); + knownHard[base] = true; + LOOP(); + }); + } else { + process.nextTick(LOOP); + } } - const indent = options.indent; - const lines = []; + // walk down the path, swapping out linked pathparts for their real + // values + function LOOP() { + // stop if scanned past end of path + if (pos >= p.length) { + if (cache) cache[original] = p; + return cb(null, p); + } - // Sorting order needs to be consistent between runs, we run native sort by name because there are no - // problems with it being unstable because there are no to keys the same - // However priorities can be duplicated and native sort can shuffle things from run to run - const keys = Object.keys(obj).sort(priorityThenAlphaSort); + // find the next part + nextPartRe.lastIndex = pos; + var result = nextPartRe.exec(p); + previous = current; + current += result[0]; + base = previous + result[1]; + pos = nextPartRe.lastIndex; - let addedKeys = []; + // continue if not a symlink + if (knownHard[base] || (cache && cache[base] === base)) { + return process.nextTick(LOOP); + } - for (let i = 0; i < keys.length; i++) { - const key = keys[i]; - const val = obj[key]; - if (val == null || addedKeys.indexOf(key) >= 0) { - continue; + if (cache && Object.prototype.hasOwnProperty.call(cache, base)) { + // known symbolic link. no need to stat again. + return gotResolvedLink(cache[base]); } - const valKeys = [key]; + return fs.lstat(base, gotStat); + } - // get all keys that have the same value equality, we only want this for objects - if (typeof val === 'object') { - for (let j = i + 1; j < keys.length; j++) { - const key = keys[j]; - if (val === obj[key]) { - valKeys.push(key); - } - } - } + function gotStat(err, stat) { + if (err) return cb(err); - const keyLine = valKeys.sort((_misc || _load_misc()).sortAlpha).map(maybeWrap).join(', '); + // if not a symlink, skip to the next path part + if (!stat.isSymbolicLink()) { + knownHard[base] = true; + if (cache) cache[base] = base; + return process.nextTick(LOOP); + } - if (typeof val === 'string' || typeof val === 'boolean' || typeof val === 'number') { - lines.push(`${keyLine} ${maybeWrap(val)}`); - } else if (typeof val === 'object') { - lines.push(`${keyLine}:\n${_stringify(val, { indent: indent + ' ' })}` + (options.topLevel ? '\n' : '')); - } else { - throw new TypeError(); + // stat & read the link if not read before + // call gotTarget as soon as the link target is known + // dev/ino always return 0 on windows, so skip the check. + if (!isWindows) { + var id = stat.dev.toString(32) + ':' + stat.ino.toString(32); + if (seenLinks.hasOwnProperty(id)) { + return gotTarget(null, seenLinks[id], base); + } } + fs.stat(base, function(err) { + if (err) return cb(err); - addedKeys = addedKeys.concat(valKeys); + fs.readlink(base, function(err, target) { + if (!isWindows) seenLinks[id] = target; + gotTarget(err, target); + }); + }); } - return indent + lines.join(`\n${indent}`); -} + function gotTarget(err, target, base) { + if (err) return cb(err); -function stringify(obj, noHeader, enableVersions) { - const val = _stringify(obj, { - indent: '', - topLevel: true - }); - if (noHeader) { - return val; + var resolvedLink = pathModule.resolve(previous, target); + if (cache) cache[base] = resolvedLink; + gotResolvedLink(resolvedLink); } - const lines = []; - lines.push('# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.'); - lines.push(`# yarn lockfile v${(_constants || _load_constants()).LOCKFILE_VERSION}`); - if (enableVersions) { - lines.push(`# yarn v${(_package || _load_package()).version}`); - lines.push(`# node ${NODE_VERSION}`); + function gotResolvedLink(resolvedLink) { + // resolve the link, then start over + p = pathModule.resolve(resolvedLink, p.slice(pos)); + start(); } - lines.push('\n'); - lines.push(val); +}; - return lines.join('\n'); -} /***/ }), -/* 151 */, -/* 152 */, -/* 153 */, -/* 154 */, -/* 155 */, -/* 156 */, -/* 157 */, -/* 158 */, -/* 159 */, -/* 160 */, -/* 161 */, -/* 162 */, -/* 163 */, -/* 164 */ +/* 218 */ /***/ (function(module, exports, __webpack_require__) { -"use strict"; - +module.exports = globSync +globSync.GlobSync = GlobSync -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.fileDatesEqual = exports.copyFile = exports.unlink = undefined; +var fs = __webpack_require__(3) +var rp = __webpack_require__(114) +var minimatch = __webpack_require__(60) +var Minimatch = minimatch.Minimatch +var Glob = __webpack_require__(75).Glob +var util = __webpack_require__(2) +var path = __webpack_require__(0) +var assert = __webpack_require__(22) +var isAbsolute = __webpack_require__(76) +var common = __webpack_require__(115) +var alphasort = common.alphasort +var alphasorti = common.alphasorti +var setopts = common.setopts +var ownProp = common.ownProp +var childrenIgnored = common.childrenIgnored +var isIgnored = common.isIgnored -var _asyncToGenerator2; +function globSync (pattern, options) { + if (typeof options === 'function' || arguments.length === 3) + throw new TypeError('callback provided to sync glob\n'+ + 'See: https://github.com/isaacs/node-glob/issues/167') -function _load_asyncToGenerator() { - return _asyncToGenerator2 = _interopRequireDefault(__webpack_require__(1)); + return new GlobSync(pattern, options).found } -// We want to preserve file timestamps when copying a file, since yarn uses them to decide if a file has -// changed compared to the cache. -// There are some OS specific cases here: -// * On linux, fs.copyFile does not preserve timestamps, but does on OSX and Win. -// * On windows, you must open a file with write permissions to call `fs.futimes`. -// * On OSX you can open with read permissions and still call `fs.futimes`. -let fixTimes = (() => { - var _ref3 = (0, (_asyncToGenerator2 || _load_asyncToGenerator()).default)(function* (fd, dest, data) { - const doOpen = fd === undefined; - let openfd = fd ? fd : -1; +function GlobSync (pattern, options) { + if (!pattern) + throw new Error('must provide pattern') - if (disableTimestampCorrection === undefined) { - // if timestamps match already, no correction is needed. - // the need to correct timestamps varies based on OS and node versions. - const destStat = yield lstat(dest); - disableTimestampCorrection = fileDatesEqual(destStat.mtime, data.mtime); - } + if (typeof options === 'function' || arguments.length === 3) + throw new TypeError('callback provided to sync glob\n'+ + 'See: https://github.com/isaacs/node-glob/issues/167') - if (disableTimestampCorrection) { - return; - } + if (!(this instanceof GlobSync)) + return new GlobSync(pattern, options) - if (doOpen) { - try { - openfd = yield open(dest, 'a', data.mode); - } catch (er) { - // file is likely read-only + setopts(this, pattern, options) + + if (this.noprocess) + return this + + var n = this.minimatch.set.length + this.matches = new Array(n) + for (var i = 0; i < n; i ++) { + this._process(this.minimatch.set[i], i, false) + } + this._finish() +} + +GlobSync.prototype._finish = function () { + assert(this instanceof GlobSync) + if (this.realpath) { + var self = this + this.matches.forEach(function (matchset, index) { + var set = self.matches[index] = Object.create(null) + for (var p in matchset) { try { - openfd = yield open(dest, 'r', data.mode); - } catch (err) { - // We can't even open this file for reading. - return; + p = self._makeAbs(p) + var real = rp.realpathSync(p, self.realpathCache) + set[real] = true + } catch (er) { + if (er.syscall === 'stat') + set[self._makeAbs(p)] = true + else + throw er } } - } - - try { - if (openfd) { - yield futimes(openfd, data.atime, data.mtime); - } - } catch (er) { - // If `futimes` throws an exception, we probably have a case of a read-only file on Windows. - // In this case we can just return. The incorrect timestamp will just cause that file to be recopied - // on subsequent installs, which will effect yarn performance but not break anything. - } finally { - if (doOpen && openfd) { - yield close(openfd); - } - } - }); + }) + } + common.finish(this) +} - return function fixTimes(_x7, _x8, _x9) { - return _ref3.apply(this, arguments); - }; -})(); -// Compare file timestamps. -// Some versions of Node on windows zero the milliseconds when utime is used. +GlobSync.prototype._process = function (pattern, index, inGlobStar) { + assert(this instanceof GlobSync) + // Get the first [n] parts of pattern that are all strings. + var n = 0 + while (typeof pattern[n] === 'string') { + n ++ + } + // now n is the index of the first one that is *not* a string. -var _fs; + // See if there's anything else + var prefix + switch (n) { + // if not, then this is rather simple + case pattern.length: + this._processSimple(pattern.join('/'), index) + return -function _load_fs() { - return _fs = _interopRequireDefault(__webpack_require__(3)); -} + case 0: + // pattern *starts* with some non-trivial item. + // going to readdir(cwd), but not include the prefix in matches. + prefix = null + break -var _promise; + default: + // pattern has some string bits in the front. + // whatever it starts with, whether that's 'absolute' like /foo/bar, + // or 'relative' like '../baz' + prefix = pattern.slice(0, n).join('/') + break + } -function _load_promise() { - return _promise = __webpack_require__(40); -} + var remain = pattern.slice(n) -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + // get the list of entries. + var read + if (prefix === null) + read = '.' + else if (isAbsolute(prefix) || isAbsolute(pattern.join('/'))) { + if (!prefix || !isAbsolute(prefix)) + prefix = '/' + prefix + read = prefix + } else + read = prefix -// This module serves as a wrapper for file operations that are inconsistant across node and OS versions. + var abs = this._makeAbs(read) -let disableTimestampCorrection = undefined; // OS dependent. will be detected on first file copy. + //if ignored, skip processing + if (childrenIgnored(this, read)) + return -const readFileBuffer = (0, (_promise || _load_promise()).promisify)((_fs || _load_fs()).default.readFile); -const close = (0, (_promise || _load_promise()).promisify)((_fs || _load_fs()).default.close); -const lstat = (0, (_promise || _load_promise()).promisify)((_fs || _load_fs()).default.lstat); -const open = (0, (_promise || _load_promise()).promisify)((_fs || _load_fs()).default.open); -const futimes = (0, (_promise || _load_promise()).promisify)((_fs || _load_fs()).default.futimes); + var isGlobStar = remain[0] === minimatch.GLOBSTAR + if (isGlobStar) + this._processGlobStar(prefix, read, abs, remain, index, inGlobStar) + else + this._processReaddir(prefix, read, abs, remain, index, inGlobStar) +} -const write = (0, (_promise || _load_promise()).promisify)((_fs || _load_fs()).default.write); -const unlink = exports.unlink = (0, (_promise || _load_promise()).promisify)(__webpack_require__(233)); +GlobSync.prototype._processReaddir = function (prefix, read, abs, remain, index, inGlobStar) { + var entries = this._readdir(abs, inGlobStar) -/** - * Unlinks the destination to force a recreation. This is needed on case-insensitive file systems - * to force the correct naming when the filename has changed only in character-casing. (Jest -> jest). - */ -const copyFile = exports.copyFile = (() => { - var _ref = (0, (_asyncToGenerator2 || _load_asyncToGenerator()).default)(function* (data, cleanup) { - try { - yield unlink(data.dest); - yield copyFilePoly(data.src, data.dest, 0, data); - } finally { - if (cleanup) { - cleanup(); - } - } - }); + // if the abs isn't a dir, then nothing can match! + if (!entries) + return - return function copyFile(_x, _x2) { - return _ref.apply(this, arguments); - }; -})(); + // It will only match dot entries if it starts with a dot, or if + // dot is set. Stuff like @(.foo|.bar) isn't allowed. + var pn = remain[0] + var negate = !!this.minimatch.negate + var rawGlob = pn._glob + var dotOk = this.dot || rawGlob.charAt(0) === '.' -// Node 8.5.0 introduced `fs.copyFile` which is much faster, so use that when available. -// Otherwise we fall back to reading and writing files as buffers. -const copyFilePoly = (src, dest, flags, data) => { - if ((_fs || _load_fs()).default.copyFile) { - return new Promise((resolve, reject) => (_fs || _load_fs()).default.copyFile(src, dest, flags, err => { - if (err) { - reject(err); + var matchedEntries = [] + for (var i = 0; i < entries.length; i++) { + var e = entries[i] + if (e.charAt(0) !== '.' || dotOk) { + var m + if (negate && !prefix) { + m = !e.match(pn) } else { - fixTimes(undefined, dest, data).then(() => resolve()).catch(ex => reject(ex)); + m = e.match(pn) } - })); - } else { - return copyWithBuffer(src, dest, flags, data); + if (m) + matchedEntries.push(e) + } } -}; -const copyWithBuffer = (() => { - var _ref2 = (0, (_asyncToGenerator2 || _load_asyncToGenerator()).default)(function* (src, dest, flags, data) { - // Use open -> write -> futimes -> close sequence to avoid opening the file twice: - // one with writeFile and one with utimes - const fd = yield open(dest, 'w', data.mode); - try { - const buffer = yield readFileBuffer(src); - yield write(fd, buffer, 0, buffer.length); - yield fixTimes(fd, dest, data); - } finally { - yield close(fd); - } - }); + var len = matchedEntries.length + // If there are no matched entries, then nothing matches. + if (len === 0) + return - return function copyWithBuffer(_x3, _x4, _x5, _x6) { - return _ref2.apply(this, arguments); - }; -})();const fileDatesEqual = exports.fileDatesEqual = (a, b) => { - const aTime = a.getTime(); - const bTime = b.getTime(); + // if this is the last remaining pattern bit, then no need for + // an additional stat *unless* the user has specified mark or + // stat explicitly. We know they exist, since readdir returned + // them. - if (process.platform !== 'win32') { - return aTime === bTime; - } + if (remain.length === 1 && !this.mark && !this.stat) { + if (!this.matches[index]) + this.matches[index] = Object.create(null) - // See https://github.com/nodejs/node/pull/12607 - // Submillisecond times from stat and utimes are truncated on Windows, - // causing a file with mtime 8.0079998 and 8.0081144 to become 8.007 and 8.008 - // and making it impossible to update these files to their correct timestamps. - if (Math.abs(aTime - bTime) <= 1) { - return true; - } + for (var i = 0; i < len; i ++) { + var e = matchedEntries[i] + if (prefix) { + if (prefix.slice(-1) !== '/') + e = prefix + '/' + e + else + e = prefix + e + } - const aTimeSec = Math.floor(aTime / 1000); - const bTimeSec = Math.floor(bTime / 1000); + if (e.charAt(0) === '/' && !this.nomount) { + e = path.join(this.root, e) + } + this._emitMatch(index, e) + } + // This was the last one, and no stats were needed + return + } - // See https://github.com/nodejs/node/issues/2069 - // Some versions of Node on windows zero the milliseconds when utime is used - // So if any of the time has a milliseconds part of zero we suspect that the - // bug is present and compare only seconds. - if (aTime - aTimeSec * 1000 === 0 || bTime - bTimeSec * 1000 === 0) { - return aTimeSec === bTimeSec; + // now test all matched entries as stand-ins for that part + // of the pattern. + remain.shift() + for (var i = 0; i < len; i ++) { + var e = matchedEntries[i] + var newPattern + if (prefix) + newPattern = [prefix, e] + else + newPattern = [e] + this._process(newPattern.concat(remain), index, inGlobStar) } +} - return aTime === bTime; -}; -/***/ }), -/* 165 */, -/* 166 */, -/* 167 */, -/* 168 */, -/* 169 */ -/***/ (function(module, exports, __webpack_require__) { +GlobSync.prototype._emitMatch = function (index, e) { + if (isIgnored(this, e)) + return -"use strict"; + var abs = this._makeAbs(e) + if (this.mark) + e = this._mark(e) -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.isFakeRoot = isFakeRoot; -exports.isRootUser = isRootUser; -function getUid() { - if (process.platform !== 'win32' && process.getuid) { - return process.getuid(); + if (this.absolute) { + e = abs } - return null; -} -exports.default = isRootUser(getUid()) && !isFakeRoot(); -function isFakeRoot() { - return Boolean(process.env.FAKEROOTKEY); -} + if (this.matches[index][e]) + return -function isRootUser(uid) { - return uid === 0; -} - -/***/ }), -/* 170 */, -/* 171 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; + if (this.nodir) { + var c = this.cache[abs] + if (c === 'DIR' || Array.isArray(c)) + return + } + this.matches[index][e] = true -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.getDataDir = getDataDir; -exports.getCacheDir = getCacheDir; -exports.getConfigDir = getConfigDir; -const path = __webpack_require__(0); -const userHome = __webpack_require__(45).default; + if (this.stat) + this._stat(e) +} -const FALLBACK_CONFIG_DIR = path.join(userHome, '.config', 'yarn'); -const FALLBACK_CACHE_DIR = path.join(userHome, '.cache', 'yarn'); -function getDataDir() { - if (process.platform === 'win32') { - const WIN32_APPDATA_DIR = getLocalAppDataDir(); - return WIN32_APPDATA_DIR == null ? FALLBACK_CONFIG_DIR : path.join(WIN32_APPDATA_DIR, 'Data'); - } else if (process.env.XDG_DATA_HOME) { - return path.join(process.env.XDG_DATA_HOME, 'yarn'); - } else { - // This could arguably be ~/Library/Application Support/Yarn on Macs, - // but that feels unintuitive for a cli tool +GlobSync.prototype._readdirInGlobStar = function (abs) { + // follow all symlinked directories forever + // just proceed as if this is a non-globstar situation + if (this.follow) + return this._readdir(abs, false) - // Instead, use our prior fallback. Some day this could be - // path.join(userHome, '.local', 'share', 'yarn') - // or return path.join(WIN32_APPDATA_DIR, 'Data') on win32 - return FALLBACK_CONFIG_DIR; + var entries + var lstat + var stat + try { + lstat = fs.lstatSync(abs) + } catch (er) { + if (er.code === 'ENOENT') { + // lstat failed, doesn't exist + return null + } } -} -function getCacheDir() { - if (process.platform === 'win32') { - // process.env.TEMP also exists, but most apps put caches here - return path.join(getLocalAppDataDir() || path.join(userHome, 'AppData', 'Local', 'Yarn'), 'Cache'); - } else if (process.env.XDG_CACHE_HOME) { - return path.join(process.env.XDG_CACHE_HOME, 'yarn'); - } else if (process.platform === 'darwin') { - return path.join(userHome, 'Library', 'Caches', 'Yarn'); - } else { - return FALLBACK_CACHE_DIR; - } -} + var isSym = lstat && lstat.isSymbolicLink() + this.symlinks[abs] = isSym -function getConfigDir() { - if (process.platform === 'win32') { - // Use our prior fallback. Some day this could be - // return path.join(WIN32_APPDATA_DIR, 'Config') - const WIN32_APPDATA_DIR = getLocalAppDataDir(); - return WIN32_APPDATA_DIR == null ? FALLBACK_CONFIG_DIR : path.join(WIN32_APPDATA_DIR, 'Config'); - } else if (process.env.XDG_CONFIG_HOME) { - return path.join(process.env.XDG_CONFIG_HOME, 'yarn'); - } else { - return FALLBACK_CONFIG_DIR; - } -} + // If it's not a symlink or a dir, then it's definitely a regular file. + // don't bother doing a readdir in that case. + if (!isSym && lstat && !lstat.isDirectory()) + this.cache[abs] = 'FILE' + else + entries = this._readdir(abs, false) -function getLocalAppDataDir() { - return process.env.LOCALAPPDATA ? path.join(process.env.LOCALAPPDATA, 'Yarn') : null; + return entries } -/***/ }), -/* 172 */, -/* 173 */ -/***/ (function(module, exports, __webpack_require__) { - -module.exports = { "default": __webpack_require__(179), __esModule: true }; - -/***/ }), -/* 174 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; +GlobSync.prototype._readdir = function (abs, inGlobStar) { + var entries -module.exports = balanced; -function balanced(a, b, str) { - if (a instanceof RegExp) a = maybeMatch(a, str); - if (b instanceof RegExp) b = maybeMatch(b, str); + if (inGlobStar && !ownProp(this.symlinks, abs)) + return this._readdirInGlobStar(abs) - var r = range(a, b, str); + if (ownProp(this.cache, abs)) { + var c = this.cache[abs] + if (!c || c === 'FILE') + return null - return r && { - start: r[0], - end: r[1], - pre: str.slice(0, r[0]), - body: str.slice(r[0] + a.length, r[1]), - post: str.slice(r[1] + b.length) - }; -} + if (Array.isArray(c)) + return c + } -function maybeMatch(reg, str) { - var m = str.match(reg); - return m ? m[0] : null; + try { + return this._readdirEntries(abs, fs.readdirSync(abs)) + } catch (er) { + this._readdirError(abs, er) + return null + } } -balanced.range = range; -function range(a, b, str) { - var begs, beg, left, right, result; - var ai = str.indexOf(a); - var bi = str.indexOf(b, ai + 1); - var i = ai; +GlobSync.prototype._readdirEntries = function (abs, entries) { + // if we haven't asked to stat everything, then just + // assume that everything in there exists, so we can avoid + // having to stat it a second time. + if (!this.mark && !this.stat) { + for (var i = 0; i < entries.length; i ++) { + var e = entries[i] + if (abs === '/') + e = abs + e + else + e = abs + '/' + e + this.cache[e] = true + } + } - if (ai >= 0 && bi > 0) { - begs = []; - left = str.length; + this.cache[abs] = entries - while (i >= 0 && !result) { - if (i == ai) { - begs.push(i); - ai = str.indexOf(a, i + 1); - } else if (begs.length == 1) { - result = [ begs.pop(), bi ]; - } else { - beg = begs.pop(); - if (beg < left) { - left = beg; - right = bi; - } + // mark and cache dir-ness + return entries +} - bi = str.indexOf(b, i + 1); +GlobSync.prototype._readdirError = function (f, er) { + // handle errors, and cache the information + switch (er.code) { + case 'ENOTSUP': // https://github.com/isaacs/node-glob/issues/205 + case 'ENOTDIR': // totally normal. means it *does* exist. + var abs = this._makeAbs(f) + this.cache[abs] = 'FILE' + if (abs === this.cwdAbs) { + var error = new Error(er.code + ' invalid cwd ' + this.cwd) + error.path = this.cwd + error.code = er.code + throw error } + break - i = ai < bi && ai >= 0 ? ai : bi; - } + case 'ENOENT': // not terribly unusual + case 'ELOOP': + case 'ENAMETOOLONG': + case 'UNKNOWN': + this.cache[this._makeAbs(f)] = false + break - if (begs.length) { - result = [ left, right ]; - } + default: // some unusual error. Treat as failure. + this.cache[this._makeAbs(f)] = false + if (this.strict) + throw er + if (!this.silent) + console.error('glob error', er) + break } - - return result; } +GlobSync.prototype._processGlobStar = function (prefix, read, abs, remain, index, inGlobStar) { -/***/ }), -/* 175 */ -/***/ (function(module, exports, __webpack_require__) { + var entries = this._readdir(abs, inGlobStar) -var concatMap = __webpack_require__(178); -var balanced = __webpack_require__(174); + // no entries means not a dir, so it can never have matches + // foo.txt/** doesn't match foo.txt + if (!entries) + return -module.exports = expandTop; + // test without the globstar, and with every child both below + // and replacing the globstar. + var remainWithoutGlobStar = remain.slice(1) + var gspref = prefix ? [ prefix ] : [] + var noGlobStar = gspref.concat(remainWithoutGlobStar) -var escSlash = '\0SLASH'+Math.random()+'\0'; -var escOpen = '\0OPEN'+Math.random()+'\0'; -var escClose = '\0CLOSE'+Math.random()+'\0'; -var escComma = '\0COMMA'+Math.random()+'\0'; -var escPeriod = '\0PERIOD'+Math.random()+'\0'; + // the noGlobStar pattern exits the inGlobStar state + this._process(noGlobStar, index, false) -function numeric(str) { - return parseInt(str, 10) == str - ? parseInt(str, 10) - : str.charCodeAt(0); -} + var len = entries.length + var isSym = this.symlinks[abs] -function escapeBraces(str) { - return str.split('\\\\').join(escSlash) - .split('\\{').join(escOpen) - .split('\\}').join(escClose) - .split('\\,').join(escComma) - .split('\\.').join(escPeriod); -} + // If it's a symlink, and we're in a globstar, then stop + if (isSym && inGlobStar) + return -function unescapeBraces(str) { - return str.split(escSlash).join('\\') - .split(escOpen).join('{') - .split(escClose).join('}') - .split(escComma).join(',') - .split(escPeriod).join('.'); -} + for (var i = 0; i < len; i++) { + var e = entries[i] + if (e.charAt(0) === '.' && !this.dot) + continue + // these two cases enter the inGlobStar state + var instead = gspref.concat(entries[i], remainWithoutGlobStar) + this._process(instead, index, true) -// Basically just str.split(","), but handling cases -// where we have nested braced sections, which should be -// treated as individual members, like {a,{b,c},d} -function parseCommaParts(str) { - if (!str) - return ['']; + var below = gspref.concat(entries[i], remain) + this._process(below, index, true) + } +} - var parts = []; - var m = balanced('{', '}', str); +GlobSync.prototype._processSimple = function (prefix, index) { + // XXX review this. Shouldn't it be doing the mounting etc + // before doing stat? kinda weird? + var exists = this._stat(prefix) - if (!m) - return str.split(','); + if (!this.matches[index]) + this.matches[index] = Object.create(null) - var pre = m.pre; - var body = m.body; - var post = m.post; - var p = pre.split(','); + // If it doesn't exist, then just mark the lack of results + if (!exists) + return - p[p.length-1] += '{' + body + '}'; - var postParts = parseCommaParts(post); - if (post.length) { - p[p.length-1] += postParts.shift(); - p.push.apply(p, postParts); + if (prefix && isAbsolute(prefix) && !this.nomount) { + var trail = /[\/\\]$/.test(prefix) + if (prefix.charAt(0) === '/') { + prefix = path.join(this.root, prefix) + } else { + prefix = path.resolve(this.root, prefix) + if (trail) + prefix += '/' + } } - parts.push.apply(parts, p); + if (process.platform === 'win32') + prefix = prefix.replace(/\\/g, '/') - return parts; + // Mark this as a match + this._emitMatch(index, prefix) } -function expandTop(str) { - if (!str) - return []; - - // I don't know why Bash 4.3 does this, but it does. - // Anything starting with {} will have the first two bytes preserved - // but *only* at the top level, so {},a}b will not expand to anything, - // but a{},b}c will be expanded to [a}c,abc]. - // One could argue that this is a bug in Bash, but since the goal of - // this module is to match Bash's rules, we escape a leading {} - if (str.substr(0, 2) === '{}') { - str = '\\{\\}' + str.substr(2); - } +// Returns either 'DIR', 'FILE', or false +GlobSync.prototype._stat = function (f) { + var abs = this._makeAbs(f) + var needDir = f.slice(-1) === '/' - return expand(escapeBraces(str), true).map(unescapeBraces); -} + if (f.length > this.maxLength) + return false -function identity(e) { - return e; -} + if (!this.stat && ownProp(this.cache, abs)) { + var c = this.cache[abs] -function embrace(str) { - return '{' + str + '}'; -} -function isPadded(el) { - return /^-?0\d/.test(el); -} + if (Array.isArray(c)) + c = 'DIR' -function lte(i, y) { - return i <= y; -} -function gte(i, y) { - return i >= y; -} + // It exists, but maybe not how we need it + if (!needDir || c === 'DIR') + return c -function expand(str, isTop) { - var expansions = []; + if (needDir && c === 'FILE') + return false - var m = balanced('{', '}', str); - if (!m || /\$$/.test(m.pre)) return [str]; + // otherwise we have to stat, because maybe c=true + // if we know it exists, but not what it is. + } - var isNumericSequence = /^-?\d+\.\.-?\d+(?:\.\.-?\d+)?$/.test(m.body); - var isAlphaSequence = /^[a-zA-Z]\.\.[a-zA-Z](?:\.\.-?\d+)?$/.test(m.body); - var isSequence = isNumericSequence || isAlphaSequence; - var isOptions = m.body.indexOf(',') >= 0; - if (!isSequence && !isOptions) { - // {a},b} - if (m.post.match(/,.*\}/)) { - str = m.pre + '{' + m.body + escClose + m.post; - return expand(str); + var exists + var stat = this.statCache[abs] + if (!stat) { + var lstat + try { + lstat = fs.lstatSync(abs) + } catch (er) { + if (er && (er.code === 'ENOENT' || er.code === 'ENOTDIR')) { + this.statCache[abs] = false + return false + } } - return [str]; - } - var n; - if (isSequence) { - n = m.body.split(/\.\./); - } else { - n = parseCommaParts(m.body); - if (n.length === 1) { - // x{{a,b}}y ==> x{a}y x{b}y - n = expand(n[0], false).map(embrace); - if (n.length === 1) { - var post = m.post.length - ? expand(m.post, false) - : ['']; - return post.map(function(p) { - return m.pre + n[0] + p; - }); + if (lstat && lstat.isSymbolicLink()) { + try { + stat = fs.statSync(abs) + } catch (er) { + stat = lstat } + } else { + stat = lstat } } - // at this point, n is the parts, and we know it's not a comma set - // with a single entry. - - // no need to expand pre, since it is guaranteed to be free of brace-sets - var pre = m.pre; - var post = m.post.length - ? expand(m.post, false) - : ['']; - - var N; + this.statCache[abs] = stat - if (isSequence) { - var x = numeric(n[0]); - var y = numeric(n[1]); - var width = Math.max(n[0].length, n[1].length) - var incr = n.length == 3 - ? Math.abs(numeric(n[2])) - : 1; - var test = lte; - var reverse = y < x; - if (reverse) { - incr *= -1; - test = gte; - } - var pad = n.some(isPadded); + var c = true + if (stat) + c = stat.isDirectory() ? 'DIR' : 'FILE' - N = []; + this.cache[abs] = this.cache[abs] || c - for (var i = x; test(i, y); i += incr) { - var c; - if (isAlphaSequence) { - c = String.fromCharCode(i); - if (c === '\\') - c = ''; - } else { - c = String(i); - if (pad) { - var need = width - c.length; - if (need > 0) { - var z = new Array(need + 1).join('0'); - if (i < 0) - c = '-' + z + c.slice(1); - else - c = z + c; - } - } - } - N.push(c); - } - } else { - N = concatMap(n, function(el) { return expand(el, false) }); - } + if (needDir && c === 'FILE') + return false - for (var j = 0; j < N.length; j++) { - for (var k = 0; k < post.length; k++) { - var expansion = pre + N[j] + post[k]; - if (!isTop || isSequence || expansion) - expansions.push(expansion); - } - } + return c +} - return expansions; +GlobSync.prototype._mark = function (p) { + return common.mark(this, p) } +GlobSync.prototype._makeAbs = function (f) { + return common.makeAbs(this, f) +} /***/ }), -/* 176 */ +/* 219 */, +/* 220 */, +/* 221 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; +module.exports = function (flag, argv) { + argv = argv || process.argv; -function preserveCamelCase(str) { - let isLastCharLower = false; - let isLastCharUpper = false; - let isLastLastCharUpper = false; + var terminatorPos = argv.indexOf('--'); + var prefix = /^--/.test(flag) ? '' : '--'; + var pos = argv.indexOf(prefix + flag); - for (let i = 0; i < str.length; i++) { - const c = str[i]; + return pos !== -1 && (terminatorPos !== -1 ? pos < terminatorPos : true); +}; - if (isLastCharLower && /[a-zA-Z]/.test(c) && c.toUpperCase() === c) { - str = str.substr(0, i) + '-' + str.substr(i); - isLastCharLower = false; - isLastLastCharUpper = isLastCharUpper; - isLastCharUpper = true; - i++; - } else if (isLastCharUpper && isLastLastCharUpper && /[a-zA-Z]/.test(c) && c.toLowerCase() === c) { - str = str.substr(0, i - 1) + '-' + str.substr(i - 1); - isLastLastCharUpper = isLastCharUpper; - isLastCharUpper = false; - isLastCharLower = true; - } else { - isLastCharLower = c.toLowerCase() === c; - isLastLastCharUpper = isLastCharUpper; - isLastCharUpper = c.toUpperCase() === c; - } - } - return str; -} +/***/ }), +/* 222 */, +/* 223 */ +/***/ (function(module, exports, __webpack_require__) { -module.exports = function (str) { - if (arguments.length > 1) { - str = Array.from(arguments) - .map(x => x.trim()) - .filter(x => x.length) - .join('-'); - } else { - str = str.trim(); - } +var wrappy = __webpack_require__(123) +var reqs = Object.create(null) +var once = __webpack_require__(61) - if (str.length === 0) { - return ''; - } +module.exports = wrappy(inflight) - if (str.length === 1) { - return str.toLowerCase(); - } +function inflight (key, cb) { + if (reqs[key]) { + reqs[key].push(cb) + return null + } else { + reqs[key] = [cb] + return makeres(key) + } +} - if (/^[a-z0-9]+$/.test(str)) { - return str; - } +function makeres (key) { + return once(function RES () { + var cbs = reqs[key] + var len = cbs.length + var args = slice(arguments) - const hasUpperCase = str !== str.toLowerCase(); + // XXX It's somewhat ambiguous whether a new callback added in this + // pass should be queued for later execution if something in the + // list of callbacks throws, or if it should just be discarded. + // However, it's such an edge case that it hardly matters, and either + // choice is likely as surprising as the other. + // As it happens, we do go ahead and schedule it for later execution. + try { + for (var i = 0; i < len; i++) { + cbs[i].apply(null, args) + } + } finally { + if (cbs.length > len) { + // added more in the interim. + // de-zalgo, just in case, but don't call again. + cbs.splice(0, len) + process.nextTick(function () { + RES.apply(null, args) + }) + } else { + delete reqs[key] + } + } + }) +} - if (hasUpperCase) { - str = preserveCamelCase(str); - } +function slice (args) { + var length = args.length + var array = [] - return str - .replace(/^[_.\- ]+/, '') - .toLowerCase() - .replace(/[_.\- ]+(\w|$)/g, (m, p1) => p1.toUpperCase()); -}; + for (var i = 0; i < length; i++) array[i] = args[i] + return array +} /***/ }), -/* 177 */, -/* 178 */ +/* 224 */ /***/ (function(module, exports) { -module.exports = function (xs, fn) { - var res = []; - for (var i = 0; i < xs.length; i++) { - var x = fn(xs[i], i); - if (isArray(x)) res.push.apply(res, x); - else res.push(x); - } - return res; -}; - -var isArray = Array.isArray || function (xs) { - return Object.prototype.toString.call(xs) === '[object Array]'; -}; +if (typeof Object.create === 'function') { + // implementation from standard node.js 'util' module + module.exports = function inherits(ctor, superCtor) { + ctor.super_ = superCtor + ctor.prototype = Object.create(superCtor.prototype, { + constructor: { + value: ctor, + enumerable: false, + writable: true, + configurable: true + } + }); + }; +} else { + // old school shim for old browsers + module.exports = function inherits(ctor, superCtor) { + ctor.super_ = superCtor + var TempCtor = function () {} + TempCtor.prototype = superCtor.prototype + ctor.prototype = new TempCtor() + ctor.prototype.constructor = ctor + } +} /***/ }), -/* 179 */ +/* 225 */, +/* 226 */, +/* 227 */ /***/ (function(module, exports, __webpack_require__) { -__webpack_require__(205); -__webpack_require__(207); -__webpack_require__(210); -__webpack_require__(206); -__webpack_require__(208); -__webpack_require__(209); -module.exports = __webpack_require__(23).Promise; - +// @flow -/***/ }), -/* 180 */ -/***/ (function(module, exports) { +/*:: +declare var __webpack_require__: mixed; +*/ -module.exports = function () { /* empty */ }; +module.exports = typeof __webpack_require__ !== "undefined"; /***/ }), -/* 181 */ +/* 228 */, +/* 229 */ /***/ (function(module, exports) { -module.exports = function (it, Constructor, name, forbiddenField) { - if (!(it instanceof Constructor) || (forbiddenField !== undefined && forbiddenField in it)) { - throw TypeError(name + ': incorrect invocation!'); - } return it; -}; - - -/***/ }), -/* 182 */ -/***/ (function(module, exports, __webpack_require__) { - -// false -> Array#indexOf -// true -> Array#includes -var toIObject = __webpack_require__(74); -var toLength = __webpack_require__(110); -var toAbsoluteIndex = __webpack_require__(200); -module.exports = function (IS_INCLUDES) { - return function ($this, el, fromIndex) { - var O = toIObject($this); - var length = toLength(O.length); - var index = toAbsoluteIndex(fromIndex, length); - var value; - // Array#includes uses SameValueZero equality algorithm - // eslint-disable-next-line no-self-compare - if (IS_INCLUDES && el != el) while (length > index) { - value = O[index++]; - // eslint-disable-next-line no-self-compare - if (value != value) return true; - // Array#indexOf ignores holes, Array#includes - not - } else for (;length > index; index++) if (IS_INCLUDES || index in O) { - if (O[index] === el) return IS_INCLUDES || index || 0; - } return !IS_INCLUDES && -1; - }; -}; +/** + * Helpers. + */ +var s = 1000; +var m = s * 60; +var h = m * 60; +var d = h * 24; +var y = d * 365.25; -/***/ }), -/* 183 */ -/***/ (function(module, exports, __webpack_require__) { +/** + * Parse or format the given `val`. + * + * Options: + * + * - `long` verbose formatting [false] + * + * @param {String|Number} val + * @param {Object} [options] + * @throws {Error} throw an error if val is not a non-empty string or a number + * @return {String|Number} + * @api public + */ -var ctx = __webpack_require__(48); -var call = __webpack_require__(187); -var isArrayIter = __webpack_require__(186); -var anObject = __webpack_require__(27); -var toLength = __webpack_require__(110); -var getIterFn = __webpack_require__(203); -var BREAK = {}; -var RETURN = {}; -var exports = module.exports = function (iterable, entries, fn, that, ITERATOR) { - var iterFn = ITERATOR ? function () { return iterable; } : getIterFn(iterable); - var f = ctx(fn, that, entries ? 2 : 1); - var index = 0; - var length, step, iterator, result; - if (typeof iterFn != 'function') throw TypeError(iterable + ' is not iterable!'); - // fast case for arrays with default iterator - if (isArrayIter(iterFn)) for (length = toLength(iterable.length); length > index; index++) { - result = entries ? f(anObject(step = iterable[index])[0], step[1]) : f(iterable[index]); - if (result === BREAK || result === RETURN) return result; - } else for (iterator = iterFn.call(iterable); !(step = iterator.next()).done;) { - result = call(iterator, f, step.value, entries); - if (result === BREAK || result === RETURN) return result; +module.exports = function(val, options) { + options = options || {}; + var type = typeof val; + if (type === 'string' && val.length > 0) { + return parse(val); + } else if (type === 'number' && isNaN(val) === false) { + return options.long ? fmtLong(val) : fmtShort(val); } + throw new Error( + 'val is not a non-empty string or a valid number. val=' + + JSON.stringify(val) + ); }; -exports.BREAK = BREAK; -exports.RETURN = RETURN; - - -/***/ }), -/* 184 */ -/***/ (function(module, exports, __webpack_require__) { -module.exports = !__webpack_require__(33) && !__webpack_require__(85)(function () { - return Object.defineProperty(__webpack_require__(68)('div'), 'a', { get: function () { return 7; } }).a != 7; -}); +/** + * Parse the given `str` and return milliseconds. + * + * @param {String} str + * @return {Number} + * @api private + */ +function parse(str) { + str = String(str); + if (str.length > 100) { + return; + } + var match = /^((?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|years?|yrs?|y)?$/i.exec( + str + ); + if (!match) { + return; + } + var n = parseFloat(match[1]); + var type = (match[2] || 'ms').toLowerCase(); + switch (type) { + case 'years': + case 'year': + case 'yrs': + case 'yr': + case 'y': + return n * y; + case 'days': + case 'day': + case 'd': + return n * d; + case 'hours': + case 'hour': + case 'hrs': + case 'hr': + case 'h': + return n * h; + case 'minutes': + case 'minute': + case 'mins': + case 'min': + case 'm': + return n * m; + case 'seconds': + case 'second': + case 'secs': + case 'sec': + case 's': + return n * s; + case 'milliseconds': + case 'millisecond': + case 'msecs': + case 'msec': + case 'ms': + return n; + default: + return undefined; + } +} -/***/ }), -/* 185 */ -/***/ (function(module, exports) { +/** + * Short format for `ms`. + * + * @param {Number} ms + * @return {String} + * @api private + */ -// fast apply, http://jsperf.lnkit.com/fast-apply/5 -module.exports = function (fn, args, that) { - var un = that === undefined; - switch (args.length) { - case 0: return un ? fn() - : fn.call(that); - case 1: return un ? fn(args[0]) - : fn.call(that, args[0]); - case 2: return un ? fn(args[0], args[1]) - : fn.call(that, args[0], args[1]); - case 3: return un ? fn(args[0], args[1], args[2]) - : fn.call(that, args[0], args[1], args[2]); - case 4: return un ? fn(args[0], args[1], args[2], args[3]) - : fn.call(that, args[0], args[1], args[2], args[3]); - } return fn.apply(that, args); -}; +function fmtShort(ms) { + if (ms >= d) { + return Math.round(ms / d) + 'd'; + } + if (ms >= h) { + return Math.round(ms / h) + 'h'; + } + if (ms >= m) { + return Math.round(ms / m) + 'm'; + } + if (ms >= s) { + return Math.round(ms / s) + 's'; + } + return ms + 'ms'; +} +/** + * Long format for `ms`. + * + * @param {Number} ms + * @return {String} + * @api private + */ -/***/ }), -/* 186 */ -/***/ (function(module, exports, __webpack_require__) { +function fmtLong(ms) { + return plural(ms, d, 'day') || + plural(ms, h, 'hour') || + plural(ms, m, 'minute') || + plural(ms, s, 'second') || + ms + ' ms'; +} -// check on default Array iterator -var Iterators = __webpack_require__(35); -var ITERATOR = __webpack_require__(13)('iterator'); -var ArrayProto = Array.prototype; +/** + * Pluralization helper. + */ -module.exports = function (it) { - return it !== undefined && (Iterators.Array === it || ArrayProto[ITERATOR] === it); -}; +function plural(ms, n, name) { + if (ms < n) { + return; + } + if (ms < n * 1.5) { + return Math.floor(ms / n) + ' ' + name; + } + return Math.ceil(ms / n) + ' ' + name + 's'; +} /***/ }), -/* 187 */ +/* 230 */, +/* 231 */, +/* 232 */, +/* 233 */ /***/ (function(module, exports, __webpack_require__) { -// call something on iterator step with safe closing on error -var anObject = __webpack_require__(27); -module.exports = function (iterator, fn, value, entries) { - try { - return entries ? fn(anObject(value)[0], value[1]) : fn(value); - // 7.4.6 IteratorClose(iterator, completion) - } catch (e) { - var ret = iterator['return']; - if (ret !== undefined) anObject(ret.call(iterator)); - throw e; - } -}; +module.exports = rimraf +rimraf.sync = rimrafSync +var assert = __webpack_require__(22) +var path = __webpack_require__(0) +var fs = __webpack_require__(3) +var glob = __webpack_require__(75) +var _0666 = parseInt('666', 8) -/***/ }), -/* 188 */ -/***/ (function(module, exports, __webpack_require__) { +var defaultGlobOpts = { + nosort: true, + silent: true +} -"use strict"; +// for EMFILE handling +var timeout = 0 -var create = __webpack_require__(192); -var descriptor = __webpack_require__(106); -var setToStringTag = __webpack_require__(71); -var IteratorPrototype = {}; +var isWindows = (process.platform === "win32") -// 25.1.2.1.1 %IteratorPrototype%[@@iterator]() -__webpack_require__(31)(IteratorPrototype, __webpack_require__(13)('iterator'), function () { return this; }); +function defaults (options) { + var methods = [ + 'unlink', + 'chmod', + 'stat', + 'lstat', + 'rmdir', + 'readdir' + ] + methods.forEach(function(m) { + options[m] = options[m] || fs[m] + m = m + 'Sync' + options[m] = options[m] || fs[m] + }) -module.exports = function (Constructor, NAME, next) { - Constructor.prototype = create(IteratorPrototype, { next: descriptor(1, next) }); - setToStringTag(Constructor, NAME + ' Iterator'); -}; + options.maxBusyTries = options.maxBusyTries || 3 + options.emfileWait = options.emfileWait || 1000 + if (options.glob === false) { + options.disableGlob = true + } + options.disableGlob = options.disableGlob || false + options.glob = options.glob || defaultGlobOpts +} +function rimraf (p, options, cb) { + if (typeof options === 'function') { + cb = options + options = {} + } -/***/ }), -/* 189 */ -/***/ (function(module, exports, __webpack_require__) { + assert(p, 'rimraf: missing path') + assert.equal(typeof p, 'string', 'rimraf: path should be a string') + assert.equal(typeof cb, 'function', 'rimraf: callback function required') + assert(options, 'rimraf: invalid options argument provided') + assert.equal(typeof options, 'object', 'rimraf: options should be object') -var ITERATOR = __webpack_require__(13)('iterator'); -var SAFE_CLOSING = false; + defaults(options) -try { - var riter = [7][ITERATOR](); - riter['return'] = function () { SAFE_CLOSING = true; }; - // eslint-disable-next-line no-throw-literal - Array.from(riter, function () { throw 2; }); -} catch (e) { /* empty */ } + var busyTries = 0 + var errState = null + var n = 0 -module.exports = function (exec, skipClosing) { - if (!skipClosing && !SAFE_CLOSING) return false; - var safe = false; - try { - var arr = [7]; - var iter = arr[ITERATOR](); - iter.next = function () { return { done: safe = true }; }; - arr[ITERATOR] = function () { return iter; }; - exec(arr); - } catch (e) { /* empty */ } - return safe; -}; + if (options.disableGlob || !glob.hasMagic(p)) + return afterGlob(null, [p]) + options.lstat(p, function (er, stat) { + if (!er) + return afterGlob(null, [p]) -/***/ }), -/* 190 */ -/***/ (function(module, exports) { + glob(p, options.glob, afterGlob) + }) -module.exports = function (done, value) { - return { value: value, done: !!done }; -}; + function next (er) { + errState = errState || er + if (--n === 0) + cb(errState) + } + function afterGlob (er, results) { + if (er) + return cb(er) -/***/ }), -/* 191 */ -/***/ (function(module, exports, __webpack_require__) { + n = results.length + if (n === 0) + return cb() -var global = __webpack_require__(11); -var macrotask = __webpack_require__(109).set; -var Observer = global.MutationObserver || global.WebKitMutationObserver; -var process = global.process; -var Promise = global.Promise; -var isNode = __webpack_require__(47)(process) == 'process'; + results.forEach(function (p) { + rimraf_(p, options, function CB (er) { + if (er) { + if ((er.code === "EBUSY" || er.code === "ENOTEMPTY" || er.code === "EPERM") && + busyTries < options.maxBusyTries) { + busyTries ++ + var time = busyTries * 100 + // try again, with the same exact callback as this one. + return setTimeout(function () { + rimraf_(p, options, CB) + }, time) + } -module.exports = function () { - var head, last, notify; + // this one won't happen if graceful-fs is used. + if (er.code === "EMFILE" && timeout < options.emfileWait) { + return setTimeout(function () { + rimraf_(p, options, CB) + }, timeout ++) + } - var flush = function () { - var parent, fn; - if (isNode && (parent = process.domain)) parent.exit(); - while (head) { - fn = head.fn; - head = head.next; - try { - fn(); - } catch (e) { - if (head) notify(); - else last = undefined; - throw e; - } - } last = undefined; - if (parent) parent.enter(); - }; + // already gone + if (er.code === "ENOENT") er = null + } - // Node.js - if (isNode) { - notify = function () { - process.nextTick(flush); - }; - // browsers with MutationObserver, except iOS Safari - https://github.com/zloirock/core-js/issues/339 - } else if (Observer && !(global.navigator && global.navigator.standalone)) { - var toggle = true; - var node = document.createTextNode(''); - new Observer(flush).observe(node, { characterData: true }); // eslint-disable-line no-new - notify = function () { - node.data = toggle = !toggle; - }; - // environments with maybe non-completely correct, but existent Promise - } else if (Promise && Promise.resolve) { - // Promise.resolve without an argument throws an error in LG WebOS 2 - var promise = Promise.resolve(undefined); - notify = function () { - promise.then(flush); - }; - // for other environments - macrotask based on: - // - setImmediate - // - MessageChannel - // - window.postMessag - // - onreadystatechange - // - setTimeout - } else { - notify = function () { - // strange IE + webpack dev server bug - use .call(global) - macrotask.call(global, flush); - }; + timeout = 0 + next(er) + }) + }) } +} - return function (fn) { - var task = { fn: fn, next: undefined }; - if (last) last.next = task; - if (!head) { - head = task; - notify(); - } last = task; - }; -}; +// Two possible strategies. +// 1. Assume it's a file. unlink it, then do the dir stuff on EPERM or EISDIR +// 2. Assume it's a directory. readdir, then do the file stuff on ENOTDIR +// +// Both result in an extra syscall when you guess wrong. However, there +// are likely far more normal files in the world than directories. This +// is based on the assumption that a the average number of files per +// directory is >= 1. +// +// If anyone ever complains about this, then I guess the strategy could +// be made configurable somehow. But until then, YAGNI. +function rimraf_ (p, options, cb) { + assert(p) + assert(options) + assert(typeof cb === 'function') + // sunos lets the root user unlink directories, which is... weird. + // so we have to lstat here and make sure it's not a dir. + options.lstat(p, function (er, st) { + if (er && er.code === "ENOENT") + return cb(null) -/***/ }), -/* 192 */ -/***/ (function(module, exports, __webpack_require__) { + // Windows can EPERM on stat. Life is suffering. + if (er && er.code === "EPERM" && isWindows) + fixWinEPERM(p, options, er, cb) -// 19.1.2.2 / 15.2.3.5 Object.create(O [, Properties]) -var anObject = __webpack_require__(27); -var dPs = __webpack_require__(193); -var enumBugKeys = __webpack_require__(101); -var IE_PROTO = __webpack_require__(72)('IE_PROTO'); -var Empty = function () { /* empty */ }; -var PROTOTYPE = 'prototype'; + if (st && st.isDirectory()) + return rmdir(p, options, er, cb) -// Create object with fake `null` prototype: use iframe Object with cleared prototype -var createDict = function () { - // Thrash, waste and sodomy: IE GC bug - var iframe = __webpack_require__(68)('iframe'); - var i = enumBugKeys.length; - var lt = '<'; - var gt = '>'; - var iframeDocument; - iframe.style.display = 'none'; - __webpack_require__(102).appendChild(iframe); - iframe.src = 'javascript:'; // eslint-disable-line no-script-url - // createDict = iframe.contentWindow.Object; - // html.removeChild(iframe); - iframeDocument = iframe.contentWindow.document; - iframeDocument.open(); - iframeDocument.write(lt + 'script' + gt + 'document.F=Object' + lt + '/script' + gt); - iframeDocument.close(); - createDict = iframeDocument.F; - while (i--) delete createDict[PROTOTYPE][enumBugKeys[i]]; - return createDict(); -}; + options.unlink(p, function (er) { + if (er) { + if (er.code === "ENOENT") + return cb(null) + if (er.code === "EPERM") + return (isWindows) + ? fixWinEPERM(p, options, er, cb) + : rmdir(p, options, er, cb) + if (er.code === "EISDIR") + return rmdir(p, options, er, cb) + } + return cb(er) + }) + }) +} -module.exports = Object.create || function create(O, Properties) { - var result; - if (O !== null) { - Empty[PROTOTYPE] = anObject(O); - result = new Empty(); - Empty[PROTOTYPE] = null; - // add "__proto__" for Object.getPrototypeOf polyfill - result[IE_PROTO] = O; - } else result = createDict(); - return Properties === undefined ? result : dPs(result, Properties); -}; +function fixWinEPERM (p, options, er, cb) { + assert(p) + assert(options) + assert(typeof cb === 'function') + if (er) + assert(er instanceof Error) + options.chmod(p, _0666, function (er2) { + if (er2) + cb(er2.code === "ENOENT" ? null : er) + else + options.stat(p, function(er3, stats) { + if (er3) + cb(er3.code === "ENOENT" ? null : er) + else if (stats.isDirectory()) + rmdir(p, options, er, cb) + else + options.unlink(p, cb) + }) + }) +} -/***/ }), -/* 193 */ -/***/ (function(module, exports, __webpack_require__) { +function fixWinEPERMSync (p, options, er) { + assert(p) + assert(options) + if (er) + assert(er instanceof Error) -var dP = __webpack_require__(50); -var anObject = __webpack_require__(27); -var getKeys = __webpack_require__(132); + try { + options.chmodSync(p, _0666) + } catch (er2) { + if (er2.code === "ENOENT") + return + else + throw er + } -module.exports = __webpack_require__(33) ? Object.defineProperties : function defineProperties(O, Properties) { - anObject(O); - var keys = getKeys(Properties); - var length = keys.length; - var i = 0; - var P; - while (length > i) dP.f(O, P = keys[i++], Properties[P]); - return O; -}; + try { + var stats = options.statSync(p) + } catch (er3) { + if (er3.code === "ENOENT") + return + else + throw er + } + if (stats.isDirectory()) + rmdirSync(p, options, er) + else + options.unlinkSync(p) +} -/***/ }), -/* 194 */ -/***/ (function(module, exports, __webpack_require__) { +function rmdir (p, options, originalEr, cb) { + assert(p) + assert(options) + if (originalEr) + assert(originalEr instanceof Error) + assert(typeof cb === 'function') -// 19.1.2.9 / 15.2.3.2 Object.getPrototypeOf(O) -var has = __webpack_require__(49); -var toObject = __webpack_require__(133); -var IE_PROTO = __webpack_require__(72)('IE_PROTO'); -var ObjectProto = Object.prototype; + // try to rmdir first, and only readdir on ENOTEMPTY or EEXIST (SunOS) + // if we guessed wrong, and it's not a directory, then + // raise the original error. + options.rmdir(p, function (er) { + if (er && (er.code === "ENOTEMPTY" || er.code === "EEXIST" || er.code === "EPERM")) + rmkids(p, options, cb) + else if (er && er.code === "ENOTDIR") + cb(originalEr) + else + cb(er) + }) +} -module.exports = Object.getPrototypeOf || function (O) { - O = toObject(O); - if (has(O, IE_PROTO)) return O[IE_PROTO]; - if (typeof O.constructor == 'function' && O instanceof O.constructor) { - return O.constructor.prototype; - } return O instanceof Object ? ObjectProto : null; -}; +function rmkids(p, options, cb) { + assert(p) + assert(options) + assert(typeof cb === 'function') + options.readdir(p, function (er, files) { + if (er) + return cb(er) + var n = files.length + if (n === 0) + return options.rmdir(p, cb) + var errState + files.forEach(function (f) { + rimraf(path.join(p, f), options, function (er) { + if (errState) + return + if (er) + return cb(errState = er) + if (--n === 0) + options.rmdir(p, cb) + }) + }) + }) +} -/***/ }), -/* 195 */ -/***/ (function(module, exports, __webpack_require__) { +// this looks simpler, and is strictly *faster*, but will +// tie up the JavaScript thread and fail on excessively +// deep directory trees. +function rimrafSync (p, options) { + options = options || {} + defaults(options) -var has = __webpack_require__(49); -var toIObject = __webpack_require__(74); -var arrayIndexOf = __webpack_require__(182)(false); -var IE_PROTO = __webpack_require__(72)('IE_PROTO'); + assert(p, 'rimraf: missing path') + assert.equal(typeof p, 'string', 'rimraf: path should be a string') + assert(options, 'rimraf: missing options') + assert.equal(typeof options, 'object', 'rimraf: options should be object') -module.exports = function (object, names) { - var O = toIObject(object); - var i = 0; - var result = []; - var key; - for (key in O) if (key != IE_PROTO) has(O, key) && result.push(key); - // Don't enum bug & hidden keys - while (names.length > i) if (has(O, key = names[i++])) { - ~arrayIndexOf(result, key) || result.push(key); - } - return result; -}; + var results + if (options.disableGlob || !glob.hasMagic(p)) { + results = [p] + } else { + try { + options.lstatSync(p) + results = [p] + } catch (er) { + results = glob.sync(p, options.glob) + } + } -/***/ }), -/* 196 */ -/***/ (function(module, exports, __webpack_require__) { + if (!results.length) + return -var hide = __webpack_require__(31); -module.exports = function (target, src, safe) { - for (var key in src) { - if (safe && target[key]) target[key] = src[key]; - else hide(target, key, src[key]); - } return target; -}; + for (var i = 0; i < results.length; i++) { + var p = results[i] + try { + var st = options.lstatSync(p) + } catch (er) { + if (er.code === "ENOENT") + return -/***/ }), -/* 197 */ -/***/ (function(module, exports, __webpack_require__) { + // Windows can EPERM on stat. Life is suffering. + if (er.code === "EPERM" && isWindows) + fixWinEPERMSync(p, options, er) + } -module.exports = __webpack_require__(31); + try { + // sunos lets the root user unlink directories, which is... weird. + if (st && st.isDirectory()) + rmdirSync(p, options, null) + else + options.unlinkSync(p) + } catch (er) { + if (er.code === "ENOENT") + return + if (er.code === "EPERM") + return isWindows ? fixWinEPERMSync(p, options, er) : rmdirSync(p, options, er) + if (er.code !== "EISDIR") + throw er + rmdirSync(p, options, er) + } + } +} -/***/ }), -/* 198 */ -/***/ (function(module, exports, __webpack_require__) { +function rmdirSync (p, options, originalEr) { + assert(p) + assert(options) + if (originalEr) + assert(originalEr instanceof Error) -"use strict"; + try { + options.rmdirSync(p) + } catch (er) { + if (er.code === "ENOENT") + return + if (er.code === "ENOTDIR") + throw originalEr + if (er.code === "ENOTEMPTY" || er.code === "EEXIST" || er.code === "EPERM") + rmkidsSync(p, options) + } +} -var global = __webpack_require__(11); -var core = __webpack_require__(23); -var dP = __webpack_require__(50); -var DESCRIPTORS = __webpack_require__(33); -var SPECIES = __webpack_require__(13)('species'); +function rmkidsSync (p, options) { + assert(p) + assert(options) + options.readdirSync(p).forEach(function (f) { + rimrafSync(path.join(p, f), options) + }) -module.exports = function (KEY) { - var C = typeof core[KEY] == 'function' ? core[KEY] : global[KEY]; - if (DESCRIPTORS && C && !C[SPECIES]) dP.f(C, SPECIES, { - configurable: true, - get: function () { return this; } - }); -}; + // We only end up here once we got ENOTEMPTY at least once, and + // at this point, we are guaranteed to have removed all the kids. + // So, we know that it won't be ENOENT or ENOTDIR or anything else. + // try really hard to delete stuff on windows, because it has a + // PROFOUNDLY annoying habit of not closing handles promptly when + // files are deleted, resulting in spurious ENOTEMPTY errors. + var retries = isWindows ? 100 : 1 + var i = 0 + do { + var threw = true + try { + var ret = options.rmdirSync(p, options) + threw = false + return ret + } finally { + if (++i < retries && threw) + continue + } + } while (true) +} /***/ }), -/* 199 */ +/* 234 */, +/* 235 */, +/* 236 */, +/* 237 */, +/* 238 */, +/* 239 */ /***/ (function(module, exports, __webpack_require__) { -var toInteger = __webpack_require__(73); -var defined = __webpack_require__(67); -// true -> String#at -// false -> String#codePointAt -module.exports = function (TO_STRING) { - return function (that, pos) { - var s = String(defined(that)); - var i = toInteger(pos); - var l = s.length; - var a, b; - if (i < 0 || i >= l) return TO_STRING ? '' : undefined; - a = s.charCodeAt(i); - return a < 0xd800 || a > 0xdbff || i + 1 === l || (b = s.charCodeAt(i + 1)) < 0xdc00 || b > 0xdfff - ? TO_STRING ? s.charAt(i) : a - : TO_STRING ? s.slice(i, i + 2) : (a - 0xd800 << 10) + (b - 0xdc00) + 0x10000; - }; -}; +"use strict"; +var hasFlag = __webpack_require__(221); -/***/ }), -/* 200 */ -/***/ (function(module, exports, __webpack_require__) { +var support = function (level) { + if (level === 0) { + return false; + } -var toInteger = __webpack_require__(73); -var max = Math.max; -var min = Math.min; -module.exports = function (index, length) { - index = toInteger(index); - return index < 0 ? max(index + length, 0) : min(index, length); + return { + level: level, + hasBasic: true, + has256: level >= 2, + has16m: level >= 3 + }; }; +var supportLevel = (function () { + if (hasFlag('no-color') || + hasFlag('no-colors') || + hasFlag('color=false')) { + return 0; + } -/***/ }), -/* 201 */ -/***/ (function(module, exports, __webpack_require__) { + if (hasFlag('color=16m') || + hasFlag('color=full') || + hasFlag('color=truecolor')) { + return 3; + } -// 7.1.1 ToPrimitive(input [, PreferredType]) -var isObject = __webpack_require__(34); -// instead of the ES6 spec version, we didn't implement @@toPrimitive case -// and the second argument - flag - preferred type is a string -module.exports = function (it, S) { - if (!isObject(it)) return it; - var fn, val; - if (S && typeof (fn = it.toString) == 'function' && !isObject(val = fn.call(it))) return val; - if (typeof (fn = it.valueOf) == 'function' && !isObject(val = fn.call(it))) return val; - if (!S && typeof (fn = it.toString) == 'function' && !isObject(val = fn.call(it))) return val; - throw TypeError("Can't convert object to primitive value"); -}; + if (hasFlag('color=256')) { + return 2; + } + if (hasFlag('color') || + hasFlag('colors') || + hasFlag('color=true') || + hasFlag('color=always')) { + return 1; + } -/***/ }), -/* 202 */ -/***/ (function(module, exports, __webpack_require__) { + if (process.stdout && !process.stdout.isTTY) { + return 0; + } -var global = __webpack_require__(11); -var navigator = global.navigator; + if (process.platform === 'win32') { + return 1; + } -module.exports = navigator && navigator.userAgent || ''; + if ('CI' in process.env) { + if ('TRAVIS' in process.env || process.env.CI === 'Travis') { + return 1; + } + return 0; + } -/***/ }), -/* 203 */ -/***/ (function(module, exports, __webpack_require__) { + if ('TEAMCITY_VERSION' in process.env) { + return process.env.TEAMCITY_VERSION.match(/^(9\.(0*[1-9]\d*)\.|\d{2,}\.)/) === null ? 0 : 1; + } -var classof = __webpack_require__(100); -var ITERATOR = __webpack_require__(13)('iterator'); -var Iterators = __webpack_require__(35); -module.exports = __webpack_require__(23).getIteratorMethod = function (it) { - if (it != undefined) return it[ITERATOR] - || it['@@iterator'] - || Iterators[classof(it)]; -}; + if (/^(screen|xterm)-256(?:color)?/.test(process.env.TERM)) { + return 2; + } + if (/^screen|^xterm|^vt100|color|ansi|cygwin|linux/i.test(process.env.TERM)) { + return 1; + } -/***/ }), -/* 204 */ -/***/ (function(module, exports, __webpack_require__) { + if ('COLORTERM' in process.env) { + return 1; + } -"use strict"; + if (process.env.TERM === 'dumb') { + return 0; + } -var addToUnscopables = __webpack_require__(180); -var step = __webpack_require__(190); -var Iterators = __webpack_require__(35); -var toIObject = __webpack_require__(74); + return 0; +})(); -// 22.1.3.4 Array.prototype.entries() -// 22.1.3.13 Array.prototype.keys() -// 22.1.3.29 Array.prototype.values() -// 22.1.3.30 Array.prototype[@@iterator]() -module.exports = __webpack_require__(103)(Array, 'Array', function (iterated, kind) { - this._t = toIObject(iterated); // target - this._i = 0; // next index - this._k = kind; // kind -// 22.1.5.2.1 %ArrayIteratorPrototype%.next() -}, function () { - var O = this._t; - var kind = this._k; - var index = this._i++; - if (!O || index >= O.length) { - this._t = undefined; - return step(1); - } - if (kind == 'keys') return step(0, index); - if (kind == 'values') return step(0, O[index]); - return step(0, [index, O[index]]); -}, 'values'); +if (supportLevel === 0 && 'FORCE_COLOR' in process.env) { + supportLevel = 1; +} -// argumentsList[@@iterator] is %ArrayProto_values% (9.4.4.6, 9.4.4.7) -Iterators.Arguments = Iterators.Array; +module.exports = process && support(supportLevel); -addToUnscopables('keys'); -addToUnscopables('values'); -addToUnscopables('entries'); +/***/ }) +/******/ ]); /***/ }), -/* 205 */ +/* 277 */ /***/ (function(module, exports) { - +module.exports = require("buffer"); /***/ }), -/* 206 */ -/***/ (function(module, exports, __webpack_require__) { +/* 278 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "BootstrapCacheFile", function() { return BootstrapCacheFile; }); +/* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(134); +/* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(fs__WEBPACK_IMPORTED_MODULE_0__); +/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(4); +/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_1__); +function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } -var LIBRARY = __webpack_require__(69); -var global = __webpack_require__(11); -var ctx = __webpack_require__(48); -var classof = __webpack_require__(100); -var $export = __webpack_require__(41); -var isObject = __webpack_require__(34); -var aFunction = __webpack_require__(46); -var anInstance = __webpack_require__(181); -var forOf = __webpack_require__(183); -var speciesConstructor = __webpack_require__(108); -var task = __webpack_require__(109).set; -var microtask = __webpack_require__(191)(); -var newPromiseCapabilityModule = __webpack_require__(70); -var perform = __webpack_require__(104); -var userAgent = __webpack_require__(202); -var promiseResolve = __webpack_require__(105); -var PROMISE = 'Promise'; -var TypeError = global.TypeError; -var process = global.process; -var versions = process && process.versions; -var v8 = versions && versions.v8 || ''; -var $Promise = global[PROMISE]; -var isNode = classof(process) == 'process'; -var empty = function () { /* empty */ }; -var Internal, newGenericPromiseCapability, OwnPromiseCapability, Wrapper; -var newPromiseCapability = newGenericPromiseCapability = newPromiseCapabilityModule.f; +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ -var USE_NATIVE = !!function () { - try { - // correct subclassing with @@species support - var promise = $Promise.resolve(1); - var FakePromise = (promise.constructor = {})[__webpack_require__(13)('species')] = function (exec) { - exec(empty, empty); - }; - // unhandled rejections tracking support, NodeJS Promise without it fails @@species test - return (isNode || typeof PromiseRejectionEvent == 'function') - && promise.then(empty) instanceof FakePromise - // v8 6.6 (Node 10 and Chrome 66) have a bug with resolving custom thenables - // https://bugs.chromium.org/p/chromium/issues/detail?id=830565 - // we can't detect it synchronously, so just check versions - && v8.indexOf('6.6') !== 0 - && userAgent.indexOf('Chrome/66') === -1; - } catch (e) { /* empty */ } -}(); -// helpers -var isThenable = function (it) { - var then; - return isObject(it) && typeof (then = it.then) == 'function' ? then : false; -}; -var notify = function (promise, isReject) { - if (promise._n) return; - promise._n = true; - var chain = promise._c; - microtask(function () { - var value = promise._v; - var ok = promise._s == 1; - var i = 0; - var run = function (reaction) { - var handler = ok ? reaction.ok : reaction.fail; - var resolve = reaction.resolve; - var reject = reaction.reject; - var domain = reaction.domain; - var result, then, exited; - try { - if (handler) { - if (!ok) { - if (promise._h == 2) onHandleUnhandled(promise); - promise._h = 1; - } - if (handler === true) result = value; - else { - if (domain) domain.enter(); - result = handler(value); // may throw - if (domain) { - domain.exit(); - exited = true; - } - } - if (result === reaction.promise) { - reject(TypeError('Promise-chain cycle')); - } else if (then = isThenable(result)) { - then.call(result, resolve, reject); - } else resolve(result); - } else reject(value); - } catch (e) { - if (domain && !exited) domain.exit(); - reject(e); +class BootstrapCacheFile { + constructor(kbn, project, checksums) { + _defineProperty(this, "path", void 0); + + _defineProperty(this, "expectedValue", void 0); + + this.path = path__WEBPACK_IMPORTED_MODULE_1___default.a.resolve(project.targetLocation, '.bootstrap-cache'); + + if (!checksums) { + return; + } + + const projectAndDepCacheKeys = Array.from(kbn.getProjectAndDeps(project.name).values()) // sort deps by name so that the key is stable + .sort((a, b) => a.name.localeCompare(b.name)) // get the cacheKey for each project, return undefined if the cache key couldn't be determined + .map(p => { + const cacheKey = checksums.get(p.name); + + if (cacheKey) { + return `${p.name}:${cacheKey}`; } - }; - while (chain.length > i) run(chain[i++]); // variable length - can't use forEach - promise._c = []; - promise._n = false; - if (isReject && !promise._h) onUnhandled(promise); - }); -}; -var onUnhandled = function (promise) { - task.call(global, function () { - var value = promise._v; - var unhandled = isUnhandled(promise); - var result, handler, console; - if (unhandled) { - result = perform(function () { - if (isNode) { - process.emit('unhandledRejection', value, promise); - } else if (handler = global.onunhandledrejection) { - handler({ promise: promise, reason: value }); - } else if ((console = global.console) && console.error) { - console.error('Unhandled promise rejection', value); - } - }); - // Browsers should not trigger `rejectionHandled` event if it was handled here, NodeJS - should - promise._h = isNode || isUnhandled(promise) ? 2 : 1; - } promise._a = undefined; - if (unhandled && result.e) throw result.v; - }); -}; -var isUnhandled = function (promise) { - return promise._h !== 1 && (promise._a || promise._c).length === 0; -}; -var onHandleUnhandled = function (promise) { - task.call(global, function () { - var handler; - if (isNode) { - process.emit('rejectionHandled', promise); - } else if (handler = global.onrejectionhandled) { - handler({ promise: promise, reason: promise._v }); + }); // if any of the relevant cache keys are undefined then the projectCacheKey must be too + + this.expectedValue = projectAndDepCacheKeys.some(k => !k) ? undefined : [`# this is only human readable for debugging, please don't try to parse this`, ...projectAndDepCacheKeys].join('\n'); + } + + isValid() { + if (!this.expectedValue) { + return false; } - }); -}; -var $reject = function (value) { - var promise = this; - if (promise._d) return; - promise._d = true; - promise = promise._w || promise; // unwrap - promise._v = value; - promise._s = 2; - if (!promise._a) promise._a = promise._c.slice(); - notify(promise, true); -}; -var $resolve = function (value) { - var promise = this; - var then; - if (promise._d) return; - promise._d = true; - promise = promise._w || promise; // unwrap - try { - if (promise === value) throw TypeError("Promise can't be resolved itself"); - if (then = isThenable(value)) { - microtask(function () { - var wrapper = { _w: promise, _d: false }; // wrap - try { - then.call(value, ctx($resolve, wrapper, 1), ctx($reject, wrapper, 1)); - } catch (e) { - $reject.call(wrapper, e); - } - }); - } else { - promise._v = value; - promise._s = 1; - notify(promise, false); + + try { + return fs__WEBPACK_IMPORTED_MODULE_0___default.a.readFileSync(this.path, 'utf8') === this.expectedValue; + } catch (error) { + if (error.code === 'ENOENT') { + return false; + } + + throw error; } - } catch (e) { - $reject.call({ _w: promise, _d: false }, e); // wrap } -}; -// constructor polyfill -if (!USE_NATIVE) { - // 25.4.3.1 Promise(executor) - $Promise = function Promise(executor) { - anInstance(this, $Promise, PROMISE, '_h'); - aFunction(executor); - Internal.call(this); + delete() { try { - executor(ctx($resolve, this, 1), ctx($reject, this, 1)); - } catch (err) { - $reject.call(this, err); - } - }; - // eslint-disable-next-line no-unused-vars - Internal = function Promise(executor) { - this._c = []; // <- awaiting reactions - this._a = undefined; // <- checked in isUnhandled reactions - this._s = 0; // <- state - this._d = false; // <- done - this._v = undefined; // <- value - this._h = 0; // <- rejection state, 0 - default, 1 - handled, 2 - unhandled - this._n = false; // <- notify - }; - Internal.prototype = __webpack_require__(196)($Promise.prototype, { - // 25.4.5.3 Promise.prototype.then(onFulfilled, onRejected) - then: function then(onFulfilled, onRejected) { - var reaction = newPromiseCapability(speciesConstructor(this, $Promise)); - reaction.ok = typeof onFulfilled == 'function' ? onFulfilled : true; - reaction.fail = typeof onRejected == 'function' && onRejected; - reaction.domain = isNode ? process.domain : undefined; - this._c.push(reaction); - if (this._a) this._a.push(reaction); - if (this._s) notify(this, false); - return reaction.promise; - }, - // 25.4.5.1 Promise.prototype.catch(onRejected) - 'catch': function (onRejected) { - return this.then(undefined, onRejected); + fs__WEBPACK_IMPORTED_MODULE_0___default.a.unlinkSync(this.path); + } catch (error) { + if (error.code !== 'ENOENT') { + throw error; + } } - }); - OwnPromiseCapability = function () { - var promise = new Internal(); - this.promise = promise; - this.resolve = ctx($resolve, promise, 1); - this.reject = ctx($reject, promise, 1); - }; - newPromiseCapabilityModule.f = newPromiseCapability = function (C) { - return C === $Promise || C === Wrapper - ? new OwnPromiseCapability(C) - : newGenericPromiseCapability(C); - }; -} + } -$export($export.G + $export.W + $export.F * !USE_NATIVE, { Promise: $Promise }); -__webpack_require__(71)($Promise, PROMISE); -__webpack_require__(198)(PROMISE); -Wrapper = __webpack_require__(23)[PROMISE]; + write() { + if (!this.expectedValue) { + return; + } -// statics -$export($export.S + $export.F * !USE_NATIVE, PROMISE, { - // 25.4.4.5 Promise.reject(r) - reject: function reject(r) { - var capability = newPromiseCapability(this); - var $$reject = capability.reject; - $$reject(r); - return capability.promise; - } -}); -$export($export.S + $export.F * (LIBRARY || !USE_NATIVE), PROMISE, { - // 25.4.4.6 Promise.resolve(x) - resolve: function resolve(x) { - return promiseResolve(LIBRARY && this === Wrapper ? $Promise : this, x); - } -}); -$export($export.S + $export.F * !(USE_NATIVE && __webpack_require__(189)(function (iter) { - $Promise.all(iter)['catch'](empty); -})), PROMISE, { - // 25.4.4.1 Promise.all(iterable) - all: function all(iterable) { - var C = this; - var capability = newPromiseCapability(C); - var resolve = capability.resolve; - var reject = capability.reject; - var result = perform(function () { - var values = []; - var index = 0; - var remaining = 1; - forOf(iterable, false, function (promise) { - var $index = index++; - var alreadyCalled = false; - values.push(undefined); - remaining++; - C.resolve(promise).then(function (value) { - if (alreadyCalled) return; - alreadyCalled = true; - values[$index] = value; - --remaining || resolve(values); - }, reject); - }); - --remaining || resolve(values); - }); - if (result.e) reject(result.v); - return capability.promise; - }, - // 25.4.4.4 Promise.race(iterable) - race: function race(iterable) { - var C = this; - var capability = newPromiseCapability(C); - var reject = capability.reject; - var result = perform(function () { - forOf(iterable, false, function (promise) { - C.resolve(promise).then(capability.resolve, reject); - }); + fs__WEBPACK_IMPORTED_MODULE_0___default.a.mkdirSync(path__WEBPACK_IMPORTED_MODULE_1___default.a.dirname(this.path), { + recursive: true }); - if (result.e) reject(result.v); - return capability.promise; + fs__WEBPACK_IMPORTED_MODULE_0___default.a.writeFileSync(this.path, this.expectedValue); } -}); +} /***/ }), -/* 207 */ -/***/ (function(module, exports, __webpack_require__) { +/* 279 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "validateYarnLock", function() { return validateYarnLock; }); +/* harmony import */ var _yarnpkg_lockfile__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(276); +/* harmony import */ var _yarnpkg_lockfile__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_yarnpkg_lockfile__WEBPACK_IMPORTED_MODULE_0__); +/* harmony import */ var dedent__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(2); +/* harmony import */ var dedent__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(dedent__WEBPACK_IMPORTED_MODULE_1__); +/* harmony import */ var _fs__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(131); +/* harmony import */ var _log__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(144); +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +// @ts-expect-error published types are useless -var $at = __webpack_require__(199)(true); -// 21.1.3.27 String.prototype[@@iterator]() -__webpack_require__(103)(String, 'String', function (iterated) { - this._t = String(iterated); // target - this._i = 0; // next index -// 21.1.5.2.1 %StringIteratorPrototype%.next() -}, function () { - var O = this._t; - var index = this._i; - var point; - if (index >= O.length) return { value: undefined, done: true }; - point = $at(O, index); - this._i += point.length; - return { value: point, done: false }; -}); -/***/ }), -/* 208 */ -/***/ (function(module, exports, __webpack_require__) { +async function validateYarnLock(kbn, yarnLock) { + // look through all of the packages in the yarn.lock file to see if + // we have accidentally installed multiple lodash v4 versions + const lodash4Versions = new Set(); + const lodash4Reqs = new Set(); -"use strict"; -// https://github.com/tc39/proposal-promise-finally + for (const [req, dep] of Object.entries(yarnLock)) { + if (req.startsWith('lodash@') && dep.version.startsWith('4.')) { + lodash4Reqs.add(req); + lodash4Versions.add(dep.version); + } + } // if we find more than one lodash v4 version installed then delete + // lodash v4 requests from the yarn.lock file and prompt the user to + // retry bootstrap so that a single v4 version will be installed -var $export = __webpack_require__(41); -var core = __webpack_require__(23); -var global = __webpack_require__(11); -var speciesConstructor = __webpack_require__(108); -var promiseResolve = __webpack_require__(105); -$export($export.P + $export.R, 'Promise', { 'finally': function (onFinally) { - var C = speciesConstructor(this, core.Promise || global.Promise); - var isFunction = typeof onFinally == 'function'; - return this.then( - isFunction ? function (x) { - return promiseResolve(C, onFinally()).then(function () { return x; }); - } : onFinally, - isFunction ? function (e) { - return promiseResolve(C, onFinally()).then(function () { throw e; }); - } : onFinally - ); -} }); + if (lodash4Versions.size > 1) { + for (const req of lodash4Reqs) { + delete yarnLock[req]; + } + await Object(_fs__WEBPACK_IMPORTED_MODULE_2__["writeFile"])(kbn.getAbsolute('yarn.lock'), Object(_yarnpkg_lockfile__WEBPACK_IMPORTED_MODULE_0__["stringify"])(yarnLock), 'utf8'); + _log__WEBPACK_IMPORTED_MODULE_3__["log"].error(dedent__WEBPACK_IMPORTED_MODULE_1___default.a` -/***/ }), -/* 209 */ -/***/ (function(module, exports, __webpack_require__) { + Multiple version of lodash v4 were detected, so they have been removed + from the yarn.lock file. Please rerun yarn kbn bootstrap to coalese the + lodash versions installed. -"use strict"; + If you still see this error when you re-bootstrap then you might need + to force a new dependency to use the latest version of lodash via the + "resolutions" field in package.json. -// https://github.com/tc39/proposal-promise-try -var $export = __webpack_require__(41); -var newPromiseCapability = __webpack_require__(70); -var perform = __webpack_require__(104); + If you have questions about this please reach out to the operations team. -$export($export.S, 'Promise', { 'try': function (callbackfn) { - var promiseCapability = newPromiseCapability.f(this); - var result = perform(callbackfn); - (result.e ? promiseCapability.reject : promiseCapability.resolve)(result.v); - return promiseCapability.promise; -} }); + `); + process.exit(1); + } // look through all the dependencies of production packages and production + // dependencies of those packages to determine if we're shipping any versions + // of lodash v3 in the distributable -/***/ }), -/* 210 */ -/***/ (function(module, exports, __webpack_require__) { + const prodDependencies = kbn.resolveAllProductionDependencies(yarnLock, _log__WEBPACK_IMPORTED_MODULE_3__["log"]); + const lodash3Versions = new Set(); -__webpack_require__(204); -var global = __webpack_require__(11); -var hide = __webpack_require__(31); -var Iterators = __webpack_require__(35); -var TO_STRING_TAG = __webpack_require__(13)('toStringTag'); + for (const dep of prodDependencies.values()) { + if (dep.name === 'lodash' && dep.version.startsWith('3.')) { + lodash3Versions.add(dep.version); + } + } // if any lodash v3 packages were found we abort and tell the user to fix things -var DOMIterables = ('CSSRuleList,CSSStyleDeclaration,CSSValueList,ClientRectList,DOMRectList,DOMStringList,' + - 'DOMTokenList,DataTransferItemList,FileList,HTMLAllCollection,HTMLCollection,HTMLFormElement,HTMLSelectElement,' + - 'MediaList,MimeTypeArray,NamedNodeMap,NodeList,PaintRequestList,Plugin,PluginArray,SVGLengthList,SVGNumberList,' + - 'SVGPathSegList,SVGPointList,SVGStringList,SVGTransformList,SourceBufferList,StyleSheetList,TextTrackCueList,' + - 'TextTrackList,TouchList').split(','); -for (var i = 0; i < DOMIterables.length; i++) { - var NAME = DOMIterables[i]; - var Collection = global[NAME]; - var proto = Collection && Collection.prototype; - if (proto && !proto[TO_STRING_TAG]) hide(proto, TO_STRING_TAG, NAME); - Iterators[NAME] = Iterators.Array; -} + if (lodash3Versions.size) { + _log__WEBPACK_IMPORTED_MODULE_3__["log"].error(dedent__WEBPACK_IMPORTED_MODULE_1___default.a` + Due to changes in the yarn.lock file and/or package.json files a version of + lodash 3 is now included in the production dependencies. To reduce the size of + our distributable and especially our front-end bundles we have decided to + prevent adding any new instances of lodash 3. -/***/ }), -/* 211 */ -/***/ (function(module, exports, __webpack_require__) { + Please inspect the changes to yarn.lock or package.json files to identify where + the lodash 3 version is coming from and remove it. -/** - * This is the web browser implementation of `debug()`. - * - * Expose `debug()` as the module. - */ + If you have questions about this please reack out to the operations team. -exports = module.exports = __webpack_require__(112); -exports.log = log; -exports.formatArgs = formatArgs; -exports.save = save; -exports.load = load; -exports.useColors = useColors; -exports.storage = 'undefined' != typeof chrome - && 'undefined' != typeof chrome.storage - ? chrome.storage.local - : localstorage(); + `); + process.exit(1); + } // TODO: remove this once we move into a single package.json + // look through all the package.json files to find packages which have mismatched version ranges -/** - * Colors. - */ -exports.colors = [ - '#0000CC', '#0000FF', '#0033CC', '#0033FF', '#0066CC', '#0066FF', '#0099CC', - '#0099FF', '#00CC00', '#00CC33', '#00CC66', '#00CC99', '#00CCCC', '#00CCFF', - '#3300CC', '#3300FF', '#3333CC', '#3333FF', '#3366CC', '#3366FF', '#3399CC', - '#3399FF', '#33CC00', '#33CC33', '#33CC66', '#33CC99', '#33CCCC', '#33CCFF', - '#6600CC', '#6600FF', '#6633CC', '#6633FF', '#66CC00', '#66CC33', '#9900CC', - '#9900FF', '#9933CC', '#9933FF', '#99CC00', '#99CC33', '#CC0000', '#CC0033', - '#CC0066', '#CC0099', '#CC00CC', '#CC00FF', '#CC3300', '#CC3333', '#CC3366', - '#CC3399', '#CC33CC', '#CC33FF', '#CC6600', '#CC6633', '#CC9900', '#CC9933', - '#CCCC00', '#CCCC33', '#FF0000', '#FF0033', '#FF0066', '#FF0099', '#FF00CC', - '#FF00FF', '#FF3300', '#FF3333', '#FF3366', '#FF3399', '#FF33CC', '#FF33FF', - '#FF6600', '#FF6633', '#FF9900', '#FF9933', '#FFCC00', '#FFCC33' -]; + const depRanges = new Map(); -/** - * Currently only WebKit-based Web Inspectors, Firefox >= v31, - * and the Firebug extension (any Firefox version) are known - * to support "%c" CSS customizations. - * - * TODO: add a `localStorage` variable to explicitly enable/disable colors - */ + for (const project of kbn.getAllProjects().values()) { + for (const [dep, range] of Object.entries(project.allDependencies)) { + const existingDep = depRanges.get(dep); -function useColors() { - // NB: In an Electron preload script, document will be defined but not fully - // initialized. Since we know we're in Chrome, we'll just detect this case - // explicitly - if (typeof window !== 'undefined' && window.process && window.process.type === 'renderer') { - return true; - } + if (!existingDep) { + depRanges.set(dep, [{ + range, + projects: [project] + }]); + continue; + } - // Internet Explorer and Edge do not support colors. - if (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/(edge|trident)\/(\d+)/)) { - return false; + const existingRange = existingDep.find(existing => existing.range === range); + + if (!existingRange) { + existingDep.push({ + range, + projects: [project] + }); + continue; + } + + existingRange.projects.push(project); + } } - // is webkit? http://stackoverflow.com/a/16459606/376773 - // document is undefined in react-native: https://github.com/facebook/react-native/pull/1632 - return (typeof document !== 'undefined' && document.documentElement && document.documentElement.style && document.documentElement.style.WebkitAppearance) || - // is firebug? http://stackoverflow.com/a/398120/376773 - (typeof window !== 'undefined' && window.console && (window.console.firebug || (window.console.exception && window.console.table))) || - // is firefox >= v31? - // https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages - (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/) && parseInt(RegExp.$1, 10) >= 31) || - // double check webkit in userAgent just in case we are in a worker - (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/applewebkit\/(\d+)/)); -} + const duplicateRanges = Array.from(depRanges.entries()).filter(([, ranges]) => ranges.length > 1).reduce((acc, [dep, ranges]) => [...acc, dep, ...ranges.map(({ + range, + projects + }) => ` ${range} => ${projects.map(p => p.name).join(', ')}`)], []).join('\n '); -/** - * Map %j to `JSON.stringify()`, since no Web Inspectors do that by default. - */ + if (duplicateRanges) { + _log__WEBPACK_IMPORTED_MODULE_3__["log"].error(dedent__WEBPACK_IMPORTED_MODULE_1___default.a` -exports.formatters.j = function(v) { - try { - return JSON.stringify(v); - } catch (err) { - return '[UnexpectedJSONParseError]: ' + err.message; + [single_version_dependencies] Multiple version ranges for the same dependency + were found declared across different package.json files. Please consolidate + those to match across all package.json files. Different versions for the + same dependency is not supported. + + If you have questions about this please reach out to the operations team. + + The conflicting dependencies are: + + ${duplicateRanges} + `); + process.exit(1); } -}; + _log__WEBPACK_IMPORTED_MODULE_3__["log"].success('yarn.lock analysis completed without any issues'); +} + +/***/ }), +/* 280 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { -/** - * Colorize log arguments if enabled. +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CleanCommand", function() { return CleanCommand; }); +/* harmony import */ var del__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(281); +/* harmony import */ var del__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(del__WEBPACK_IMPORTED_MODULE_0__); +/* harmony import */ var ora__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(367); +/* harmony import */ var ora__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(ora__WEBPACK_IMPORTED_MODULE_1__); +/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(4); +/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_2__); +/* harmony import */ var _utils_fs__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(131); +/* harmony import */ var _utils_log__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(144); +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * @api public + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. */ -function formatArgs(args) { - var useColors = this.useColors; - args[0] = (useColors ? '%c' : '') - + this.namespace - + (useColors ? ' %c' : ' ') - + args[0] - + (useColors ? '%c ' : ' ') - + '+' + exports.humanize(this.diff); - if (!useColors) return; - var c = 'color: ' + this.color; - args.splice(1, 0, c, 'color: inherit') - // the final "%c" is somewhat tricky, because there could be other - // arguments passed either before or after the %c, so we need to - // figure out the correct index to insert the CSS into - var index = 0; - var lastC = 0; - args[0].replace(/%[a-zA-Z%]/g, function(match) { - if ('%%' === match) return; - index++; - if ('%c' === match) { - // we only are interested in the *last* %c - // (the user may have provided their own) - lastC = index; - } - }); +const CleanCommand = { + description: 'Remove the node_modules and target directories from all projects.', + name: 'clean', - args.splice(lastC, 0, c); -} + async run(projects) { + const toDelete = []; -/** - * Invokes `console.log()` when available. - * No-op when `console.log` is not a "function". - * - * @api public - */ + for (const project of projects.values()) { + if (await Object(_utils_fs__WEBPACK_IMPORTED_MODULE_3__["isDirectory"])(project.nodeModulesLocation)) { + toDelete.push({ + cwd: project.path, + pattern: Object(path__WEBPACK_IMPORTED_MODULE_2__["relative"])(project.path, project.nodeModulesLocation) + }); + } -function log() { - // this hackery is required for IE8/9, where - // the `console.log` function doesn't have 'apply' - return 'object' === typeof console - && console.log - && Function.prototype.apply.call(console.log, console, arguments); -} + if (await Object(_utils_fs__WEBPACK_IMPORTED_MODULE_3__["isDirectory"])(project.targetLocation)) { + toDelete.push({ + cwd: project.path, + pattern: Object(path__WEBPACK_IMPORTED_MODULE_2__["relative"])(project.path, project.targetLocation) + }); + } -/** - * Save `namespaces`. - * - * @param {String} namespaces - * @api private - */ + const { + extraPatterns + } = project.getCleanConfig(); -function save(namespaces) { - try { - if (null == namespaces) { - exports.storage.removeItem('debug'); - } else { - exports.storage.debug = namespaces; + if (extraPatterns) { + toDelete.push({ + cwd: project.path, + pattern: extraPatterns + }); + } } - } catch(e) {} -} -/** - * Load `namespaces`. - * - * @return {String} returns the previously persisted debug modes - * @api private - */ + if (toDelete.length === 0) { + _utils_log__WEBPACK_IMPORTED_MODULE_4__["log"].success('Nothing to delete'); + } else { + /** + * In order to avoid patterns like `/build` in packages from accidentally + * impacting files outside the package we use `process.chdir()` to change + * the cwd to the package and execute `del()` without the `force` option + * so it will check that each file being deleted is within the package. + * + * `del()` does support a `cwd` option, but it's only for resolving the + * patterns and does not impact the cwd check. + */ + const originalCwd = process.cwd(); -function load() { - var r; - try { - r = exports.storage.debug; - } catch(e) {} + try { + for (const { + pattern, + cwd + } of toDelete) { + process.chdir(cwd); + const promise = del__WEBPACK_IMPORTED_MODULE_0___default()(pattern); - // If debug isn't set in LS, and we're in Electron, try to load $DEBUG - if (!r && typeof process !== 'undefined' && 'env' in process) { - r = process.env.DEBUG; + if (_utils_log__WEBPACK_IMPORTED_MODULE_4__["log"].wouldLogLevel('info')) { + ora__WEBPACK_IMPORTED_MODULE_1___default.a.promise(promise, Object(path__WEBPACK_IMPORTED_MODULE_2__["relative"])(originalCwd, Object(path__WEBPACK_IMPORTED_MODULE_2__["join"])(cwd, String(pattern)))); + } + + await promise; + } + } finally { + process.chdir(originalCwd); + } + } } - return r; -} +}; -/** - * Enable namespaces listed in `localStorage.debug` initially. - */ +/***/ }), +/* 281 */ +/***/ (function(module, exports, __webpack_require__) { -exports.enable(load()); +"use strict"; -/** - * Localstorage attempts to return the localstorage. - * - * This is necessary because safari throws - * when a user disables cookies/localstorage - * and you attempt to access it. - * - * @return {LocalStorage} - * @api private - */ +const {promisify} = __webpack_require__(112); +const path = __webpack_require__(4); +const globby = __webpack_require__(282); +const isGlob = __webpack_require__(294); +const slash = __webpack_require__(358); +const gracefulFs = __webpack_require__(133); +const isPathCwd = __webpack_require__(360); +const isPathInside = __webpack_require__(361); +const rimraf = __webpack_require__(362); +const pMap = __webpack_require__(363); -function localstorage() { - try { - return window.localStorage; - } catch (e) {} +const rimrafP = promisify(rimraf); + +const rimrafOptions = { + glob: false, + unlink: gracefulFs.unlink, + unlinkSync: gracefulFs.unlinkSync, + chmod: gracefulFs.chmod, + chmodSync: gracefulFs.chmodSync, + stat: gracefulFs.stat, + statSync: gracefulFs.statSync, + lstat: gracefulFs.lstat, + lstatSync: gracefulFs.lstatSync, + rmdir: gracefulFs.rmdir, + rmdirSync: gracefulFs.rmdirSync, + readdir: gracefulFs.readdir, + readdirSync: gracefulFs.readdirSync +}; + +function safeCheck(file, cwd) { + if (isPathCwd(file)) { + throw new Error('Cannot delete the current working directory. Can be overridden with the `force` option.'); + } + + if (!isPathInside(file, cwd)) { + throw new Error('Cannot delete files/directories outside the current working directory. Can be overridden with the `force` option.'); + } } +function normalizePatterns(patterns) { + patterns = Array.isArray(patterns) ? patterns : [patterns]; -/***/ }), -/* 212 */ -/***/ (function(module, exports, __webpack_require__) { + patterns = patterns.map(pattern => { + if (process.platform === 'win32' && isGlob(pattern) === false) { + return slash(pattern); + } -/** - * Detect Electron renderer process, which is node, but we should - * treat as a browser. - */ + return pattern; + }); -if (typeof process === 'undefined' || process.type === 'renderer') { - module.exports = __webpack_require__(211); -} else { - module.exports = __webpack_require__(213); + return patterns; } +module.exports = async (patterns, {force, dryRun, cwd = process.cwd(), ...options} = {}) => { + options = { + expandDirectories: false, + onlyFiles: false, + followSymbolicLinks: false, + cwd, + ...options + }; -/***/ }), -/* 213 */ -/***/ (function(module, exports, __webpack_require__) { + patterns = normalizePatterns(patterns); -/** - * Module dependencies. - */ + const files = (await globby(patterns, options)) + .sort((a, b) => b.localeCompare(a)); -var tty = __webpack_require__(79); -var util = __webpack_require__(2); + const mapper = async file => { + file = path.resolve(cwd, file); -/** - * This is the Node.js implementation of `debug()`. - * - * Expose `debug()` as the module. - */ + if (!force) { + safeCheck(file, cwd); + } -exports = module.exports = __webpack_require__(112); -exports.init = init; -exports.log = log; -exports.formatArgs = formatArgs; -exports.save = save; -exports.load = load; -exports.useColors = useColors; + if (!dryRun) { + await rimrafP(file, rimrafOptions); + } -/** - * Colors. - */ + return file; + }; -exports.colors = [ 6, 2, 3, 4, 5, 1 ]; + const removedFiles = await pMap(files, mapper, options); -try { - var supportsColor = __webpack_require__(239); - if (supportsColor && supportsColor.level >= 2) { - exports.colors = [ - 20, 21, 26, 27, 32, 33, 38, 39, 40, 41, 42, 43, 44, 45, 56, 57, 62, 63, 68, - 69, 74, 75, 76, 77, 78, 79, 80, 81, 92, 93, 98, 99, 112, 113, 128, 129, 134, - 135, 148, 149, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, - 172, 173, 178, 179, 184, 185, 196, 197, 198, 199, 200, 201, 202, 203, 204, - 205, 206, 207, 208, 209, 214, 215, 220, 221 - ]; - } -} catch (err) { - // swallow - we only care if `supports-color` is available; it doesn't have to be. -} + removedFiles.sort((a, b) => a.localeCompare(b)); -/** - * Build up the default `inspectOpts` object from the environment variables. - * - * $ DEBUG_COLORS=no DEBUG_DEPTH=10 DEBUG_SHOW_HIDDEN=enabled node script.js - */ + return removedFiles; +}; -exports.inspectOpts = Object.keys(process.env).filter(function (key) { - return /^debug_/i.test(key); -}).reduce(function (obj, key) { - // camel-case - var prop = key - .substring(6) - .toLowerCase() - .replace(/_([a-z])/g, function (_, k) { return k.toUpperCase() }); +module.exports.sync = (patterns, {force, dryRun, cwd = process.cwd(), ...options} = {}) => { + options = { + expandDirectories: false, + onlyFiles: false, + followSymbolicLinks: false, + cwd, + ...options + }; - // coerce string value into JS value - var val = process.env[key]; - if (/^(yes|on|true|enabled)$/i.test(val)) val = true; - else if (/^(no|off|false|disabled)$/i.test(val)) val = false; - else if (val === 'null') val = null; - else val = Number(val); + patterns = normalizePatterns(patterns); - obj[prop] = val; - return obj; -}, {}); + const files = globby.sync(patterns, options) + .sort((a, b) => b.localeCompare(a)); -/** - * Is stdout a TTY? Colored output is enabled when `true`. - */ + const removedFiles = files.map(file => { + file = path.resolve(cwd, file); -function useColors() { - return 'colors' in exports.inspectOpts - ? Boolean(exports.inspectOpts.colors) - : tty.isatty(process.stderr.fd); -} + if (!force) { + safeCheck(file, cwd); + } -/** - * Map %o to `util.inspect()`, all on a single line. - */ + if (!dryRun) { + rimraf.sync(file, rimrafOptions); + } -exports.formatters.o = function(v) { - this.inspectOpts.colors = this.useColors; - return util.inspect(v, this.inspectOpts) - .split('\n').map(function(str) { - return str.trim() - }).join(' '); -}; + return file; + }); -/** - * Map %o to `util.inspect()`, allowing multiple lines if needed. - */ + removedFiles.sort((a, b) => a.localeCompare(b)); -exports.formatters.O = function(v) { - this.inspectOpts.colors = this.useColors; - return util.inspect(v, this.inspectOpts); + return removedFiles; }; -/** - * Adds ANSI color escape codes if enabled. - * - * @api public - */ - -function formatArgs(args) { - var name = this.namespace; - var useColors = this.useColors; - if (useColors) { - var c = this.color; - var colorCode = '\u001b[3' + (c < 8 ? c : '8;5;' + c); - var prefix = ' ' + colorCode + ';1m' + name + ' ' + '\u001b[0m'; +/***/ }), +/* 282 */ +/***/ (function(module, exports, __webpack_require__) { - args[0] = prefix + args[0].split('\n').join('\n' + prefix); - args.push(colorCode + 'm+' + exports.humanize(this.diff) + '\u001b[0m'); - } else { - args[0] = getDate() + name + ' ' + args[0]; - } -} +"use strict"; -function getDate() { - if (exports.inspectOpts.hideDate) { - return ''; - } else { - return new Date().toISOString() + ' '; - } -} +const fs = __webpack_require__(134); +const arrayUnion = __webpack_require__(283); +const merge2 = __webpack_require__(284); +const glob = __webpack_require__(147); +const fastGlob = __webpack_require__(285); +const dirGlob = __webpack_require__(354); +const gitignore = __webpack_require__(356); +const {FilterStream, UniqueStream} = __webpack_require__(359); -/** - * Invokes `util.format()` with the specified arguments and writes to stderr. - */ +const DEFAULT_FILTER = () => false; -function log() { - return process.stderr.write(util.format.apply(util, arguments) + '\n'); -} +const isNegative = pattern => pattern[0] === '!'; -/** - * Save `namespaces`. - * - * @param {String} namespaces - * @api private - */ +const assertPatternsInput = patterns => { + if (!patterns.every(pattern => typeof pattern === 'string')) { + throw new TypeError('Patterns must be a string or an array of strings'); + } +}; -function save(namespaces) { - if (null == namespaces) { - // If you set a process.env field to null or undefined, it gets cast to the - // string 'null' or 'undefined'. Just delete instead. - delete process.env.DEBUG; - } else { - process.env.DEBUG = namespaces; - } -} +const checkCwdOption = (options = {}) => { + if (!options.cwd) { + return; + } -/** - * Load `namespaces`. - * - * @return {String} returns the previously persisted debug modes - * @api private - */ + let stat; + try { + stat = fs.statSync(options.cwd); + } catch (_) { + return; + } -function load() { - return process.env.DEBUG; -} + if (!stat.isDirectory()) { + throw new Error('The `cwd` option must be a path to a directory'); + } +}; -/** - * Init logic for `debug` instances. - * - * Create a new `inspectOpts` object in case `useColors` is set - * differently for a particular `debug` instance. - */ +const getPathString = p => p.stats instanceof fs.Stats ? p.path : p; -function init (debug) { - debug.inspectOpts = {}; +const generateGlobTasks = (patterns, taskOptions) => { + patterns = arrayUnion([].concat(patterns)); + assertPatternsInput(patterns); + checkCwdOption(taskOptions); - var keys = Object.keys(exports.inspectOpts); - for (var i = 0; i < keys.length; i++) { - debug.inspectOpts[keys[i]] = exports.inspectOpts[keys[i]]; - } -} + const globTasks = []; -/** - * Enable namespaces listed in `process.env.DEBUG` initially. - */ + taskOptions = { + ignore: [], + expandDirectories: true, + ...taskOptions + }; -exports.enable(load()); + for (const [index, pattern] of patterns.entries()) { + if (isNegative(pattern)) { + continue; + } + const ignore = patterns + .slice(index) + .filter(isNegative) + .map(pattern => pattern.slice(1)); -/***/ }), -/* 214 */, -/* 215 */, -/* 216 */, -/* 217 */ -/***/ (function(module, exports, __webpack_require__) { + const options = { + ...taskOptions, + ignore: taskOptions.ignore.concat(ignore) + }; -// Copyright Joyent, Inc. and other Node contributors. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to permit -// persons to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -// USE OR OTHER DEALINGS IN THE SOFTWARE. + globTasks.push({pattern, options}); + } -var pathModule = __webpack_require__(0); -var isWindows = process.platform === 'win32'; -var fs = __webpack_require__(3); + return globTasks; +}; -// JavaScript implementation of realpath, ported from node pre-v6 +const globDirs = (task, fn) => { + let options = {}; + if (task.options.cwd) { + options.cwd = task.options.cwd; + } -var DEBUG = process.env.NODE_DEBUG && /fs/.test(process.env.NODE_DEBUG); + if (Array.isArray(task.options.expandDirectories)) { + options = { + ...options, + files: task.options.expandDirectories + }; + } else if (typeof task.options.expandDirectories === 'object') { + options = { + ...options, + ...task.options.expandDirectories + }; + } -function rethrow() { - // Only enable in debug mode. A backtrace uses ~1000 bytes of heap space and - // is fairly slow to generate. - var callback; - if (DEBUG) { - var backtrace = new Error; - callback = debugCallback; - } else - callback = missingCallback; + return fn(task.pattern, options); +}; - return callback; +const getPattern = (task, fn) => task.options.expandDirectories ? globDirs(task, fn) : [task.pattern]; - function debugCallback(err) { - if (err) { - backtrace.message = err.message; - err = backtrace; - missingCallback(err); - } - } +const getFilterSync = options => { + return options && options.gitignore ? + gitignore.sync({cwd: options.cwd, ignore: options.ignore}) : + DEFAULT_FILTER; +}; - function missingCallback(err) { - if (err) { - if (process.throwDeprecation) - throw err; // Forgot a callback but don't know where? Use NODE_DEBUG=fs - else if (!process.noDeprecation) { - var msg = 'fs: missing callback ' + (err.stack || err.message); - if (process.traceDeprecation) - console.trace(msg); - else - console.error(msg); - } - } - } -} +const globToTask = task => glob => { + const {options} = task; + if (options.ignore && Array.isArray(options.ignore) && options.expandDirectories) { + options.ignore = dirGlob.sync(options.ignore); + } -function maybeCallback(cb) { - return typeof cb === 'function' ? cb : rethrow(); -} + return { + pattern: glob, + options + }; +}; -var normalize = pathModule.normalize; +module.exports = async (patterns, options) => { + const globTasks = generateGlobTasks(patterns, options); -// Regexp that finds the next partion of a (partial) path -// result is [base_with_slash, base], e.g. ['somedir/', 'somedir'] -if (isWindows) { - var nextPartRe = /(.*?)(?:[\/\\]+|$)/g; -} else { - var nextPartRe = /(.*?)(?:[\/]+|$)/g; -} + const getFilter = async () => { + return options && options.gitignore ? + gitignore({cwd: options.cwd, ignore: options.ignore}) : + DEFAULT_FILTER; + }; -// Regex to find the device root, including trailing slash. E.g. 'c:\\'. -if (isWindows) { - var splitRootRe = /^(?:[a-zA-Z]:|[\\\/]{2}[^\\\/]+[\\\/][^\\\/]+)?[\\\/]*/; -} else { - var splitRootRe = /^[\/]*/; -} + const getTasks = async () => { + const tasks = await Promise.all(globTasks.map(async task => { + const globs = await getPattern(task, dirGlob); + return Promise.all(globs.map(globToTask(task))); + })); -exports.realpathSync = function realpathSync(p, cache) { - // make p is absolute - p = pathModule.resolve(p); + return arrayUnion(...tasks); + }; - if (cache && Object.prototype.hasOwnProperty.call(cache, p)) { - return cache[p]; - } + const [filter, tasks] = await Promise.all([getFilter(), getTasks()]); + const paths = await Promise.all(tasks.map(task => fastGlob(task.pattern, task.options))); - var original = p, - seenLinks = {}, - knownHard = {}; + return arrayUnion(...paths).filter(path_ => !filter(getPathString(path_))); +}; - // current character position in p - var pos; - // the partial path so far, including a trailing slash if any - var current; - // the partial path without a trailing slash (except when pointing at a root) - var base; - // the partial path scanned in the previous round, with slash - var previous; +module.exports.sync = (patterns, options) => { + const globTasks = generateGlobTasks(patterns, options); - start(); + const tasks = globTasks.reduce((tasks, task) => { + const newTask = getPattern(task, dirGlob.sync).map(globToTask(task)); + return tasks.concat(newTask); + }, []); - function start() { - // Skip over roots - var m = splitRootRe.exec(p); - pos = m[0].length; - current = m[0]; - base = m[0]; - previous = ''; + const filter = getFilterSync(options); - // On windows, check that the root exists. On unix there is no need. - if (isWindows && !knownHard[base]) { - fs.lstatSync(base); - knownHard[base] = true; - } - } + return tasks.reduce( + (matches, task) => arrayUnion(matches, fastGlob.sync(task.pattern, task.options)), + [] + ).filter(path_ => !filter(path_)); +}; - // walk down the path, swapping out linked pathparts for their real - // values - // NB: p.length changes. - while (pos < p.length) { - // find the next part - nextPartRe.lastIndex = pos; - var result = nextPartRe.exec(p); - previous = current; - current += result[0]; - base = previous + result[1]; - pos = nextPartRe.lastIndex; +module.exports.stream = (patterns, options) => { + const globTasks = generateGlobTasks(patterns, options); - // continue if not a symlink - if (knownHard[base] || (cache && cache[base] === base)) { - continue; - } + const tasks = globTasks.reduce((tasks, task) => { + const newTask = getPattern(task, dirGlob.sync).map(globToTask(task)); + return tasks.concat(newTask); + }, []); - var resolvedLink; - if (cache && Object.prototype.hasOwnProperty.call(cache, base)) { - // some known symbolic link. no need to stat again. - resolvedLink = cache[base]; - } else { - var stat = fs.lstatSync(base); - if (!stat.isSymbolicLink()) { - knownHard[base] = true; - if (cache) cache[base] = base; - continue; - } + const filter = getFilterSync(options); + const filterStream = new FilterStream(p => !filter(p)); + const uniqueStream = new UniqueStream(); - // read the link if it wasn't read before - // dev/ino always return 0 on windows, so skip the check. - var linkTarget = null; - if (!isWindows) { - var id = stat.dev.toString(32) + ':' + stat.ino.toString(32); - if (seenLinks.hasOwnProperty(id)) { - linkTarget = seenLinks[id]; - } - } - if (linkTarget === null) { - fs.statSync(base); - linkTarget = fs.readlinkSync(base); - } - resolvedLink = pathModule.resolve(previous, linkTarget); - // track this, if given a cache. - if (cache) cache[base] = resolvedLink; - if (!isWindows) seenLinks[id] = linkTarget; - } + return merge2(tasks.map(task => fastGlob.stream(task.pattern, task.options))) + .pipe(filterStream) + .pipe(uniqueStream); +}; - // resolve the link, then start over - p = pathModule.resolve(resolvedLink, p.slice(pos)); - start(); - } +module.exports.generateGlobTasks = generateGlobTasks; - if (cache) cache[original] = p; +module.exports.hasMagic = (patterns, options) => [] + .concat(patterns) + .some(pattern => glob.hasMagic(pattern, options)); - return p; +module.exports.gitignore = gitignore; + + +/***/ }), +/* 283 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +module.exports = (...arguments_) => { + return [...new Set([].concat(...arguments_))]; }; -exports.realpath = function realpath(p, cache, cb) { - if (typeof cb !== 'function') { - cb = maybeCallback(cache); - cache = null; - } +/***/ }), +/* 284 */ +/***/ (function(module, exports, __webpack_require__) { - // make p is absolute - p = pathModule.resolve(p); +"use strict"; - if (cache && Object.prototype.hasOwnProperty.call(cache, p)) { - return process.nextTick(cb.bind(null, null, cache[p])); - } +/* + * merge2 + * https://github.com/teambition/merge2 + * + * Copyright (c) 2014-2020 Teambition + * Licensed under the MIT license. + */ +const Stream = __webpack_require__(138) +const PassThrough = Stream.PassThrough +const slice = Array.prototype.slice - var original = p, - seenLinks = {}, - knownHard = {}; +module.exports = merge2 - // current character position in p - var pos; - // the partial path so far, including a trailing slash if any - var current; - // the partial path without a trailing slash (except when pointing at a root) - var base; - // the partial path scanned in the previous round, with slash - var previous; +function merge2 () { + const streamsQueue = [] + const args = slice.call(arguments) + let merging = false + let options = args[args.length - 1] - start(); + if (options && !Array.isArray(options) && options.pipe == null) { + args.pop() + } else { + options = {} + } - function start() { - // Skip over roots - var m = splitRootRe.exec(p); - pos = m[0].length; - current = m[0]; - base = m[0]; - previous = ''; + const doEnd = options.end !== false + const doPipeError = options.pipeError === true + if (options.objectMode == null) { + options.objectMode = true + } + if (options.highWaterMark == null) { + options.highWaterMark = 64 * 1024 + } + const mergedStream = PassThrough(options) - // On windows, check that the root exists. On unix there is no need. - if (isWindows && !knownHard[base]) { - fs.lstat(base, function(err) { - if (err) return cb(err); - knownHard[base] = true; - LOOP(); - }); - } else { - process.nextTick(LOOP); + function addStream () { + for (let i = 0, len = arguments.length; i < len; i++) { + streamsQueue.push(pauseStreams(arguments[i], options)) } + mergeStream() + return this } - // walk down the path, swapping out linked pathparts for their real - // values - function LOOP() { - // stop if scanned past end of path - if (pos >= p.length) { - if (cache) cache[original] = p; - return cb(null, p); + function mergeStream () { + if (merging) { + return } + merging = true - // find the next part - nextPartRe.lastIndex = pos; - var result = nextPartRe.exec(p); - previous = current; - current += result[0]; - base = previous + result[1]; - pos = nextPartRe.lastIndex; - - // continue if not a symlink - if (knownHard[base] || (cache && cache[base] === base)) { - return process.nextTick(LOOP); + let streams = streamsQueue.shift() + if (!streams) { + process.nextTick(endStream) + return + } + if (!Array.isArray(streams)) { + streams = [streams] } - if (cache && Object.prototype.hasOwnProperty.call(cache, base)) { - // known symbolic link. no need to stat again. - return gotResolvedLink(cache[base]); + let pipesCount = streams.length + 1 + + function next () { + if (--pipesCount > 0) { + return + } + merging = false + mergeStream() } - return fs.lstat(base, gotStat); - } + function pipe (stream) { + function onend () { + stream.removeListener('merge2UnpipeEnd', onend) + stream.removeListener('end', onend) + if (doPipeError) { + stream.removeListener('error', onerror) + } + next() + } + function onerror (err) { + mergedStream.emit('error', err) + } + // skip ended stream + if (stream._readableState.endEmitted) { + return next() + } - function gotStat(err, stat) { - if (err) return cb(err); + stream.on('merge2UnpipeEnd', onend) + stream.on('end', onend) - // if not a symlink, skip to the next path part - if (!stat.isSymbolicLink()) { - knownHard[base] = true; - if (cache) cache[base] = base; - return process.nextTick(LOOP); + if (doPipeError) { + stream.on('error', onerror) + } + + stream.pipe(mergedStream, { end: false }) + // compatible for old stream + stream.resume() } - // stat & read the link if not read before - // call gotTarget as soon as the link target is known - // dev/ino always return 0 on windows, so skip the check. - if (!isWindows) { - var id = stat.dev.toString(32) + ':' + stat.ino.toString(32); - if (seenLinks.hasOwnProperty(id)) { - return gotTarget(null, seenLinks[id], base); - } + for (let i = 0; i < streams.length; i++) { + pipe(streams[i]) } - fs.stat(base, function(err) { - if (err) return cb(err); - fs.readlink(base, function(err, target) { - if (!isWindows) seenLinks[id] = target; - gotTarget(err, target); - }); - }); + next() } - function gotTarget(err, target, base) { - if (err) return cb(err); - - var resolvedLink = pathModule.resolve(previous, target); - if (cache) cache[base] = resolvedLink; - gotResolvedLink(resolvedLink); - } - - function gotResolvedLink(resolvedLink) { - // resolve the link, then start over - p = pathModule.resolve(resolvedLink, p.slice(pos)); - start(); + function endStream () { + merging = false + // emit 'queueDrain' when all streams merged. + mergedStream.emit('queueDrain') + if (doEnd) { + mergedStream.end() + } } -}; - - -/***/ }), -/* 218 */ -/***/ (function(module, exports, __webpack_require__) { - -module.exports = globSync -globSync.GlobSync = GlobSync - -var fs = __webpack_require__(3) -var rp = __webpack_require__(114) -var minimatch = __webpack_require__(60) -var Minimatch = minimatch.Minimatch -var Glob = __webpack_require__(75).Glob -var util = __webpack_require__(2) -var path = __webpack_require__(0) -var assert = __webpack_require__(22) -var isAbsolute = __webpack_require__(76) -var common = __webpack_require__(115) -var alphasort = common.alphasort -var alphasorti = common.alphasorti -var setopts = common.setopts -var ownProp = common.ownProp -var childrenIgnored = common.childrenIgnored -var isIgnored = common.isIgnored - -function globSync (pattern, options) { - if (typeof options === 'function' || arguments.length === 3) - throw new TypeError('callback provided to sync glob\n'+ - 'See: https://github.com/isaacs/node-glob/issues/167') - - return new GlobSync(pattern, options).found -} - -function GlobSync (pattern, options) { - if (!pattern) - throw new Error('must provide pattern') - - if (typeof options === 'function' || arguments.length === 3) - throw new TypeError('callback provided to sync glob\n'+ - 'See: https://github.com/isaacs/node-glob/issues/167') - - if (!(this instanceof GlobSync)) - return new GlobSync(pattern, options) - - setopts(this, pattern, options) - - if (this.noprocess) - return this - var n = this.minimatch.set.length - this.matches = new Array(n) - for (var i = 0; i < n; i ++) { - this._process(this.minimatch.set[i], i, false) - } - this._finish() -} + mergedStream.setMaxListeners(0) + mergedStream.add = addStream + mergedStream.on('unpipe', function (stream) { + stream.emit('merge2UnpipeEnd') + }) -GlobSync.prototype._finish = function () { - assert(this instanceof GlobSync) - if (this.realpath) { - var self = this - this.matches.forEach(function (matchset, index) { - var set = self.matches[index] = Object.create(null) - for (var p in matchset) { - try { - p = self._makeAbs(p) - var real = rp.realpathSync(p, self.realpathCache) - set[real] = true - } catch (er) { - if (er.syscall === 'stat') - set[self._makeAbs(p)] = true - else - throw er - } - } - }) + if (args.length) { + addStream.apply(null, args) } - common.finish(this) + return mergedStream } - -GlobSync.prototype._process = function (pattern, index, inGlobStar) { - assert(this instanceof GlobSync) - - // Get the first [n] parts of pattern that are all strings. - var n = 0 - while (typeof pattern[n] === 'string') { - n ++ - } - // now n is the index of the first one that is *not* a string. - - // See if there's anything else - var prefix - switch (n) { - // if not, then this is rather simple - case pattern.length: - this._processSimple(pattern.join('/'), index) - return - - case 0: - // pattern *starts* with some non-trivial item. - // going to readdir(cwd), but not include the prefix in matches. - prefix = null - break - - default: - // pattern has some string bits in the front. - // whatever it starts with, whether that's 'absolute' like /foo/bar, - // or 'relative' like '../baz' - prefix = pattern.slice(0, n).join('/') - break +// check and pause streams for pipe. +function pauseStreams (streams, options) { + if (!Array.isArray(streams)) { + // Backwards-compat with old-style streams + if (!streams._readableState && streams.pipe) { + streams = streams.pipe(PassThrough(options)) + } + if (!streams._readableState || !streams.pause || !streams.pipe) { + throw new Error('Only readable stream can be merged.') + } + streams.pause() + } else { + for (let i = 0, len = streams.length; i < len; i++) { + streams[i] = pauseStreams(streams[i], options) + } } - - var remain = pattern.slice(n) - - // get the list of entries. - var read - if (prefix === null) - read = '.' - else if (isAbsolute(prefix) || isAbsolute(pattern.join('/'))) { - if (!prefix || !isAbsolute(prefix)) - prefix = '/' + prefix - read = prefix - } else - read = prefix - - var abs = this._makeAbs(read) - - //if ignored, skip processing - if (childrenIgnored(this, read)) - return - - var isGlobStar = remain[0] === minimatch.GLOBSTAR - if (isGlobStar) - this._processGlobStar(prefix, read, abs, remain, index, inGlobStar) - else - this._processReaddir(prefix, read, abs, remain, index, inGlobStar) + return streams } -GlobSync.prototype._processReaddir = function (prefix, read, abs, remain, index, inGlobStar) { - var entries = this._readdir(abs, inGlobStar) +/***/ }), +/* 285 */ +/***/ (function(module, exports, __webpack_require__) { - // if the abs isn't a dir, then nothing can match! - if (!entries) - return +"use strict"; + +const taskManager = __webpack_require__(286); +const async_1 = __webpack_require__(315); +const stream_1 = __webpack_require__(350); +const sync_1 = __webpack_require__(351); +const settings_1 = __webpack_require__(353); +const utils = __webpack_require__(287); +async function FastGlob(source, options) { + assertPatternsInput(source); + const works = getWorks(source, async_1.default, options); + const result = await Promise.all(works); + return utils.array.flatten(result); +} +// https://github.com/typescript-eslint/typescript-eslint/issues/60 +// eslint-disable-next-line no-redeclare +(function (FastGlob) { + function sync(source, options) { + assertPatternsInput(source); + const works = getWorks(source, sync_1.default, options); + return utils.array.flatten(works); + } + FastGlob.sync = sync; + function stream(source, options) { + assertPatternsInput(source); + const works = getWorks(source, stream_1.default, options); + /** + * The stream returned by the provider cannot work with an asynchronous iterator. + * To support asynchronous iterators, regardless of the number of tasks, we always multiplex streams. + * This affects performance (+25%). I don't see best solution right now. + */ + return utils.stream.merge(works); + } + FastGlob.stream = stream; + function generateTasks(source, options) { + assertPatternsInput(source); + const patterns = [].concat(source); + const settings = new settings_1.default(options); + return taskManager.generate(patterns, settings); + } + FastGlob.generateTasks = generateTasks; + function isDynamicPattern(source, options) { + assertPatternsInput(source); + const settings = new settings_1.default(options); + return utils.pattern.isDynamicPattern(source, settings); + } + FastGlob.isDynamicPattern = isDynamicPattern; + function escapePath(source) { + assertPatternsInput(source); + return utils.path.escape(source); + } + FastGlob.escapePath = escapePath; +})(FastGlob || (FastGlob = {})); +function getWorks(source, _Provider, options) { + const patterns = [].concat(source); + const settings = new settings_1.default(options); + const tasks = taskManager.generate(patterns, settings); + const provider = new _Provider(settings); + return tasks.map(provider.read, provider); +} +function assertPatternsInput(input) { + const source = [].concat(input); + const isValidSource = source.every((item) => utils.string.isString(item) && !utils.string.isEmpty(item)); + if (!isValidSource) { + throw new TypeError('Patterns must be a string (non empty) or an array of strings'); + } +} +module.exports = FastGlob; - // It will only match dot entries if it starts with a dot, or if - // dot is set. Stuff like @(.foo|.bar) isn't allowed. - var pn = remain[0] - var negate = !!this.minimatch.negate - var rawGlob = pn._glob - var dotOk = this.dot || rawGlob.charAt(0) === '.' - var matchedEntries = [] - for (var i = 0; i < entries.length; i++) { - var e = entries[i] - if (e.charAt(0) !== '.' || dotOk) { - var m - if (negate && !prefix) { - m = !e.match(pn) - } else { - m = e.match(pn) - } - if (m) - matchedEntries.push(e) - } - } +/***/ }), +/* 286 */ +/***/ (function(module, exports, __webpack_require__) { - var len = matchedEntries.length - // If there are no matched entries, then nothing matches. - if (len === 0) - return +"use strict"; + +Object.defineProperty(exports, "__esModule", { value: true }); +const utils = __webpack_require__(287); +function generate(patterns, settings) { + const positivePatterns = getPositivePatterns(patterns); + const negativePatterns = getNegativePatternsAsPositive(patterns, settings.ignore); + const staticPatterns = positivePatterns.filter((pattern) => utils.pattern.isStaticPattern(pattern, settings)); + const dynamicPatterns = positivePatterns.filter((pattern) => utils.pattern.isDynamicPattern(pattern, settings)); + const staticTasks = convertPatternsToTasks(staticPatterns, negativePatterns, /* dynamic */ false); + const dynamicTasks = convertPatternsToTasks(dynamicPatterns, negativePatterns, /* dynamic */ true); + return staticTasks.concat(dynamicTasks); +} +exports.generate = generate; +function convertPatternsToTasks(positive, negative, dynamic) { + const positivePatternsGroup = groupPatternsByBaseDirectory(positive); + // When we have a global group – there is no reason to divide the patterns into independent tasks. + // In this case, the global task covers the rest. + if ('.' in positivePatternsGroup) { + const task = convertPatternGroupToTask('.', positive, negative, dynamic); + return [task]; + } + return convertPatternGroupsToTasks(positivePatternsGroup, negative, dynamic); +} +exports.convertPatternsToTasks = convertPatternsToTasks; +function getPositivePatterns(patterns) { + return utils.pattern.getPositivePatterns(patterns); +} +exports.getPositivePatterns = getPositivePatterns; +function getNegativePatternsAsPositive(patterns, ignore) { + const negative = utils.pattern.getNegativePatterns(patterns).concat(ignore); + const positive = negative.map(utils.pattern.convertToPositivePattern); + return positive; +} +exports.getNegativePatternsAsPositive = getNegativePatternsAsPositive; +function groupPatternsByBaseDirectory(patterns) { + const group = {}; + return patterns.reduce((collection, pattern) => { + const base = utils.pattern.getBaseDirectory(pattern); + if (base in collection) { + collection[base].push(pattern); + } + else { + collection[base] = [pattern]; + } + return collection; + }, group); +} +exports.groupPatternsByBaseDirectory = groupPatternsByBaseDirectory; +function convertPatternGroupsToTasks(positive, negative, dynamic) { + return Object.keys(positive).map((base) => { + return convertPatternGroupToTask(base, positive[base], negative, dynamic); + }); +} +exports.convertPatternGroupsToTasks = convertPatternGroupsToTasks; +function convertPatternGroupToTask(base, positive, negative, dynamic) { + return { + dynamic, + positive, + negative, + base, + patterns: [].concat(positive, negative.map(utils.pattern.convertToNegativePattern)) + }; +} +exports.convertPatternGroupToTask = convertPatternGroupToTask; - // if this is the last remaining pattern bit, then no need for - // an additional stat *unless* the user has specified mark or - // stat explicitly. We know they exist, since readdir returned - // them. - if (remain.length === 1 && !this.mark && !this.stat) { - if (!this.matches[index]) - this.matches[index] = Object.create(null) +/***/ }), +/* 287 */ +/***/ (function(module, exports, __webpack_require__) { - for (var i = 0; i < len; i ++) { - var e = matchedEntries[i] - if (prefix) { - if (prefix.slice(-1) !== '/') - e = prefix + '/' + e - else - e = prefix + e - } +"use strict"; + +Object.defineProperty(exports, "__esModule", { value: true }); +const array = __webpack_require__(288); +exports.array = array; +const errno = __webpack_require__(289); +exports.errno = errno; +const fs = __webpack_require__(290); +exports.fs = fs; +const path = __webpack_require__(291); +exports.path = path; +const pattern = __webpack_require__(292); +exports.pattern = pattern; +const stream = __webpack_require__(313); +exports.stream = stream; +const string = __webpack_require__(314); +exports.string = string; - if (e.charAt(0) === '/' && !this.nomount) { - e = path.join(this.root, e) - } - this._emitMatch(index, e) - } - // This was the last one, and no stats were needed - return - } - // now test all matched entries as stand-ins for that part - // of the pattern. - remain.shift() - for (var i = 0; i < len; i ++) { - var e = matchedEntries[i] - var newPattern - if (prefix) - newPattern = [prefix, e] - else - newPattern = [e] - this._process(newPattern.concat(remain), index, inGlobStar) - } -} +/***/ }), +/* 288 */ +/***/ (function(module, exports, __webpack_require__) { +"use strict"; + +Object.defineProperty(exports, "__esModule", { value: true }); +function flatten(items) { + return items.reduce((collection, item) => [].concat(collection, item), []); +} +exports.flatten = flatten; +function splitWhen(items, predicate) { + const result = [[]]; + let groupIndex = 0; + for (const item of items) { + if (predicate(item)) { + groupIndex++; + result[groupIndex] = []; + } + else { + result[groupIndex].push(item); + } + } + return result; +} +exports.splitWhen = splitWhen; -GlobSync.prototype._emitMatch = function (index, e) { - if (isIgnored(this, e)) - return - var abs = this._makeAbs(e) +/***/ }), +/* 289 */ +/***/ (function(module, exports, __webpack_require__) { - if (this.mark) - e = this._mark(e) +"use strict"; + +Object.defineProperty(exports, "__esModule", { value: true }); +function isEnoentCodeError(error) { + return error.code === 'ENOENT'; +} +exports.isEnoentCodeError = isEnoentCodeError; - if (this.absolute) { - e = abs - } - if (this.matches[index][e]) - return +/***/ }), +/* 290 */ +/***/ (function(module, exports, __webpack_require__) { - if (this.nodir) { - var c = this.cache[abs] - if (c === 'DIR' || Array.isArray(c)) - return - } +"use strict"; + +Object.defineProperty(exports, "__esModule", { value: true }); +class DirentFromStats { + constructor(name, stats) { + this.name = name; + this.isBlockDevice = stats.isBlockDevice.bind(stats); + this.isCharacterDevice = stats.isCharacterDevice.bind(stats); + this.isDirectory = stats.isDirectory.bind(stats); + this.isFIFO = stats.isFIFO.bind(stats); + this.isFile = stats.isFile.bind(stats); + this.isSocket = stats.isSocket.bind(stats); + this.isSymbolicLink = stats.isSymbolicLink.bind(stats); + } +} +function createDirentFromStats(name, stats) { + return new DirentFromStats(name, stats); +} +exports.createDirentFromStats = createDirentFromStats; - this.matches[index][e] = true - if (this.stat) - this._stat(e) -} +/***/ }), +/* 291 */ +/***/ (function(module, exports, __webpack_require__) { +"use strict"; + +Object.defineProperty(exports, "__esModule", { value: true }); +const path = __webpack_require__(4); +const LEADING_DOT_SEGMENT_CHARACTERS_COUNT = 2; // ./ or .\\ +const UNESCAPED_GLOB_SYMBOLS_RE = /(\\?)([()*?[\]{|}]|^!|[!+@](?=\())/g; +/** + * Designed to work only with simple paths: `dir\\file`. + */ +function unixify(filepath) { + return filepath.replace(/\\/g, '/'); +} +exports.unixify = unixify; +function makeAbsolute(cwd, filepath) { + return path.resolve(cwd, filepath); +} +exports.makeAbsolute = makeAbsolute; +function escape(pattern) { + return pattern.replace(UNESCAPED_GLOB_SYMBOLS_RE, '\\$2'); +} +exports.escape = escape; +function removeLeadingDotSegment(entry) { + // We do not use `startsWith` because this is 10x slower than current implementation for some cases. + // eslint-disable-next-line @typescript-eslint/prefer-string-starts-ends-with + if (entry.charAt(0) === '.') { + const secondCharactery = entry.charAt(1); + if (secondCharactery === '/' || secondCharactery === '\\') { + return entry.slice(LEADING_DOT_SEGMENT_CHARACTERS_COUNT); + } + } + return entry; +} +exports.removeLeadingDotSegment = removeLeadingDotSegment; -GlobSync.prototype._readdirInGlobStar = function (abs) { - // follow all symlinked directories forever - // just proceed as if this is a non-globstar situation - if (this.follow) - return this._readdir(abs, false) - var entries - var lstat - var stat - try { - lstat = fs.lstatSync(abs) - } catch (er) { - if (er.code === 'ENOENT') { - // lstat failed, doesn't exist - return null - } - } +/***/ }), +/* 292 */ +/***/ (function(module, exports, __webpack_require__) { - var isSym = lstat && lstat.isSymbolicLink() - this.symlinks[abs] = isSym +"use strict"; + +Object.defineProperty(exports, "__esModule", { value: true }); +const path = __webpack_require__(4); +const globParent = __webpack_require__(293); +const micromatch = __webpack_require__(296); +const picomatch = __webpack_require__(307); +const GLOBSTAR = '**'; +const ESCAPE_SYMBOL = '\\'; +const COMMON_GLOB_SYMBOLS_RE = /[*?]|^!/; +const REGEX_CHARACTER_CLASS_SYMBOLS_RE = /\[.*]/; +const REGEX_GROUP_SYMBOLS_RE = /(?:^|[^!*+?@])\(.*\|.*\)/; +const GLOB_EXTENSION_SYMBOLS_RE = /[!*+?@]\(.*\)/; +const BRACE_EXPANSIONS_SYMBOLS_RE = /{.*(?:,|\.\.).*}/; +function isStaticPattern(pattern, options = {}) { + return !isDynamicPattern(pattern, options); +} +exports.isStaticPattern = isStaticPattern; +function isDynamicPattern(pattern, options = {}) { + /** + * When the `caseSensitiveMatch` option is disabled, all patterns must be marked as dynamic, because we cannot check + * filepath directly (without read directory). + */ + if (options.caseSensitiveMatch === false || pattern.includes(ESCAPE_SYMBOL)) { + return true; + } + if (COMMON_GLOB_SYMBOLS_RE.test(pattern) || REGEX_CHARACTER_CLASS_SYMBOLS_RE.test(pattern) || REGEX_GROUP_SYMBOLS_RE.test(pattern)) { + return true; + } + if (options.extglob !== false && GLOB_EXTENSION_SYMBOLS_RE.test(pattern)) { + return true; + } + if (options.braceExpansion !== false && BRACE_EXPANSIONS_SYMBOLS_RE.test(pattern)) { + return true; + } + return false; +} +exports.isDynamicPattern = isDynamicPattern; +function convertToPositivePattern(pattern) { + return isNegativePattern(pattern) ? pattern.slice(1) : pattern; +} +exports.convertToPositivePattern = convertToPositivePattern; +function convertToNegativePattern(pattern) { + return '!' + pattern; +} +exports.convertToNegativePattern = convertToNegativePattern; +function isNegativePattern(pattern) { + return pattern.startsWith('!') && pattern[1] !== '('; +} +exports.isNegativePattern = isNegativePattern; +function isPositivePattern(pattern) { + return !isNegativePattern(pattern); +} +exports.isPositivePattern = isPositivePattern; +function getNegativePatterns(patterns) { + return patterns.filter(isNegativePattern); +} +exports.getNegativePatterns = getNegativePatterns; +function getPositivePatterns(patterns) { + return patterns.filter(isPositivePattern); +} +exports.getPositivePatterns = getPositivePatterns; +function getBaseDirectory(pattern) { + return globParent(pattern, { flipBackslashes: false }); +} +exports.getBaseDirectory = getBaseDirectory; +function hasGlobStar(pattern) { + return pattern.includes(GLOBSTAR); +} +exports.hasGlobStar = hasGlobStar; +function endsWithSlashGlobStar(pattern) { + return pattern.endsWith('/' + GLOBSTAR); +} +exports.endsWithSlashGlobStar = endsWithSlashGlobStar; +function isAffectDepthOfReadingPattern(pattern) { + const basename = path.basename(pattern); + return endsWithSlashGlobStar(pattern) || isStaticPattern(basename); +} +exports.isAffectDepthOfReadingPattern = isAffectDepthOfReadingPattern; +function expandPatternsWithBraceExpansion(patterns) { + return patterns.reduce((collection, pattern) => { + return collection.concat(expandBraceExpansion(pattern)); + }, []); +} +exports.expandPatternsWithBraceExpansion = expandPatternsWithBraceExpansion; +function expandBraceExpansion(pattern) { + return micromatch.braces(pattern, { + expand: true, + nodupes: true + }); +} +exports.expandBraceExpansion = expandBraceExpansion; +function getPatternParts(pattern, options) { + const info = picomatch.scan(pattern, Object.assign(Object.assign({}, options), { parts: true })); + // See micromatch/picomatch#58 for more details + if (info.parts.length === 0) { + return [pattern]; + } + return info.parts; +} +exports.getPatternParts = getPatternParts; +function makeRe(pattern, options) { + return micromatch.makeRe(pattern, options); +} +exports.makeRe = makeRe; +function convertPatternsToRe(patterns, options) { + return patterns.map((pattern) => makeRe(pattern, options)); +} +exports.convertPatternsToRe = convertPatternsToRe; +function matchAny(entry, patternsRe) { + return patternsRe.some((patternRe) => patternRe.test(entry)); +} +exports.matchAny = matchAny; - // If it's not a symlink or a dir, then it's definitely a regular file. - // don't bother doing a readdir in that case. - if (!isSym && lstat && !lstat.isDirectory()) - this.cache[abs] = 'FILE' - else - entries = this._readdir(abs, false) - return entries -} +/***/ }), +/* 293 */ +/***/ (function(module, exports, __webpack_require__) { -GlobSync.prototype._readdir = function (abs, inGlobStar) { - var entries +"use strict"; - if (inGlobStar && !ownProp(this.symlinks, abs)) - return this._readdirInGlobStar(abs) - if (ownProp(this.cache, abs)) { - var c = this.cache[abs] - if (!c || c === 'FILE') - return null +var isGlob = __webpack_require__(294); +var pathPosixDirname = __webpack_require__(4).posix.dirname; +var isWin32 = __webpack_require__(121).platform() === 'win32'; - if (Array.isArray(c)) - return c - } +var slash = '/'; +var backslash = /\\/g; +var enclosure = /[\{\[].*[\/]*.*[\}\]]$/; +var globby = /(^|[^\\])([\{\[]|\([^\)]+$)/; +var escaped = /\\([\!\*\?\|\[\]\(\)\{\}])/g; - try { - return this._readdirEntries(abs, fs.readdirSync(abs)) - } catch (er) { - this._readdirError(abs, er) - return null - } -} +/** + * @param {string} str + * @param {Object} opts + * @param {boolean} [opts.flipBackslashes=true] + */ +module.exports = function globParent(str, opts) { + var options = Object.assign({ flipBackslashes: true }, opts); -GlobSync.prototype._readdirEntries = function (abs, entries) { - // if we haven't asked to stat everything, then just - // assume that everything in there exists, so we can avoid - // having to stat it a second time. - if (!this.mark && !this.stat) { - for (var i = 0; i < entries.length; i ++) { - var e = entries[i] - if (abs === '/') - e = abs + e - else - e = abs + '/' + e - this.cache[e] = true - } + // flip windows path separators + if (options.flipBackslashes && isWin32 && str.indexOf(slash) < 0) { + str = str.replace(backslash, slash); } - this.cache[abs] = entries - - // mark and cache dir-ness - return entries -} - -GlobSync.prototype._readdirError = function (f, er) { - // handle errors, and cache the information - switch (er.code) { - case 'ENOTSUP': // https://github.com/isaacs/node-glob/issues/205 - case 'ENOTDIR': // totally normal. means it *does* exist. - var abs = this._makeAbs(f) - this.cache[abs] = 'FILE' - if (abs === this.cwdAbs) { - var error = new Error(er.code + ' invalid cwd ' + this.cwd) - error.path = this.cwd - error.code = er.code - throw error - } - break - - case 'ENOENT': // not terribly unusual - case 'ELOOP': - case 'ENAMETOOLONG': - case 'UNKNOWN': - this.cache[this._makeAbs(f)] = false - break - - default: // some unusual error. Treat as failure. - this.cache[this._makeAbs(f)] = false - if (this.strict) - throw er - if (!this.silent) - console.error('glob error', er) - break + // special case for strings ending in enclosure containing path separator + if (enclosure.test(str)) { + str += slash; } -} - -GlobSync.prototype._processGlobStar = function (prefix, read, abs, remain, index, inGlobStar) { - - var entries = this._readdir(abs, inGlobStar) - // no entries means not a dir, so it can never have matches - // foo.txt/** doesn't match foo.txt - if (!entries) - return + // preserves full path in case of trailing path separator + str += 'a'; - // test without the globstar, and with every child both below - // and replacing the globstar. - var remainWithoutGlobStar = remain.slice(1) - var gspref = prefix ? [ prefix ] : [] - var noGlobStar = gspref.concat(remainWithoutGlobStar) + // remove path parts that are globby + do { + str = pathPosixDirname(str); + } while (isGlob(str) || globby.test(str)); - // the noGlobStar pattern exits the inGlobStar state - this._process(noGlobStar, index, false) + // remove escape chars and return result + return str.replace(escaped, '$1'); +}; - var len = entries.length - var isSym = this.symlinks[abs] - // If it's a symlink, and we're in a globstar, then stop - if (isSym && inGlobStar) - return +/***/ }), +/* 294 */ +/***/ (function(module, exports, __webpack_require__) { - for (var i = 0; i < len; i++) { - var e = entries[i] - if (e.charAt(0) === '.' && !this.dot) - continue +/*! + * is-glob + * + * Copyright (c) 2014-2017, Jon Schlinkert. + * Released under the MIT License. + */ - // these two cases enter the inGlobStar state - var instead = gspref.concat(entries[i], remainWithoutGlobStar) - this._process(instead, index, true) +var isExtglob = __webpack_require__(295); +var chars = { '{': '}', '(': ')', '[': ']'}; +var strictRegex = /\\(.)|(^!|\*|[\].+)]\?|\[[^\\\]]+\]|\{[^\\}]+\}|\(\?[:!=][^\\)]+\)|\([^|]+\|[^\\)]+\))/; +var relaxedRegex = /\\(.)|(^!|[*?{}()[\]]|\(\?)/; - var below = gspref.concat(entries[i], remain) - this._process(below, index, true) +module.exports = function isGlob(str, options) { + if (typeof str !== 'string' || str === '') { + return false; } -} - -GlobSync.prototype._processSimple = function (prefix, index) { - // XXX review this. Shouldn't it be doing the mounting etc - // before doing stat? kinda weird? - var exists = this._stat(prefix) - - if (!this.matches[index]) - this.matches[index] = Object.create(null) - - // If it doesn't exist, then just mark the lack of results - if (!exists) - return - if (prefix && isAbsolute(prefix) && !this.nomount) { - var trail = /[\/\\]$/.test(prefix) - if (prefix.charAt(0) === '/') { - prefix = path.join(this.root, prefix) - } else { - prefix = path.resolve(this.root, prefix) - if (trail) - prefix += '/' - } + if (isExtglob(str)) { + return true; } - if (process.platform === 'win32') - prefix = prefix.replace(/\\/g, '/') - - // Mark this as a match - this._emitMatch(index, prefix) -} - -// Returns either 'DIR', 'FILE', or false -GlobSync.prototype._stat = function (f) { - var abs = this._makeAbs(f) - var needDir = f.slice(-1) === '/' - - if (f.length > this.maxLength) - return false - - if (!this.stat && ownProp(this.cache, abs)) { - var c = this.cache[abs] - - if (Array.isArray(c)) - c = 'DIR' - - // It exists, but maybe not how we need it - if (!needDir || c === 'DIR') - return c - - if (needDir && c === 'FILE') - return false + var regex = strictRegex; + var match; - // otherwise we have to stat, because maybe c=true - // if we know it exists, but not what it is. + // optionally relax regex + if (options && options.strict === false) { + regex = relaxedRegex; } - var exists - var stat = this.statCache[abs] - if (!stat) { - var lstat - try { - lstat = fs.lstatSync(abs) - } catch (er) { - if (er && (er.code === 'ENOENT' || er.code === 'ENOTDIR')) { - this.statCache[abs] = false - return false - } - } + while ((match = regex.exec(str))) { + if (match[2]) return true; + var idx = match.index + match[0].length; - if (lstat && lstat.isSymbolicLink()) { - try { - stat = fs.statSync(abs) - } catch (er) { - stat = lstat + // if an open bracket/brace/paren is escaped, + // set the index to the next closing character + var open = match[1]; + var close = open ? chars[open] : null; + if (open && close) { + var n = str.indexOf(close, idx); + if (n !== -1) { + idx = n + 1; } - } else { - stat = lstat } - } - this.statCache[abs] = stat + str = str.slice(idx); + } + return false; +}; - var c = true - if (stat) - c = stat.isDirectory() ? 'DIR' : 'FILE' - this.cache[abs] = this.cache[abs] || c +/***/ }), +/* 295 */ +/***/ (function(module, exports) { - if (needDir && c === 'FILE') - return false +/*! + * is-extglob + * + * Copyright (c) 2014-2016, Jon Schlinkert. + * Licensed under the MIT License. + */ - return c -} +module.exports = function isExtglob(str) { + if (typeof str !== 'string' || str === '') { + return false; + } -GlobSync.prototype._mark = function (p) { - return common.mark(this, p) -} + var match; + while ((match = /(\\).|([@?!+*]\(.*\))/g.exec(str))) { + if (match[2]) return true; + str = str.slice(match.index + match[0].length); + } -GlobSync.prototype._makeAbs = function (f) { - return common.makeAbs(this, f) -} + return false; +}; /***/ }), -/* 219 */, -/* 220 */, -/* 221 */ +/* 296 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -module.exports = function (flag, argv) { - argv = argv || process.argv; - var terminatorPos = argv.indexOf('--'); - var prefix = /^--/.test(flag) ? '' : '--'; - var pos = argv.indexOf(prefix + flag); +const util = __webpack_require__(112); +const braces = __webpack_require__(297); +const picomatch = __webpack_require__(307); +const utils = __webpack_require__(310); +const isEmptyString = val => typeof val === 'string' && (val === '' || val === './'); - return pos !== -1 && (terminatorPos !== -1 ? pos < terminatorPos : true); -}; +/** + * Returns an array of strings that match one or more glob patterns. + * + * ```js + * const mm = require('micromatch'); + * // mm(list, patterns[, options]); + * + * console.log(mm(['a.js', 'a.txt'], ['*.js'])); + * //=> [ 'a.js' ] + * ``` + * @param {String|Array} list List of strings to match. + * @param {String|Array} patterns One or more glob patterns to use for matching. + * @param {Object} options See available [options](#options) + * @return {Array} Returns an array of matches + * @summary false + * @api public + */ +const micromatch = (list, patterns, options) => { + patterns = [].concat(patterns); + list = [].concat(list); -/***/ }), -/* 222 */, -/* 223 */ -/***/ (function(module, exports, __webpack_require__) { + let omit = new Set(); + let keep = new Set(); + let items = new Set(); + let negatives = 0; -var wrappy = __webpack_require__(123) -var reqs = Object.create(null) -var once = __webpack_require__(61) + let onResult = state => { + items.add(state.output); + if (options && options.onResult) { + options.onResult(state); + } + }; -module.exports = wrappy(inflight) + for (let i = 0; i < patterns.length; i++) { + let isMatch = picomatch(String(patterns[i]), { ...options, onResult }, true); + let negated = isMatch.state.negated || isMatch.state.negatedExtglob; + if (negated) negatives++; -function inflight (key, cb) { - if (reqs[key]) { - reqs[key].push(cb) - return null - } else { - reqs[key] = [cb] - return makeres(key) - } -} + for (let item of list) { + let matched = isMatch(item, true); -function makeres (key) { - return once(function RES () { - var cbs = reqs[key] - var len = cbs.length - var args = slice(arguments) + let match = negated ? !matched.isMatch : matched.isMatch; + if (!match) continue; - // XXX It's somewhat ambiguous whether a new callback added in this - // pass should be queued for later execution if something in the - // list of callbacks throws, or if it should just be discarded. - // However, it's such an edge case that it hardly matters, and either - // choice is likely as surprising as the other. - // As it happens, we do go ahead and schedule it for later execution. - try { - for (var i = 0; i < len; i++) { - cbs[i].apply(null, args) - } - } finally { - if (cbs.length > len) { - // added more in the interim. - // de-zalgo, just in case, but don't call again. - cbs.splice(0, len) - process.nextTick(function () { - RES.apply(null, args) - }) + if (negated) { + omit.add(matched.output); } else { - delete reqs[key] + omit.delete(matched.output); + keep.add(matched.output); } } - }) -} + } -function slice (args) { - var length = args.length - var array = [] + let result = negatives === patterns.length ? [...items] : [...keep]; + let matches = result.filter(item => !omit.has(item)); - for (var i = 0; i < length; i++) array[i] = args[i] - return array -} + if (options && matches.length === 0) { + if (options.failglob === true) { + throw new Error(`No matches found for "${patterns.join(', ')}"`); + } + if (options.nonull === true || options.nullglob === true) { + return options.unescape ? patterns.map(p => p.replace(/\\/g, '')) : patterns; + } + } -/***/ }), -/* 224 */ -/***/ (function(module, exports) { + return matches; +}; -if (typeof Object.create === 'function') { - // implementation from standard node.js 'util' module - module.exports = function inherits(ctor, superCtor) { - ctor.super_ = superCtor - ctor.prototype = Object.create(superCtor.prototype, { - constructor: { - value: ctor, - enumerable: false, - writable: true, - configurable: true - } - }); - }; -} else { - // old school shim for old browsers - module.exports = function inherits(ctor, superCtor) { - ctor.super_ = superCtor - var TempCtor = function () {} - TempCtor.prototype = superCtor.prototype - ctor.prototype = new TempCtor() - ctor.prototype.constructor = ctor - } -} - - -/***/ }), -/* 225 */, -/* 226 */, -/* 227 */ -/***/ (function(module, exports, __webpack_require__) { +/** + * Backwards compatibility + */ -// @flow +micromatch.match = micromatch; -/*:: -declare var __webpack_require__: mixed; -*/ +/** + * Returns a matcher function from the given glob `pattern` and `options`. + * The returned function takes a string to match as its only argument and returns + * true if the string is a match. + * + * ```js + * const mm = require('micromatch'); + * // mm.matcher(pattern[, options]); + * + * const isMatch = mm.matcher('*.!(*a)'); + * console.log(isMatch('a.a')); //=> false + * console.log(isMatch('a.b')); //=> true + * ``` + * @param {String} `pattern` Glob pattern + * @param {Object} `options` + * @return {Function} Returns a matcher function. + * @api public + */ -module.exports = typeof __webpack_require__ !== "undefined"; +micromatch.matcher = (pattern, options) => picomatch(pattern, options); +/** + * Returns true if **any** of the given glob `patterns` match the specified `string`. + * + * ```js + * const mm = require('micromatch'); + * // mm.isMatch(string, patterns[, options]); + * + * console.log(mm.isMatch('a.a', ['b.*', '*.a'])); //=> true + * console.log(mm.isMatch('a.a', 'b.*')); //=> false + * ``` + * @param {String} str The string to test. + * @param {String|Array} patterns One or more glob patterns to use for matching. + * @param {Object} [options] See available [options](#options). + * @return {Boolean} Returns true if any patterns match `str` + * @api public + */ -/***/ }), -/* 228 */, -/* 229 */ -/***/ (function(module, exports) { +micromatch.isMatch = (str, patterns, options) => picomatch(patterns, options)(str); /** - * Helpers. + * Backwards compatibility */ -var s = 1000; -var m = s * 60; -var h = m * 60; -var d = h * 24; -var y = d * 365.25; +micromatch.any = micromatch.isMatch; /** - * Parse or format the given `val`. - * - * Options: + * Returns a list of strings that _**do not match any**_ of the given `patterns`. * - * - `long` verbose formatting [false] + * ```js + * const mm = require('micromatch'); + * // mm.not(list, patterns[, options]); * - * @param {String|Number} val - * @param {Object} [options] - * @throws {Error} throw an error if val is not a non-empty string or a number - * @return {String|Number} + * console.log(mm.not(['a.a', 'b.b', 'c.c'], '*.a')); + * //=> ['b.b', 'c.c'] + * ``` + * @param {Array} `list` Array of strings to match. + * @param {String|Array} `patterns` One or more glob pattern to use for matching. + * @param {Object} `options` See available [options](#options) for changing how matches are performed + * @return {Array} Returns an array of strings that **do not match** the given patterns. * @api public */ -module.exports = function(val, options) { - options = options || {}; - var type = typeof val; - if (type === 'string' && val.length > 0) { - return parse(val); - } else if (type === 'number' && isNaN(val) === false) { - return options.long ? fmtLong(val) : fmtShort(val); +micromatch.not = (list, patterns, options = {}) => { + patterns = [].concat(patterns).map(String); + let result = new Set(); + let items = []; + + let onResult = state => { + if (options.onResult) options.onResult(state); + items.push(state.output); + }; + + let matches = micromatch(list, patterns, { ...options, onResult }); + + for (let item of items) { + if (!matches.includes(item)) { + result.add(item); + } } - throw new Error( - 'val is not a non-empty string or a valid number. val=' + - JSON.stringify(val) - ); + return [...result]; }; /** - * Parse the given `str` and return milliseconds. + * Returns true if the given `string` contains the given pattern. Similar + * to [.isMatch](#isMatch) but the pattern can match any part of the string. * - * @param {String} str - * @return {Number} - * @api private + * ```js + * var mm = require('micromatch'); + * // mm.contains(string, pattern[, options]); + * + * console.log(mm.contains('aa/bb/cc', '*b')); + * //=> true + * console.log(mm.contains('aa/bb/cc', '*d')); + * //=> false + * ``` + * @param {String} `str` The string to match. + * @param {String|Array} `patterns` Glob pattern to use for matching. + * @param {Object} `options` See available [options](#options) for changing how matches are performed + * @return {Boolean} Returns true if the patter matches any part of `str`. + * @api public */ -function parse(str) { - str = String(str); - if (str.length > 100) { - return; +micromatch.contains = (str, pattern, options) => { + if (typeof str !== 'string') { + throw new TypeError(`Expected a string: "${util.inspect(str)}"`); } - var match = /^((?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|years?|yrs?|y)?$/i.exec( - str - ); - if (!match) { - return; + + if (Array.isArray(pattern)) { + return pattern.some(p => micromatch.contains(str, p, options)); } - var n = parseFloat(match[1]); - var type = (match[2] || 'ms').toLowerCase(); - switch (type) { - case 'years': - case 'year': - case 'yrs': - case 'yr': - case 'y': - return n * y; - case 'days': - case 'day': - case 'd': - return n * d; - case 'hours': - case 'hour': - case 'hrs': - case 'hr': - case 'h': - return n * h; - case 'minutes': - case 'minute': - case 'mins': - case 'min': - case 'm': - return n * m; - case 'seconds': - case 'second': - case 'secs': - case 'sec': - case 's': - return n * s; - case 'milliseconds': - case 'millisecond': - case 'msecs': - case 'msec': - case 'ms': - return n; - default: - return undefined; + + if (typeof pattern === 'string') { + if (isEmptyString(str) || isEmptyString(pattern)) { + return false; + } + + if (str.includes(pattern) || (str.startsWith('./') && str.slice(2).includes(pattern))) { + return true; + } } -} + + return micromatch.isMatch(str, pattern, { ...options, contains: true }); +}; /** - * Short format for `ms`. + * Filter the keys of the given object with the given `glob` pattern + * and `options`. Does not attempt to match nested keys. If you need this feature, + * use [glob-object][] instead. * - * @param {Number} ms - * @return {String} - * @api private + * ```js + * const mm = require('micromatch'); + * // mm.matchKeys(object, patterns[, options]); + * + * const obj = { aa: 'a', ab: 'b', ac: 'c' }; + * console.log(mm.matchKeys(obj, '*b')); + * //=> { ab: 'b' } + * ``` + * @param {Object} `object` The object with keys to filter. + * @param {String|Array} `patterns` One or more glob patterns to use for matching. + * @param {Object} `options` See available [options](#options) for changing how matches are performed + * @return {Object} Returns an object with only keys that match the given patterns. + * @api public */ -function fmtShort(ms) { - if (ms >= d) { - return Math.round(ms / d) + 'd'; - } - if (ms >= h) { - return Math.round(ms / h) + 'h'; - } - if (ms >= m) { - return Math.round(ms / m) + 'm'; - } - if (ms >= s) { - return Math.round(ms / s) + 's'; +micromatch.matchKeys = (obj, patterns, options) => { + if (!utils.isObject(obj)) { + throw new TypeError('Expected the first argument to be an object'); } - return ms + 'ms'; -} + let keys = micromatch(Object.keys(obj), patterns, options); + let res = {}; + for (let key of keys) res[key] = obj[key]; + return res; +}; /** - * Long format for `ms`. + * Returns true if some of the strings in the given `list` match any of the given glob `patterns`. * - * @param {Number} ms - * @return {String} - * @api private + * ```js + * const mm = require('micromatch'); + * // mm.some(list, patterns[, options]); + * + * console.log(mm.some(['foo.js', 'bar.js'], ['*.js', '!foo.js'])); + * // true + * console.log(mm.some(['foo.js'], ['*.js', '!foo.js'])); + * // false + * ``` + * @param {String|Array} `list` The string or array of strings to test. Returns as soon as the first match is found. + * @param {String|Array} `patterns` One or more glob patterns to use for matching. + * @param {Object} `options` See available [options](#options) for changing how matches are performed + * @return {Boolean} Returns true if any patterns match `str` + * @api public */ -function fmtLong(ms) { - return plural(ms, d, 'day') || - plural(ms, h, 'hour') || - plural(ms, m, 'minute') || - plural(ms, s, 'second') || - ms + ' ms'; -} - -/** - * Pluralization helper. - */ +micromatch.some = (list, patterns, options) => { + let items = [].concat(list); -function plural(ms, n, name) { - if (ms < n) { - return; - } - if (ms < n * 1.5) { - return Math.floor(ms / n) + ' ' + name; + for (let pattern of [].concat(patterns)) { + let isMatch = picomatch(String(pattern), options); + if (items.some(item => isMatch(item))) { + return true; + } } - return Math.ceil(ms / n) + ' ' + name + 's'; -} - + return false; +}; -/***/ }), -/* 230 */, -/* 231 */, -/* 232 */, -/* 233 */ -/***/ (function(module, exports, __webpack_require__) { +/** + * Returns true if every string in the given `list` matches + * any of the given glob `patterns`. + * + * ```js + * const mm = require('micromatch'); + * // mm.every(list, patterns[, options]); + * + * console.log(mm.every('foo.js', ['foo.js'])); + * // true + * console.log(mm.every(['foo.js', 'bar.js'], ['*.js'])); + * // true + * console.log(mm.every(['foo.js', 'bar.js'], ['*.js', '!foo.js'])); + * // false + * console.log(mm.every(['foo.js'], ['*.js', '!foo.js'])); + * // false + * ``` + * @param {String|Array} `list` The string or array of strings to test. + * @param {String|Array} `patterns` One or more glob patterns to use for matching. + * @param {Object} `options` See available [options](#options) for changing how matches are performed + * @return {Boolean} Returns true if any patterns match `str` + * @api public + */ -module.exports = rimraf -rimraf.sync = rimrafSync +micromatch.every = (list, patterns, options) => { + let items = [].concat(list); -var assert = __webpack_require__(22) -var path = __webpack_require__(0) -var fs = __webpack_require__(3) -var glob = __webpack_require__(75) -var _0666 = parseInt('666', 8) + for (let pattern of [].concat(patterns)) { + let isMatch = picomatch(String(pattern), options); + if (!items.every(item => isMatch(item))) { + return false; + } + } + return true; +}; -var defaultGlobOpts = { - nosort: true, - silent: true -} +/** + * Returns true if **all** of the given `patterns` match + * the specified string. + * + * ```js + * const mm = require('micromatch'); + * // mm.all(string, patterns[, options]); + * + * console.log(mm.all('foo.js', ['foo.js'])); + * // true + * + * console.log(mm.all('foo.js', ['*.js', '!foo.js'])); + * // false + * + * console.log(mm.all('foo.js', ['*.js', 'foo.js'])); + * // true + * + * console.log(mm.all('foo.js', ['*.js', 'f*', '*o*', '*o.js'])); + * // true + * ``` + * @param {String|Array} `str` The string to test. + * @param {String|Array} `patterns` One or more glob patterns to use for matching. + * @param {Object} `options` See available [options](#options) for changing how matches are performed + * @return {Boolean} Returns true if any patterns match `str` + * @api public + */ -// for EMFILE handling -var timeout = 0 +micromatch.all = (str, patterns, options) => { + if (typeof str !== 'string') { + throw new TypeError(`Expected a string: "${util.inspect(str)}"`); + } -var isWindows = (process.platform === "win32") + return [].concat(patterns).every(p => picomatch(p, options)(str)); +}; -function defaults (options) { - var methods = [ - 'unlink', - 'chmod', - 'stat', - 'lstat', - 'rmdir', - 'readdir' - ] - methods.forEach(function(m) { - options[m] = options[m] || fs[m] - m = m + 'Sync' - options[m] = options[m] || fs[m] - }) +/** + * Returns an array of matches captured by `pattern` in `string, or `null` if the pattern did not match. + * + * ```js + * const mm = require('micromatch'); + * // mm.capture(pattern, string[, options]); + * + * console.log(mm.capture('test/*.js', 'test/foo.js')); + * //=> ['foo'] + * console.log(mm.capture('test/*.js', 'foo/bar.css')); + * //=> null + * ``` + * @param {String} `glob` Glob pattern to use for matching. + * @param {String} `input` String to match + * @param {Object} `options` See available [options](#options) for changing how matches are performed + * @return {Boolean} Returns an array of captures if the input matches the glob pattern, otherwise `null`. + * @api public + */ - options.maxBusyTries = options.maxBusyTries || 3 - options.emfileWait = options.emfileWait || 1000 - if (options.glob === false) { - options.disableGlob = true - } - options.disableGlob = options.disableGlob || false - options.glob = options.glob || defaultGlobOpts -} +micromatch.capture = (glob, input, options) => { + let posix = utils.isWindows(options); + let regex = picomatch.makeRe(String(glob), { ...options, capture: true }); + let match = regex.exec(posix ? utils.toPosixSlashes(input) : input); -function rimraf (p, options, cb) { - if (typeof options === 'function') { - cb = options - options = {} + if (match) { + return match.slice(1).map(v => v === void 0 ? '' : v); } +}; - assert(p, 'rimraf: missing path') - assert.equal(typeof p, 'string', 'rimraf: path should be a string') - assert.equal(typeof cb, 'function', 'rimraf: callback function required') - assert(options, 'rimraf: invalid options argument provided') - assert.equal(typeof options, 'object', 'rimraf: options should be object') +/** + * Create a regular expression from the given glob `pattern`. + * + * ```js + * const mm = require('micromatch'); + * // mm.makeRe(pattern[, options]); + * + * console.log(mm.makeRe('*.js')); + * //=> /^(?:(\.[\\\/])?(?!\.)(?=.)[^\/]*?\.js)$/ + * ``` + * @param {String} `pattern` A glob pattern to convert to regex. + * @param {Object} `options` + * @return {RegExp} Returns a regex created from the given pattern. + * @api public + */ - defaults(options) +micromatch.makeRe = (...args) => picomatch.makeRe(...args); - var busyTries = 0 - var errState = null - var n = 0 +/** + * Scan a glob pattern to separate the pattern into segments. Used + * by the [split](#split) method. + * + * ```js + * const mm = require('micromatch'); + * const state = mm.scan(pattern[, options]); + * ``` + * @param {String} `pattern` + * @param {Object} `options` + * @return {Object} Returns an object with + * @api public + */ - if (options.disableGlob || !glob.hasMagic(p)) - return afterGlob(null, [p]) +micromatch.scan = (...args) => picomatch.scan(...args); - options.lstat(p, function (er, stat) { - if (!er) - return afterGlob(null, [p]) +/** + * Parse a glob pattern to create the source string for a regular + * expression. + * + * ```js + * const mm = require('micromatch'); + * const state = mm(pattern[, options]); + * ``` + * @param {String} `glob` + * @param {Object} `options` + * @return {Object} Returns an object with useful properties and output to be used as regex source string. + * @api public + */ - glob(p, options.glob, afterGlob) - }) +micromatch.parse = (patterns, options) => { + let res = []; + for (let pattern of [].concat(patterns || [])) { + for (let str of braces(String(pattern), options)) { + res.push(picomatch.parse(str, options)); + } + } + return res; +}; - function next (er) { - errState = errState || er - if (--n === 0) - cb(errState) +/** + * Process the given brace `pattern`. + * + * ```js + * const { braces } = require('micromatch'); + * console.log(braces('foo/{a,b,c}/bar')); + * //=> [ 'foo/(a|b|c)/bar' ] + * + * console.log(braces('foo/{a,b,c}/bar', { expand: true })); + * //=> [ 'foo/a/bar', 'foo/b/bar', 'foo/c/bar' ] + * ``` + * @param {String} `pattern` String with brace pattern to process. + * @param {Object} `options` Any [options](#options) to change how expansion is performed. See the [braces][] library for all available options. + * @return {Array} + * @api public + */ + +micromatch.braces = (pattern, options) => { + if (typeof pattern !== 'string') throw new TypeError('Expected a string'); + if ((options && options.nobrace === true) || !/\{.*\}/.test(pattern)) { + return [pattern]; } + return braces(pattern, options); +}; - function afterGlob (er, results) { - if (er) - return cb(er) +/** + * Expand braces + */ - n = results.length - if (n === 0) - return cb() +micromatch.braceExpand = (pattern, options) => { + if (typeof pattern !== 'string') throw new TypeError('Expected a string'); + return micromatch.braces(pattern, { ...options, expand: true }); +}; - results.forEach(function (p) { - rimraf_(p, options, function CB (er) { - if (er) { - if ((er.code === "EBUSY" || er.code === "ENOTEMPTY" || er.code === "EPERM") && - busyTries < options.maxBusyTries) { - busyTries ++ - var time = busyTries * 100 - // try again, with the same exact callback as this one. - return setTimeout(function () { - rimraf_(p, options, CB) - }, time) - } +/** + * Expose micromatch + */ - // this one won't happen if graceful-fs is used. - if (er.code === "EMFILE" && timeout < options.emfileWait) { - return setTimeout(function () { - rimraf_(p, options, CB) - }, timeout ++) - } +module.exports = micromatch; - // already gone - if (er.code === "ENOENT") er = null - } - timeout = 0 - next(er) - }) - }) - } -} +/***/ }), +/* 297 */ +/***/ (function(module, exports, __webpack_require__) { -// Two possible strategies. -// 1. Assume it's a file. unlink it, then do the dir stuff on EPERM or EISDIR -// 2. Assume it's a directory. readdir, then do the file stuff on ENOTDIR -// -// Both result in an extra syscall when you guess wrong. However, there -// are likely far more normal files in the world than directories. This -// is based on the assumption that a the average number of files per -// directory is >= 1. -// -// If anyone ever complains about this, then I guess the strategy could -// be made configurable somehow. But until then, YAGNI. -function rimraf_ (p, options, cb) { - assert(p) - assert(options) - assert(typeof cb === 'function') +"use strict"; - // sunos lets the root user unlink directories, which is... weird. - // so we have to lstat here and make sure it's not a dir. - options.lstat(p, function (er, st) { - if (er && er.code === "ENOENT") - return cb(null) - // Windows can EPERM on stat. Life is suffering. - if (er && er.code === "EPERM" && isWindows) - fixWinEPERM(p, options, er, cb) +const stringify = __webpack_require__(298); +const compile = __webpack_require__(300); +const expand = __webpack_require__(304); +const parse = __webpack_require__(305); - if (st && st.isDirectory()) - return rmdir(p, options, er, cb) +/** + * Expand the given pattern or create a regex-compatible string. + * + * ```js + * const braces = require('braces'); + * console.log(braces('{a,b,c}', { compile: true })); //=> ['(a|b|c)'] + * console.log(braces('{a,b,c}')); //=> ['a', 'b', 'c'] + * ``` + * @param {String} `str` + * @param {Object} `options` + * @return {String} + * @api public + */ - options.unlink(p, function (er) { - if (er) { - if (er.code === "ENOENT") - return cb(null) - if (er.code === "EPERM") - return (isWindows) - ? fixWinEPERM(p, options, er, cb) - : rmdir(p, options, er, cb) - if (er.code === "EISDIR") - return rmdir(p, options, er, cb) +const braces = (input, options = {}) => { + let output = []; + + if (Array.isArray(input)) { + for (let pattern of input) { + let result = braces.create(pattern, options); + if (Array.isArray(result)) { + output.push(...result); + } else { + output.push(result); } - return cb(er) - }) - }) -} + } + } else { + output = [].concat(braces.create(input, options)); + } -function fixWinEPERM (p, options, er, cb) { - assert(p) - assert(options) - assert(typeof cb === 'function') - if (er) - assert(er instanceof Error) + if (options && options.expand === true && options.nodupes === true) { + output = [...new Set(output)]; + } + return output; +}; - options.chmod(p, _0666, function (er2) { - if (er2) - cb(er2.code === "ENOENT" ? null : er) - else - options.stat(p, function(er3, stats) { - if (er3) - cb(er3.code === "ENOENT" ? null : er) - else if (stats.isDirectory()) - rmdir(p, options, er, cb) - else - options.unlink(p, cb) - }) - }) -} +/** + * Parse the given `str` with the given `options`. + * + * ```js + * // braces.parse(pattern, [, options]); + * const ast = braces.parse('a/{b,c}/d'); + * console.log(ast); + * ``` + * @param {String} pattern Brace pattern to parse + * @param {Object} options + * @return {Object} Returns an AST + * @api public + */ -function fixWinEPERMSync (p, options, er) { - assert(p) - assert(options) - if (er) - assert(er instanceof Error) +braces.parse = (input, options = {}) => parse(input, options); - try { - options.chmodSync(p, _0666) - } catch (er2) { - if (er2.code === "ENOENT") - return - else - throw er - } +/** + * Creates a braces string from an AST, or an AST node. + * + * ```js + * const braces = require('braces'); + * let ast = braces.parse('foo/{a,b}/bar'); + * console.log(stringify(ast.nodes[2])); //=> '{a,b}' + * ``` + * @param {String} `input` Brace pattern or AST. + * @param {Object} `options` + * @return {Array} Returns an array of expanded values. + * @api public + */ - try { - var stats = options.statSync(p) - } catch (er3) { - if (er3.code === "ENOENT") - return - else - throw er +braces.stringify = (input, options = {}) => { + if (typeof input === 'string') { + return stringify(braces.parse(input, options), options); } + return stringify(input, options); +}; - if (stats.isDirectory()) - rmdirSync(p, options, er) - else - options.unlinkSync(p) -} +/** + * Compiles a brace pattern into a regex-compatible, optimized string. + * This method is called by the main [braces](#braces) function by default. + * + * ```js + * const braces = require('braces'); + * console.log(braces.compile('a/{b,c}/d')); + * //=> ['a/(b|c)/d'] + * ``` + * @param {String} `input` Brace pattern or AST. + * @param {Object} `options` + * @return {Array} Returns an array of expanded values. + * @api public + */ -function rmdir (p, options, originalEr, cb) { - assert(p) - assert(options) - if (originalEr) - assert(originalEr instanceof Error) - assert(typeof cb === 'function') +braces.compile = (input, options = {}) => { + if (typeof input === 'string') { + input = braces.parse(input, options); + } + return compile(input, options); +}; - // try to rmdir first, and only readdir on ENOTEMPTY or EEXIST (SunOS) - // if we guessed wrong, and it's not a directory, then - // raise the original error. - options.rmdir(p, function (er) { - if (er && (er.code === "ENOTEMPTY" || er.code === "EEXIST" || er.code === "EPERM")) - rmkids(p, options, cb) - else if (er && er.code === "ENOTDIR") - cb(originalEr) - else - cb(er) - }) -} +/** + * Expands a brace pattern into an array. This method is called by the + * main [braces](#braces) function when `options.expand` is true. Before + * using this method it's recommended that you read the [performance notes](#performance)) + * and advantages of using [.compile](#compile) instead. + * + * ```js + * const braces = require('braces'); + * console.log(braces.expand('a/{b,c}/d')); + * //=> ['a/b/d', 'a/c/d']; + * ``` + * @param {String} `pattern` Brace pattern + * @param {Object} `options` + * @return {Array} Returns an array of expanded values. + * @api public + */ -function rmkids(p, options, cb) { - assert(p) - assert(options) - assert(typeof cb === 'function') +braces.expand = (input, options = {}) => { + if (typeof input === 'string') { + input = braces.parse(input, options); + } - options.readdir(p, function (er, files) { - if (er) - return cb(er) - var n = files.length - if (n === 0) - return options.rmdir(p, cb) - var errState - files.forEach(function (f) { - rimraf(path.join(p, f), options, function (er) { - if (errState) - return - if (er) - return cb(errState = er) - if (--n === 0) - options.rmdir(p, cb) - }) - }) - }) -} + let result = expand(input, options); -// this looks simpler, and is strictly *faster*, but will -// tie up the JavaScript thread and fail on excessively -// deep directory trees. -function rimrafSync (p, options) { - options = options || {} - defaults(options) + // filter out empty strings if specified + if (options.noempty === true) { + result = result.filter(Boolean); + } - assert(p, 'rimraf: missing path') - assert.equal(typeof p, 'string', 'rimraf: path should be a string') - assert(options, 'rimraf: missing options') - assert.equal(typeof options, 'object', 'rimraf: options should be object') + // filter out duplicates if specified + if (options.nodupes === true) { + result = [...new Set(result)]; + } - var results + return result; +}; - if (options.disableGlob || !glob.hasMagic(p)) { - results = [p] - } else { - try { - options.lstatSync(p) - results = [p] - } catch (er) { - results = glob.sync(p, options.glob) - } +/** + * Processes a brace pattern and returns either an expanded array + * (if `options.expand` is true), a highly optimized regex-compatible string. + * This method is called by the main [braces](#braces) function. + * + * ```js + * const braces = require('braces'); + * console.log(braces.create('user-{200..300}/project-{a,b,c}-{1..10}')) + * //=> 'user-(20[0-9]|2[1-9][0-9]|300)/project-(a|b|c)-([1-9]|10)' + * ``` + * @param {String} `pattern` Brace pattern + * @param {Object} `options` + * @return {Array} Returns an array of expanded values. + * @api public + */ + +braces.create = (input, options = {}) => { + if (input === '' || input.length < 3) { + return [input]; } - if (!results.length) - return + return options.expand !== true + ? braces.compile(input, options) + : braces.expand(input, options); +}; - for (var i = 0; i < results.length; i++) { - var p = results[i] +/** + * Expose "braces" + */ - try { - var st = options.lstatSync(p) - } catch (er) { - if (er.code === "ENOENT") - return +module.exports = braces; - // Windows can EPERM on stat. Life is suffering. - if (er.code === "EPERM" && isWindows) - fixWinEPERMSync(p, options, er) - } - try { - // sunos lets the root user unlink directories, which is... weird. - if (st && st.isDirectory()) - rmdirSync(p, options, null) - else - options.unlinkSync(p) - } catch (er) { - if (er.code === "ENOENT") - return - if (er.code === "EPERM") - return isWindows ? fixWinEPERMSync(p, options, er) : rmdirSync(p, options, er) - if (er.code !== "EISDIR") - throw er +/***/ }), +/* 298 */ +/***/ (function(module, exports, __webpack_require__) { - rmdirSync(p, options, er) - } - } -} +"use strict"; -function rmdirSync (p, options, originalEr) { - assert(p) - assert(options) - if (originalEr) - assert(originalEr instanceof Error) - try { - options.rmdirSync(p) - } catch (er) { - if (er.code === "ENOENT") - return - if (er.code === "ENOTDIR") - throw originalEr - if (er.code === "ENOTEMPTY" || er.code === "EEXIST" || er.code === "EPERM") - rmkidsSync(p, options) - } -} +const utils = __webpack_require__(299); -function rmkidsSync (p, options) { - assert(p) - assert(options) - options.readdirSync(p).forEach(function (f) { - rimrafSync(path.join(p, f), options) - }) +module.exports = (ast, options = {}) => { + let stringify = (node, parent = {}) => { + let invalidBlock = options.escapeInvalid && utils.isInvalidBrace(parent); + let invalidNode = node.invalid === true && options.escapeInvalid === true; + let output = ''; - // We only end up here once we got ENOTEMPTY at least once, and - // at this point, we are guaranteed to have removed all the kids. - // So, we know that it won't be ENOENT or ENOTDIR or anything else. - // try really hard to delete stuff on windows, because it has a - // PROFOUNDLY annoying habit of not closing handles promptly when - // files are deleted, resulting in spurious ENOTEMPTY errors. - var retries = isWindows ? 100 : 1 - var i = 0 - do { - var threw = true - try { - var ret = options.rmdirSync(p, options) - threw = false - return ret - } finally { - if (++i < retries && threw) - continue + if (node.value) { + if ((invalidBlock || invalidNode) && utils.isOpenOrClose(node)) { + return '\\' + node.value; + } + return node.value; } - } while (true) -} + + if (node.value) { + return node.value; + } + + if (node.nodes) { + for (let child of node.nodes) { + output += stringify(child); + } + } + return output; + }; + + return stringify(ast); +}; + /***/ }), -/* 234 */, -/* 235 */, -/* 236 */, -/* 237 */, -/* 238 */, -/* 239 */ +/* 299 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var hasFlag = __webpack_require__(221); - -var support = function (level) { - if (level === 0) { - return false; - } - return { - level: level, - hasBasic: true, - has256: level >= 2, - has16m: level >= 3 - }; +exports.isInteger = num => { + if (typeof num === 'number') { + return Number.isInteger(num); + } + if (typeof num === 'string' && num.trim() !== '') { + return Number.isInteger(Number(num)); + } + return false; }; -var supportLevel = (function () { - if (hasFlag('no-color') || - hasFlag('no-colors') || - hasFlag('color=false')) { - return 0; - } +/** + * Find a node of the given type + */ - if (hasFlag('color=16m') || - hasFlag('color=full') || - hasFlag('color=truecolor')) { - return 3; - } +exports.find = (node, type) => node.nodes.find(node => node.type === type); - if (hasFlag('color=256')) { - return 2; - } +/** + * Find a node of the given type + */ - if (hasFlag('color') || - hasFlag('colors') || - hasFlag('color=true') || - hasFlag('color=always')) { - return 1; - } - - if (process.stdout && !process.stdout.isTTY) { - return 0; - } - - if (process.platform === 'win32') { - return 1; - } +exports.exceedsLimit = (min, max, step = 1, limit) => { + if (limit === false) return false; + if (!exports.isInteger(min) || !exports.isInteger(max)) return false; + return ((Number(max) - Number(min)) / Number(step)) >= limit; +}; - if ('CI' in process.env) { - if ('TRAVIS' in process.env || process.env.CI === 'Travis') { - return 1; - } +/** + * Escape the given node with '\\' before node.value + */ - return 0; - } +exports.escapeNode = (block, n = 0, type) => { + let node = block.nodes[n]; + if (!node) return; - if ('TEAMCITY_VERSION' in process.env) { - return process.env.TEAMCITY_VERSION.match(/^(9\.(0*[1-9]\d*)\.|\d{2,}\.)/) === null ? 0 : 1; - } + if ((type && node.type === type) || node.type === 'open' || node.type === 'close') { + if (node.escaped !== true) { + node.value = '\\' + node.value; + node.escaped = true; + } + } +}; - if (/^(screen|xterm)-256(?:color)?/.test(process.env.TERM)) { - return 2; - } +/** + * Returns true if the given brace node should be enclosed in literal braces + */ - if (/^screen|^xterm|^vt100|color|ansi|cygwin|linux/i.test(process.env.TERM)) { - return 1; - } +exports.encloseBrace = node => { + if (node.type !== 'brace') return false; + if ((node.commas >> 0 + node.ranges >> 0) === 0) { + node.invalid = true; + return true; + } + return false; +}; - if ('COLORTERM' in process.env) { - return 1; - } +/** + * Returns true if a brace node is invalid. + */ - if (process.env.TERM === 'dumb') { - return 0; - } +exports.isInvalidBrace = block => { + if (block.type !== 'brace') return false; + if (block.invalid === true || block.dollar) return true; + if ((block.commas >> 0 + block.ranges >> 0) === 0) { + block.invalid = true; + return true; + } + if (block.open !== true || block.close !== true) { + block.invalid = true; + return true; + } + return false; +}; - return 0; -})(); +/** + * Returns true if a node is an open or close node + */ -if (supportLevel === 0 && 'FORCE_COLOR' in process.env) { - supportLevel = 1; -} +exports.isOpenOrClose = node => { + if (node.type === 'open' || node.type === 'close') { + return true; + } + return node.open === true || node.close === true; +}; -module.exports = process && support(supportLevel); +/** + * Reduce an array of text nodes. + */ +exports.reduce = nodes => nodes.reduce((acc, node) => { + if (node.type === 'text') acc.push(node.value); + if (node.type === 'range') node.type = 'text'; + return acc; +}, []); -/***/ }) -/******/ ]); +/** + * Flatten an array + */ -/***/ }), -/* 285 */ -/***/ (function(module, exports) { +exports.flatten = (...args) => { + const result = []; + const flat = arr => { + for (let i = 0; i < arr.length; i++) { + let ele = arr[i]; + Array.isArray(ele) ? flat(ele, result) : ele !== void 0 && result.push(ele); + } + return result; + }; + flat(args); + return result; +}; -module.exports = require("buffer"); /***/ }), -/* 286 */ -/***/ (function(module, __webpack_exports__, __webpack_require__) { +/* 300 */ +/***/ (function(module, exports, __webpack_require__) { "use strict"; -__webpack_require__.r(__webpack_exports__); -/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "BootstrapCacheFile", function() { return BootstrapCacheFile; }); -/* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(133); -/* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(fs__WEBPACK_IMPORTED_MODULE_0__); -/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(4); -/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_1__); -function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } - -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -class BootstrapCacheFile { - constructor(kbn, project, checksums) { - _defineProperty(this, "path", void 0); - - _defineProperty(this, "expectedValue", void 0); +const fill = __webpack_require__(301); +const utils = __webpack_require__(299); - this.path = path__WEBPACK_IMPORTED_MODULE_1___default.a.resolve(project.targetLocation, '.bootstrap-cache'); +const compile = (ast, options = {}) => { + let walk = (node, parent = {}) => { + let invalidBlock = utils.isInvalidBrace(parent); + let invalidNode = node.invalid === true && options.escapeInvalid === true; + let invalid = invalidBlock === true || invalidNode === true; + let prefix = options.escapeInvalid === true ? '\\' : ''; + let output = ''; - if (!checksums) { - return; + if (node.isOpen === true) { + return prefix + node.value; + } + if (node.isClose === true) { + return prefix + node.value; } - const projectAndDepCacheKeys = Array.from(kbn.getProjectAndDeps(project.name).values()) // sort deps by name so that the key is stable - .sort((a, b) => a.name.localeCompare(b.name)) // get the cacheKey for each project, return undefined if the cache key couldn't be determined - .map(p => { - const cacheKey = checksums.get(p.name); + if (node.type === 'open') { + return invalid ? (prefix + node.value) : '('; + } - if (cacheKey) { - return `${p.name}:${cacheKey}`; - } - }); // if any of the relevant cache keys are undefined then the projectCacheKey must be too + if (node.type === 'close') { + return invalid ? (prefix + node.value) : ')'; + } - this.expectedValue = projectAndDepCacheKeys.some(k => !k) ? undefined : [`# this is only human readable for debugging, please don't try to parse this`, ...projectAndDepCacheKeys].join('\n'); - } + if (node.type === 'comma') { + return node.prev.type === 'comma' ? '' : (invalid ? node.value : '|'); + } - isValid() { - if (!this.expectedValue) { - return false; + if (node.value) { + return node.value; } - try { - return fs__WEBPACK_IMPORTED_MODULE_0___default.a.readFileSync(this.path, 'utf8') === this.expectedValue; - } catch (error) { - if (error.code === 'ENOENT') { - return false; - } + if (node.nodes && node.ranges > 0) { + let args = utils.reduce(node.nodes); + let range = fill(...args, { ...options, wrap: false, toRegex: true }); - throw error; + if (range.length !== 0) { + return args.length > 1 && range.length > 1 ? `(${range})` : range; + } } - } - delete() { - try { - fs__WEBPACK_IMPORTED_MODULE_0___default.a.unlinkSync(this.path); - } catch (error) { - if (error.code !== 'ENOENT') { - throw error; + if (node.nodes) { + for (let child of node.nodes) { + output += walk(child, node); } } - } + return output; + }; - write() { - if (!this.expectedValue) { - return; - } + return walk(ast); +}; - fs__WEBPACK_IMPORTED_MODULE_0___default.a.mkdirSync(path__WEBPACK_IMPORTED_MODULE_1___default.a.dirname(this.path), { - recursive: true - }); - fs__WEBPACK_IMPORTED_MODULE_0___default.a.writeFileSync(this.path, this.expectedValue); - } +module.exports = compile; -} /***/ }), -/* 287 */ -/***/ (function(module, __webpack_exports__, __webpack_require__) { +/* 301 */ +/***/ (function(module, exports, __webpack_require__) { "use strict"; -__webpack_require__.r(__webpack_exports__); -/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CleanCommand", function() { return CleanCommand; }); -/* harmony import */ var del__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(288); -/* harmony import */ var del__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(del__WEBPACK_IMPORTED_MODULE_0__); -/* harmony import */ var ora__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(375); -/* harmony import */ var ora__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(ora__WEBPACK_IMPORTED_MODULE_1__); -/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(4); -/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_2__); -/* harmony import */ var _utils_fs__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(130); -/* harmony import */ var _utils_log__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(143); -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 +/*! + * fill-range * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * Copyright (c) 2014-present, Jon Schlinkert. + * Licensed under the MIT License. */ +const util = __webpack_require__(112); +const toRegexRange = __webpack_require__(302); +const isObject = val => val !== null && typeof val === 'object' && !Array.isArray(val); -const CleanCommand = { - description: 'Remove the node_modules and target directories from all projects.', - name: 'clean', - - async run(projects) { - const toDelete = []; - - for (const project of projects.values()) { - if (await Object(_utils_fs__WEBPACK_IMPORTED_MODULE_3__["isDirectory"])(project.nodeModulesLocation)) { - toDelete.push({ - cwd: project.path, - pattern: Object(path__WEBPACK_IMPORTED_MODULE_2__["relative"])(project.path, project.nodeModulesLocation) - }); - } - - if (await Object(_utils_fs__WEBPACK_IMPORTED_MODULE_3__["isDirectory"])(project.targetLocation)) { - toDelete.push({ - cwd: project.path, - pattern: Object(path__WEBPACK_IMPORTED_MODULE_2__["relative"])(project.path, project.targetLocation) - }); - } - - const { - extraPatterns - } = project.getCleanConfig(); +const transform = toNumber => { + return value => toNumber === true ? Number(value) : String(value); +}; - if (extraPatterns) { - toDelete.push({ - cwd: project.path, - pattern: extraPatterns - }); - } - } +const isValidValue = value => { + return typeof value === 'number' || (typeof value === 'string' && value !== ''); +}; - if (toDelete.length === 0) { - _utils_log__WEBPACK_IMPORTED_MODULE_4__["log"].success('Nothing to delete'); - } else { - /** - * In order to avoid patterns like `/build` in packages from accidentally - * impacting files outside the package we use `process.chdir()` to change - * the cwd to the package and execute `del()` without the `force` option - * so it will check that each file being deleted is within the package. - * - * `del()` does support a `cwd` option, but it's only for resolving the - * patterns and does not impact the cwd check. - */ - const originalCwd = process.cwd(); +const isNumber = num => Number.isInteger(+num); - try { - for (const { - pattern, - cwd - } of toDelete) { - process.chdir(cwd); - const promise = del__WEBPACK_IMPORTED_MODULE_0___default()(pattern); +const zeros = input => { + let value = `${input}`; + let index = -1; + if (value[0] === '-') value = value.slice(1); + if (value === '0') return false; + while (value[++index] === '0'); + return index > 0; +}; - if (_utils_log__WEBPACK_IMPORTED_MODULE_4__["log"].wouldLogLevel('info')) { - ora__WEBPACK_IMPORTED_MODULE_1___default.a.promise(promise, Object(path__WEBPACK_IMPORTED_MODULE_2__["relative"])(originalCwd, Object(path__WEBPACK_IMPORTED_MODULE_2__["join"])(cwd, String(pattern)))); - } +const stringify = (start, end, options) => { + if (typeof start === 'string' || typeof end === 'string') { + return true; + } + return options.stringify === true; +}; - await promise; - } - } finally { - process.chdir(originalCwd); - } - } +const pad = (input, maxLength, toNumber) => { + if (maxLength > 0) { + let dash = input[0] === '-' ? '-' : ''; + if (dash) input = input.slice(1); + input = (dash + input.padStart(dash ? maxLength - 1 : maxLength, '0')); + } + if (toNumber === false) { + return String(input); } + return input; +}; +const toMaxLen = (input, maxLength) => { + let negative = input[0] === '-' ? '-' : ''; + if (negative) { + input = input.slice(1); + maxLength--; + } + while (input.length < maxLength) input = '0' + input; + return negative ? ('-' + input) : input; }; -/***/ }), -/* 288 */ -/***/ (function(module, exports, __webpack_require__) { +const toSequence = (parts, options) => { + parts.negatives.sort((a, b) => a < b ? -1 : a > b ? 1 : 0); + parts.positives.sort((a, b) => a < b ? -1 : a > b ? 1 : 0); -"use strict"; + let prefix = options.capture ? '' : '?:'; + let positives = ''; + let negatives = ''; + let result; -const {promisify} = __webpack_require__(111); -const path = __webpack_require__(4); -const globby = __webpack_require__(289); -const isGlob = __webpack_require__(367); -const slash = __webpack_require__(365); -const gracefulFs = __webpack_require__(132); -const isPathCwd = __webpack_require__(368); -const isPathInside = __webpack_require__(369); -const rimraf = __webpack_require__(370); -const pMap = __webpack_require__(371); + if (parts.positives.length) { + positives = parts.positives.join('|'); + } -const rimrafP = promisify(rimraf); + if (parts.negatives.length) { + negatives = `-(${prefix}${parts.negatives.join('|')})`; + } -const rimrafOptions = { - glob: false, - unlink: gracefulFs.unlink, - unlinkSync: gracefulFs.unlinkSync, - chmod: gracefulFs.chmod, - chmodSync: gracefulFs.chmodSync, - stat: gracefulFs.stat, - statSync: gracefulFs.statSync, - lstat: gracefulFs.lstat, - lstatSync: gracefulFs.lstatSync, - rmdir: gracefulFs.rmdir, - rmdirSync: gracefulFs.rmdirSync, - readdir: gracefulFs.readdir, - readdirSync: gracefulFs.readdirSync -}; + if (positives && negatives) { + result = `${positives}|${negatives}`; + } else { + result = positives || negatives; + } -function safeCheck(file, cwd) { - if (isPathCwd(file)) { - throw new Error('Cannot delete the current working directory. Can be overridden with the `force` option.'); - } + if (options.wrap) { + return `(${prefix}${result})`; + } - if (!isPathInside(file, cwd)) { - throw new Error('Cannot delete files/directories outside the current working directory. Can be overridden with the `force` option.'); - } -} + return result; +}; -function normalizePatterns(patterns) { - patterns = Array.isArray(patterns) ? patterns : [patterns]; +const toRange = (a, b, isNumbers, options) => { + if (isNumbers) { + return toRegexRange(a, b, { wrap: false, ...options }); + } - patterns = patterns.map(pattern => { - if (process.platform === 'win32' && isGlob(pattern) === false) { - return slash(pattern); - } + let start = String.fromCharCode(a); + if (a === b) return start; - return pattern; - }); + let stop = String.fromCharCode(b); + return `[${start}-${stop}]`; +}; - return patterns; -} +const toRegex = (start, end, options) => { + if (Array.isArray(start)) { + let wrap = options.wrap === true; + let prefix = options.capture ? '' : '?:'; + return wrap ? `(${prefix}${start.join('|')})` : start.join('|'); + } + return toRegexRange(start, end, options); +}; -module.exports = async (patterns, {force, dryRun, cwd = process.cwd(), ...options} = {}) => { - options = { - expandDirectories: false, - onlyFiles: false, - followSymbolicLinks: false, - cwd, - ...options - }; +const rangeError = (...args) => { + return new RangeError('Invalid range arguments: ' + util.inspect(...args)); +}; - patterns = normalizePatterns(patterns); +const invalidRange = (start, end, options) => { + if (options.strictRanges === true) throw rangeError([start, end]); + return []; +}; - const files = (await globby(patterns, options)) - .sort((a, b) => b.localeCompare(a)); +const invalidStep = (step, options) => { + if (options.strictRanges === true) { + throw new TypeError(`Expected step "${step}" to be a number`); + } + return []; +}; - const mapper = async file => { - file = path.resolve(cwd, file); +const fillNumbers = (start, end, step = 1, options = {}) => { + let a = Number(start); + let b = Number(end); - if (!force) { - safeCheck(file, cwd); - } + if (!Number.isInteger(a) || !Number.isInteger(b)) { + if (options.strictRanges === true) throw rangeError([start, end]); + return []; + } - if (!dryRun) { - await rimrafP(file, rimrafOptions); - } + // fix negative zero + if (a === 0) a = 0; + if (b === 0) b = 0; - return file; - }; + let descending = a > b; + let startString = String(start); + let endString = String(end); + let stepString = String(step); + step = Math.max(Math.abs(step), 1); - const removedFiles = await pMap(files, mapper, options); + let padded = zeros(startString) || zeros(endString) || zeros(stepString); + let maxLen = padded ? Math.max(startString.length, endString.length, stepString.length) : 0; + let toNumber = padded === false && stringify(start, end, options) === false; + let format = options.transform || transform(toNumber); - removedFiles.sort((a, b) => a.localeCompare(b)); + if (options.toRegex && step === 1) { + return toRange(toMaxLen(start, maxLen), toMaxLen(end, maxLen), true, options); + } - return removedFiles; -}; + let parts = { negatives: [], positives: [] }; + let push = num => parts[num < 0 ? 'negatives' : 'positives'].push(Math.abs(num)); + let range = []; + let index = 0; -module.exports.sync = (patterns, {force, dryRun, cwd = process.cwd(), ...options} = {}) => { - options = { - expandDirectories: false, - onlyFiles: false, - followSymbolicLinks: false, - cwd, - ...options - }; - - patterns = normalizePatterns(patterns); - - const files = globby.sync(patterns, options) - .sort((a, b) => b.localeCompare(a)); - - const removedFiles = files.map(file => { - file = path.resolve(cwd, file); - - if (!force) { - safeCheck(file, cwd); - } - - if (!dryRun) { - rimraf.sync(file, rimrafOptions); - } - - return file; - }); + while (descending ? a >= b : a <= b) { + if (options.toRegex === true && step > 1) { + push(a); + } else { + range.push(pad(format(a, index), maxLen, toNumber)); + } + a = descending ? a - step : a + step; + index++; + } - removedFiles.sort((a, b) => a.localeCompare(b)); + if (options.toRegex === true) { + return step > 1 + ? toSequence(parts, options) + : toRegex(range, null, { wrap: false, ...options }); + } - return removedFiles; + return range; }; +const fillLetters = (start, end, step = 1, options = {}) => { + if ((!isNumber(start) && start.length > 1) || (!isNumber(end) && end.length > 1)) { + return invalidRange(start, end, options); + } -/***/ }), -/* 289 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; -const fs = __webpack_require__(133); -const arrayUnion = __webpack_require__(290); -const merge2 = __webpack_require__(291); -const glob = __webpack_require__(146); -const fastGlob = __webpack_require__(292); -const dirGlob = __webpack_require__(361); -const gitignore = __webpack_require__(363); -const {FilterStream, UniqueStream} = __webpack_require__(366); + let format = options.transform || (val => String.fromCharCode(val)); + let a = `${start}`.charCodeAt(0); + let b = `${end}`.charCodeAt(0); -const DEFAULT_FILTER = () => false; + let descending = a > b; + let min = Math.min(a, b); + let max = Math.max(a, b); -const isNegative = pattern => pattern[0] === '!'; + if (options.toRegex && step === 1) { + return toRange(min, max, false, options); + } -const assertPatternsInput = patterns => { - if (!patterns.every(pattern => typeof pattern === 'string')) { - throw new TypeError('Patterns must be a string or an array of strings'); - } -}; + let range = []; + let index = 0; -const checkCwdOption = (options = {}) => { - if (!options.cwd) { - return; - } + while (descending ? a >= b : a <= b) { + range.push(format(a, index)); + a = descending ? a - step : a + step; + index++; + } - let stat; - try { - stat = fs.statSync(options.cwd); - } catch (_) { - return; - } + if (options.toRegex === true) { + return toRegex(range, null, { wrap: false, options }); + } - if (!stat.isDirectory()) { - throw new Error('The `cwd` option must be a path to a directory'); - } + return range; }; -const getPathString = p => p.stats instanceof fs.Stats ? p.path : p; - -const generateGlobTasks = (patterns, taskOptions) => { - patterns = arrayUnion([].concat(patterns)); - assertPatternsInput(patterns); - checkCwdOption(taskOptions); +const fill = (start, end, step, options = {}) => { + if (end == null && isValidValue(start)) { + return [start]; + } - const globTasks = []; + if (!isValidValue(start) || !isValidValue(end)) { + return invalidRange(start, end, options); + } - taskOptions = { - ignore: [], - expandDirectories: true, - ...taskOptions - }; + if (typeof step === 'function') { + return fill(start, end, 1, { transform: step }); + } - for (const [index, pattern] of patterns.entries()) { - if (isNegative(pattern)) { - continue; - } + if (isObject(step)) { + return fill(start, end, 0, step); + } - const ignore = patterns - .slice(index) - .filter(isNegative) - .map(pattern => pattern.slice(1)); + let opts = { ...options }; + if (opts.capture === true) opts.wrap = true; + step = step || opts.step || 1; - const options = { - ...taskOptions, - ignore: taskOptions.ignore.concat(ignore) - }; + if (!isNumber(step)) { + if (step != null && !isObject(step)) return invalidStep(step, opts); + return fill(start, end, 1, step); + } - globTasks.push({pattern, options}); - } + if (isNumber(start) && isNumber(end)) { + return fillNumbers(start, end, step, opts); + } - return globTasks; + return fillLetters(start, end, Math.max(Math.abs(step), 1), opts); }; -const globDirs = (task, fn) => { - let options = {}; - if (task.options.cwd) { - options.cwd = task.options.cwd; - } - - if (Array.isArray(task.options.expandDirectories)) { - options = { - ...options, - files: task.options.expandDirectories - }; - } else if (typeof task.options.expandDirectories === 'object') { - options = { - ...options, - ...task.options.expandDirectories - }; - } +module.exports = fill; - return fn(task.pattern, options); -}; -const getPattern = (task, fn) => task.options.expandDirectories ? globDirs(task, fn) : [task.pattern]; +/***/ }), +/* 302 */ +/***/ (function(module, exports, __webpack_require__) { -const getFilterSync = options => { - return options && options.gitignore ? - gitignore.sync({cwd: options.cwd, ignore: options.ignore}) : - DEFAULT_FILTER; -}; +"use strict"; +/*! + * to-regex-range + * + * Copyright (c) 2015-present, Jon Schlinkert. + * Released under the MIT License. + */ -const globToTask = task => glob => { - const {options} = task; - if (options.ignore && Array.isArray(options.ignore) && options.expandDirectories) { - options.ignore = dirGlob.sync(options.ignore); - } - return { - pattern: glob, - options - }; -}; -module.exports = async (patterns, options) => { - const globTasks = generateGlobTasks(patterns, options); +const isNumber = __webpack_require__(303); - const getFilter = async () => { - return options && options.gitignore ? - gitignore({cwd: options.cwd, ignore: options.ignore}) : - DEFAULT_FILTER; - }; +const toRegexRange = (min, max, options) => { + if (isNumber(min) === false) { + throw new TypeError('toRegexRange: expected the first argument to be a number'); + } - const getTasks = async () => { - const tasks = await Promise.all(globTasks.map(async task => { - const globs = await getPattern(task, dirGlob); - return Promise.all(globs.map(globToTask(task))); - })); + if (max === void 0 || min === max) { + return String(min); + } - return arrayUnion(...tasks); - }; + if (isNumber(max) === false) { + throw new TypeError('toRegexRange: expected the second argument to be a number.'); + } - const [filter, tasks] = await Promise.all([getFilter(), getTasks()]); - const paths = await Promise.all(tasks.map(task => fastGlob(task.pattern, task.options))); + let opts = { relaxZeros: true, ...options }; + if (typeof opts.strictZeros === 'boolean') { + opts.relaxZeros = opts.strictZeros === false; + } - return arrayUnion(...paths).filter(path_ => !filter(getPathString(path_))); -}; + let relax = String(opts.relaxZeros); + let shorthand = String(opts.shorthand); + let capture = String(opts.capture); + let wrap = String(opts.wrap); + let cacheKey = min + ':' + max + '=' + relax + shorthand + capture + wrap; -module.exports.sync = (patterns, options) => { - const globTasks = generateGlobTasks(patterns, options); + if (toRegexRange.cache.hasOwnProperty(cacheKey)) { + return toRegexRange.cache[cacheKey].result; + } - const tasks = globTasks.reduce((tasks, task) => { - const newTask = getPattern(task, dirGlob.sync).map(globToTask(task)); - return tasks.concat(newTask); - }, []); + let a = Math.min(min, max); + let b = Math.max(min, max); - const filter = getFilterSync(options); + if (Math.abs(a - b) === 1) { + let result = min + '|' + max; + if (opts.capture) { + return `(${result})`; + } + if (opts.wrap === false) { + return result; + } + return `(?:${result})`; + } - return tasks.reduce( - (matches, task) => arrayUnion(matches, fastGlob.sync(task.pattern, task.options)), - [] - ).filter(path_ => !filter(path_)); -}; + let isPadded = hasPadding(min) || hasPadding(max); + let state = { min, max, a, b }; + let positives = []; + let negatives = []; -module.exports.stream = (patterns, options) => { - const globTasks = generateGlobTasks(patterns, options); + if (isPadded) { + state.isPadded = isPadded; + state.maxLen = String(state.max).length; + } - const tasks = globTasks.reduce((tasks, task) => { - const newTask = getPattern(task, dirGlob.sync).map(globToTask(task)); - return tasks.concat(newTask); - }, []); + if (a < 0) { + let newMin = b < 0 ? Math.abs(b) : 1; + negatives = splitToPatterns(newMin, Math.abs(a), state, opts); + a = state.a = 0; + } - const filter = getFilterSync(options); - const filterStream = new FilterStream(p => !filter(p)); - const uniqueStream = new UniqueStream(); + if (b >= 0) { + positives = splitToPatterns(a, b, state, opts); + } - return merge2(tasks.map(task => fastGlob.stream(task.pattern, task.options))) - .pipe(filterStream) - .pipe(uniqueStream); -}; + state.negatives = negatives; + state.positives = positives; + state.result = collatePatterns(negatives, positives, opts); -module.exports.generateGlobTasks = generateGlobTasks; + if (opts.capture === true) { + state.result = `(${state.result})`; + } else if (opts.wrap !== false && (positives.length + negatives.length) > 1) { + state.result = `(?:${state.result})`; + } -module.exports.hasMagic = (patterns, options) => [] - .concat(patterns) - .some(pattern => glob.hasMagic(pattern, options)); + toRegexRange.cache[cacheKey] = state; + return state.result; +}; -module.exports.gitignore = gitignore; +function collatePatterns(neg, pos, options) { + let onlyNegative = filterPatterns(neg, pos, '-', false, options) || []; + let onlyPositive = filterPatterns(pos, neg, '', false, options) || []; + let intersected = filterPatterns(neg, pos, '-?', true, options) || []; + let subpatterns = onlyNegative.concat(intersected).concat(onlyPositive); + return subpatterns.join('|'); +} +function splitToRanges(min, max) { + let nines = 1; + let zeros = 1; -/***/ }), -/* 290 */ -/***/ (function(module, exports, __webpack_require__) { + let stop = countNines(min, nines); + let stops = new Set([max]); -"use strict"; + while (min <= stop && stop <= max) { + stops.add(stop); + nines += 1; + stop = countNines(min, nines); + } + stop = countZeros(max + 1, zeros) - 1; -module.exports = (...arguments_) => { - return [...new Set([].concat(...arguments_))]; -}; + while (min < stop && stop <= max) { + stops.add(stop); + zeros += 1; + stop = countZeros(max + 1, zeros) - 1; + } + stops = [...stops]; + stops.sort(compare); + return stops; +} -/***/ }), -/* 291 */ -/***/ (function(module, exports, __webpack_require__) { +/** + * Convert a range to a regex pattern + * @param {Number} `start` + * @param {Number} `stop` + * @return {String} + */ -"use strict"; +function rangeToPattern(start, stop, options) { + if (start === stop) { + return { pattern: start, count: [], digits: 0 }; + } -/* - * merge2 - * https://github.com/teambition/merge2 - * - * Copyright (c) 2014-2020 Teambition - * Licensed under the MIT license. - */ -const Stream = __webpack_require__(137) -const PassThrough = Stream.PassThrough -const slice = Array.prototype.slice + let zipped = zip(start, stop); + let digits = zipped.length; + let pattern = ''; + let count = 0; -module.exports = merge2 + for (let i = 0; i < digits; i++) { + let [startDigit, stopDigit] = zipped[i]; -function merge2 () { - const streamsQueue = [] - const args = slice.call(arguments) - let merging = false - let options = args[args.length - 1] + if (startDigit === stopDigit) { + pattern += startDigit; - if (options && !Array.isArray(options) && options.pipe == null) { - args.pop() - } else { - options = {} - } + } else if (startDigit !== '0' || stopDigit !== '9') { + pattern += toCharacterClass(startDigit, stopDigit, options); - const doEnd = options.end !== false - const doPipeError = options.pipeError === true - if (options.objectMode == null) { - options.objectMode = true - } - if (options.highWaterMark == null) { - options.highWaterMark = 64 * 1024 + } else { + count++; + } } - const mergedStream = PassThrough(options) - function addStream () { - for (let i = 0, len = arguments.length; i < len; i++) { - streamsQueue.push(pauseStreams(arguments[i], options)) - } - mergeStream() - return this + if (count) { + pattern += options.shorthand === true ? '\\d' : '[0-9]'; } - function mergeStream () { - if (merging) { - return - } - merging = true + return { pattern, count: [count], digits }; +} - let streams = streamsQueue.shift() - if (!streams) { - process.nextTick(endStream) - return - } - if (!Array.isArray(streams)) { - streams = [streams] - } +function splitToPatterns(min, max, tok, options) { + let ranges = splitToRanges(min, max); + let tokens = []; + let start = min; + let prev; - let pipesCount = streams.length + 1 + for (let i = 0; i < ranges.length; i++) { + let max = ranges[i]; + let obj = rangeToPattern(String(start), String(max), options); + let zeros = ''; - function next () { - if (--pipesCount > 0) { - return + if (!tok.isPadded && prev && prev.pattern === obj.pattern) { + if (prev.count.length > 1) { + prev.count.pop(); } - merging = false - mergeStream() + + prev.count.push(obj.count[0]); + prev.string = prev.pattern + toQuantifier(prev.count); + start = max + 1; + continue; } - function pipe (stream) { - function onend () { - stream.removeListener('merge2UnpipeEnd', onend) - stream.removeListener('end', onend) - if (doPipeError) { - stream.removeListener('error', onerror) - } - next() - } - function onerror (err) { - mergedStream.emit('error', err) - } - // skip ended stream - if (stream._readableState.endEmitted) { - return next() - } + if (tok.isPadded) { + zeros = padZeros(max, tok, options); + } - stream.on('merge2UnpipeEnd', onend) - stream.on('end', onend) + obj.string = zeros + obj.pattern + toQuantifier(obj.count); + tokens.push(obj); + start = max + 1; + prev = obj; + } - if (doPipeError) { - stream.on('error', onerror) - } + return tokens; +} - stream.pipe(mergedStream, { end: false }) - // compatible for old stream - stream.resume() - } +function filterPatterns(arr, comparison, prefix, intersection, options) { + let result = []; - for (let i = 0; i < streams.length; i++) { - pipe(streams[i]) - } + for (let ele of arr) { + let { string } = ele; - next() - } + // only push if _both_ are negative... + if (!intersection && !contains(comparison, 'string', string)) { + result.push(prefix + string); + } - function endStream () { - merging = false - // emit 'queueDrain' when all streams merged. - mergedStream.emit('queueDrain') - if (doEnd) { - mergedStream.end() + // or _both_ are positive + if (intersection && contains(comparison, 'string', string)) { + result.push(prefix + string); } } + return result; +} - mergedStream.setMaxListeners(0) - mergedStream.add = addStream - mergedStream.on('unpipe', function (stream) { - stream.emit('merge2UnpipeEnd') - }) +/** + * Zip strings + */ - if (args.length) { - addStream.apply(null, args) - } - return mergedStream +function zip(a, b) { + let arr = []; + for (let i = 0; i < a.length; i++) arr.push([a[i], b[i]]); + return arr; } -// check and pause streams for pipe. -function pauseStreams (streams, options) { - if (!Array.isArray(streams)) { - // Backwards-compat with old-style streams - if (!streams._readableState && streams.pipe) { - streams = streams.pipe(PassThrough(options)) - } - if (!streams._readableState || !streams.pause || !streams.pipe) { - throw new Error('Only readable stream can be merged.') - } - streams.pause() - } else { - for (let i = 0, len = streams.length; i < len; i++) { - streams[i] = pauseStreams(streams[i], options) - } - } - return streams +function compare(a, b) { + return a > b ? 1 : b > a ? -1 : 0; } +function contains(arr, key, val) { + return arr.some(ele => ele[key] === val); +} -/***/ }), -/* 292 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - -const taskManager = __webpack_require__(293); -const async_1 = __webpack_require__(322); -const stream_1 = __webpack_require__(357); -const sync_1 = __webpack_require__(358); -const settings_1 = __webpack_require__(360); -const utils = __webpack_require__(294); -async function FastGlob(source, options) { - assertPatternsInput(source); - const works = getWorks(source, async_1.default, options); - const result = await Promise.all(works); - return utils.array.flatten(result); -} -// https://github.com/typescript-eslint/typescript-eslint/issues/60 -// eslint-disable-next-line no-redeclare -(function (FastGlob) { - function sync(source, options) { - assertPatternsInput(source); - const works = getWorks(source, sync_1.default, options); - return utils.array.flatten(works); - } - FastGlob.sync = sync; - function stream(source, options) { - assertPatternsInput(source); - const works = getWorks(source, stream_1.default, options); - /** - * The stream returned by the provider cannot work with an asynchronous iterator. - * To support asynchronous iterators, regardless of the number of tasks, we always multiplex streams. - * This affects performance (+25%). I don't see best solution right now. - */ - return utils.stream.merge(works); - } - FastGlob.stream = stream; - function generateTasks(source, options) { - assertPatternsInput(source); - const patterns = [].concat(source); - const settings = new settings_1.default(options); - return taskManager.generate(patterns, settings); - } - FastGlob.generateTasks = generateTasks; - function isDynamicPattern(source, options) { - assertPatternsInput(source); - const settings = new settings_1.default(options); - return utils.pattern.isDynamicPattern(source, settings); - } - FastGlob.isDynamicPattern = isDynamicPattern; - function escapePath(source) { - assertPatternsInput(source); - return utils.path.escape(source); - } - FastGlob.escapePath = escapePath; -})(FastGlob || (FastGlob = {})); -function getWorks(source, _Provider, options) { - const patterns = [].concat(source); - const settings = new settings_1.default(options); - const tasks = taskManager.generate(patterns, settings); - const provider = new _Provider(settings); - return tasks.map(provider.read, provider); -} -function assertPatternsInput(input) { - const source = [].concat(input); - const isValidSource = source.every((item) => utils.string.isString(item) && !utils.string.isEmpty(item)); - if (!isValidSource) { - throw new TypeError('Patterns must be a string (non empty) or an array of strings'); - } -} -module.exports = FastGlob; - - -/***/ }), -/* 293 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - -Object.defineProperty(exports, "__esModule", { value: true }); -const utils = __webpack_require__(294); -function generate(patterns, settings) { - const positivePatterns = getPositivePatterns(patterns); - const negativePatterns = getNegativePatternsAsPositive(patterns, settings.ignore); - const staticPatterns = positivePatterns.filter((pattern) => utils.pattern.isStaticPattern(pattern, settings)); - const dynamicPatterns = positivePatterns.filter((pattern) => utils.pattern.isDynamicPattern(pattern, settings)); - const staticTasks = convertPatternsToTasks(staticPatterns, negativePatterns, /* dynamic */ false); - const dynamicTasks = convertPatternsToTasks(dynamicPatterns, negativePatterns, /* dynamic */ true); - return staticTasks.concat(dynamicTasks); -} -exports.generate = generate; -function convertPatternsToTasks(positive, negative, dynamic) { - const positivePatternsGroup = groupPatternsByBaseDirectory(positive); - // When we have a global group – there is no reason to divide the patterns into independent tasks. - // In this case, the global task covers the rest. - if ('.' in positivePatternsGroup) { - const task = convertPatternGroupToTask('.', positive, negative, dynamic); - return [task]; - } - return convertPatternGroupsToTasks(positivePatternsGroup, negative, dynamic); -} -exports.convertPatternsToTasks = convertPatternsToTasks; -function getPositivePatterns(patterns) { - return utils.pattern.getPositivePatterns(patterns); -} -exports.getPositivePatterns = getPositivePatterns; -function getNegativePatternsAsPositive(patterns, ignore) { - const negative = utils.pattern.getNegativePatterns(patterns).concat(ignore); - const positive = negative.map(utils.pattern.convertToPositivePattern); - return positive; -} -exports.getNegativePatternsAsPositive = getNegativePatternsAsPositive; -function groupPatternsByBaseDirectory(patterns) { - const group = {}; - return patterns.reduce((collection, pattern) => { - const base = utils.pattern.getBaseDirectory(pattern); - if (base in collection) { - collection[base].push(pattern); - } - else { - collection[base] = [pattern]; - } - return collection; - }, group); -} -exports.groupPatternsByBaseDirectory = groupPatternsByBaseDirectory; -function convertPatternGroupsToTasks(positive, negative, dynamic) { - return Object.keys(positive).map((base) => { - return convertPatternGroupToTask(base, positive[base], negative, dynamic); - }); -} -exports.convertPatternGroupsToTasks = convertPatternGroupsToTasks; -function convertPatternGroupToTask(base, positive, negative, dynamic) { - return { - dynamic, - positive, - negative, - base, - patterns: [].concat(positive, negative.map(utils.pattern.convertToNegativePattern)) - }; -} -exports.convertPatternGroupToTask = convertPatternGroupToTask; - +function countNines(min, len) { + return Number(String(min).slice(0, -len) + '9'.repeat(len)); +} -/***/ }), -/* 294 */ -/***/ (function(module, exports, __webpack_require__) { +function countZeros(integer, zeros) { + return integer - (integer % Math.pow(10, zeros)); +} -"use strict"; - -Object.defineProperty(exports, "__esModule", { value: true }); -const array = __webpack_require__(295); -exports.array = array; -const errno = __webpack_require__(296); -exports.errno = errno; -const fs = __webpack_require__(297); -exports.fs = fs; -const path = __webpack_require__(298); -exports.path = path; -const pattern = __webpack_require__(299); -exports.pattern = pattern; -const stream = __webpack_require__(320); -exports.stream = stream; -const string = __webpack_require__(321); -exports.string = string; +function toQuantifier(digits) { + let [start = 0, stop = ''] = digits; + if (stop || start > 1) { + return `{${start + (stop ? ',' + stop : '')}}`; + } + return ''; +} +function toCharacterClass(a, b, options) { + return `[${a}${(b - a === 1) ? '' : '-'}${b}]`; +} -/***/ }), -/* 295 */ -/***/ (function(module, exports, __webpack_require__) { +function hasPadding(str) { + return /^-?(0+)\d/.test(str); +} -"use strict"; - -Object.defineProperty(exports, "__esModule", { value: true }); -function flatten(items) { - return items.reduce((collection, item) => [].concat(collection, item), []); -} -exports.flatten = flatten; -function splitWhen(items, predicate) { - const result = [[]]; - let groupIndex = 0; - for (const item of items) { - if (predicate(item)) { - groupIndex++; - result[groupIndex] = []; - } - else { - result[groupIndex].push(item); - } - } - return result; -} -exports.splitWhen = splitWhen; +function padZeros(value, tok, options) { + if (!tok.isPadded) { + return value; + } + let diff = Math.abs(tok.maxLen - String(value).length); + let relax = options.relaxZeros !== false; -/***/ }), -/* 296 */ -/***/ (function(module, exports, __webpack_require__) { + switch (diff) { + case 0: + return ''; + case 1: + return relax ? '0?' : '0'; + case 2: + return relax ? '0{0,2}' : '00'; + default: { + return relax ? `0{0,${diff}}` : `0{${diff}}`; + } + } +} -"use strict"; - -Object.defineProperty(exports, "__esModule", { value: true }); -function isEnoentCodeError(error) { - return error.code === 'ENOENT'; -} -exports.isEnoentCodeError = isEnoentCodeError; +/** + * Cache + */ +toRegexRange.cache = {}; +toRegexRange.clearCache = () => (toRegexRange.cache = {}); -/***/ }), -/* 297 */ -/***/ (function(module, exports, __webpack_require__) { +/** + * Expose `toRegexRange` + */ -"use strict"; - -Object.defineProperty(exports, "__esModule", { value: true }); -class DirentFromStats { - constructor(name, stats) { - this.name = name; - this.isBlockDevice = stats.isBlockDevice.bind(stats); - this.isCharacterDevice = stats.isCharacterDevice.bind(stats); - this.isDirectory = stats.isDirectory.bind(stats); - this.isFIFO = stats.isFIFO.bind(stats); - this.isFile = stats.isFile.bind(stats); - this.isSocket = stats.isSocket.bind(stats); - this.isSymbolicLink = stats.isSymbolicLink.bind(stats); - } -} -function createDirentFromStats(name, stats) { - return new DirentFromStats(name, stats); -} -exports.createDirentFromStats = createDirentFromStats; +module.exports = toRegexRange; /***/ }), -/* 298 */ +/* 303 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; - -Object.defineProperty(exports, "__esModule", { value: true }); -const path = __webpack_require__(4); -const LEADING_DOT_SEGMENT_CHARACTERS_COUNT = 2; // ./ or .\\ -const UNESCAPED_GLOB_SYMBOLS_RE = /(\\?)([()*?[\]{|}]|^!|[!+@](?=\())/g; -/** - * Designed to work only with simple paths: `dir\\file`. - */ -function unixify(filepath) { - return filepath.replace(/\\/g, '/'); -} -exports.unixify = unixify; -function makeAbsolute(cwd, filepath) { - return path.resolve(cwd, filepath); -} -exports.makeAbsolute = makeAbsolute; -function escape(pattern) { - return pattern.replace(UNESCAPED_GLOB_SYMBOLS_RE, '\\$2'); -} -exports.escape = escape; -function removeLeadingDotSegment(entry) { - // We do not use `startsWith` because this is 10x slower than current implementation for some cases. - // eslint-disable-next-line @typescript-eslint/prefer-string-starts-ends-with - if (entry.charAt(0) === '.') { - const secondCharactery = entry.charAt(1); - if (secondCharactery === '/' || secondCharactery === '\\') { - return entry.slice(LEADING_DOT_SEGMENT_CHARACTERS_COUNT); - } - } - return entry; -} -exports.removeLeadingDotSegment = removeLeadingDotSegment; +/*! + * is-number + * + * Copyright (c) 2014-present, Jon Schlinkert. + * Released under the MIT License. + */ -/***/ }), -/* 299 */ -/***/ (function(module, exports, __webpack_require__) { -"use strict"; - -Object.defineProperty(exports, "__esModule", { value: true }); -const path = __webpack_require__(4); -const globParent = __webpack_require__(300); -const micromatch = __webpack_require__(303); -const picomatch = __webpack_require__(314); -const GLOBSTAR = '**'; -const ESCAPE_SYMBOL = '\\'; -const COMMON_GLOB_SYMBOLS_RE = /[*?]|^!/; -const REGEX_CHARACTER_CLASS_SYMBOLS_RE = /\[.*]/; -const REGEX_GROUP_SYMBOLS_RE = /(?:^|[^!*+?@])\(.*\|.*\)/; -const GLOB_EXTENSION_SYMBOLS_RE = /[!*+?@]\(.*\)/; -const BRACE_EXPANSIONS_SYMBOLS_RE = /{.*(?:,|\.\.).*}/; -function isStaticPattern(pattern, options = {}) { - return !isDynamicPattern(pattern, options); -} -exports.isStaticPattern = isStaticPattern; -function isDynamicPattern(pattern, options = {}) { - /** - * When the `caseSensitiveMatch` option is disabled, all patterns must be marked as dynamic, because we cannot check - * filepath directly (without read directory). - */ - if (options.caseSensitiveMatch === false || pattern.includes(ESCAPE_SYMBOL)) { - return true; - } - if (COMMON_GLOB_SYMBOLS_RE.test(pattern) || REGEX_CHARACTER_CLASS_SYMBOLS_RE.test(pattern) || REGEX_GROUP_SYMBOLS_RE.test(pattern)) { - return true; - } - if (options.extglob !== false && GLOB_EXTENSION_SYMBOLS_RE.test(pattern)) { - return true; - } - if (options.braceExpansion !== false && BRACE_EXPANSIONS_SYMBOLS_RE.test(pattern)) { - return true; - } - return false; -} -exports.isDynamicPattern = isDynamicPattern; -function convertToPositivePattern(pattern) { - return isNegativePattern(pattern) ? pattern.slice(1) : pattern; -} -exports.convertToPositivePattern = convertToPositivePattern; -function convertToNegativePattern(pattern) { - return '!' + pattern; -} -exports.convertToNegativePattern = convertToNegativePattern; -function isNegativePattern(pattern) { - return pattern.startsWith('!') && pattern[1] !== '('; -} -exports.isNegativePattern = isNegativePattern; -function isPositivePattern(pattern) { - return !isNegativePattern(pattern); -} -exports.isPositivePattern = isPositivePattern; -function getNegativePatterns(patterns) { - return patterns.filter(isNegativePattern); -} -exports.getNegativePatterns = getNegativePatterns; -function getPositivePatterns(patterns) { - return patterns.filter(isPositivePattern); -} -exports.getPositivePatterns = getPositivePatterns; -function getBaseDirectory(pattern) { - return globParent(pattern, { flipBackslashes: false }); -} -exports.getBaseDirectory = getBaseDirectory; -function hasGlobStar(pattern) { - return pattern.includes(GLOBSTAR); -} -exports.hasGlobStar = hasGlobStar; -function endsWithSlashGlobStar(pattern) { - return pattern.endsWith('/' + GLOBSTAR); -} -exports.endsWithSlashGlobStar = endsWithSlashGlobStar; -function isAffectDepthOfReadingPattern(pattern) { - const basename = path.basename(pattern); - return endsWithSlashGlobStar(pattern) || isStaticPattern(basename); -} -exports.isAffectDepthOfReadingPattern = isAffectDepthOfReadingPattern; -function expandPatternsWithBraceExpansion(patterns) { - return patterns.reduce((collection, pattern) => { - return collection.concat(expandBraceExpansion(pattern)); - }, []); -} -exports.expandPatternsWithBraceExpansion = expandPatternsWithBraceExpansion; -function expandBraceExpansion(pattern) { - return micromatch.braces(pattern, { - expand: true, - nodupes: true - }); -} -exports.expandBraceExpansion = expandBraceExpansion; -function getPatternParts(pattern, options) { - const info = picomatch.scan(pattern, Object.assign(Object.assign({}, options), { parts: true })); - // See micromatch/picomatch#58 for more details - if (info.parts.length === 0) { - return [pattern]; - } - return info.parts; -} -exports.getPatternParts = getPatternParts; -function makeRe(pattern, options) { - return micromatch.makeRe(pattern, options); -} -exports.makeRe = makeRe; -function convertPatternsToRe(patterns, options) { - return patterns.map((pattern) => makeRe(pattern, options)); -} -exports.convertPatternsToRe = convertPatternsToRe; -function matchAny(entry, patternsRe) { - return patternsRe.some((patternRe) => patternRe.test(entry)); -} -exports.matchAny = matchAny; +module.exports = function(num) { + if (typeof num === 'number') { + return num - num === 0; + } + if (typeof num === 'string' && num.trim() !== '') { + return Number.isFinite ? Number.isFinite(+num) : isFinite(+num); + } + return false; +}; /***/ }), -/* 300 */ +/* 304 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var isGlob = __webpack_require__(301); -var pathPosixDirname = __webpack_require__(4).posix.dirname; -var isWin32 = __webpack_require__(120).platform() === 'win32'; +const fill = __webpack_require__(301); +const stringify = __webpack_require__(298); +const utils = __webpack_require__(299); -var slash = '/'; -var backslash = /\\/g; -var enclosure = /[\{\[].*[\/]*.*[\}\]]$/; -var globby = /(^|[^\\])([\{\[]|\([^\)]+$)/; -var escaped = /\\([\!\*\?\|\[\]\(\)\{\}])/g; +const append = (queue = '', stash = '', enclose = false) => { + let result = []; -/** - * @param {string} str - * @param {Object} opts - * @param {boolean} [opts.flipBackslashes=true] - */ -module.exports = function globParent(str, opts) { - var options = Object.assign({ flipBackslashes: true }, opts); + queue = [].concat(queue); + stash = [].concat(stash); - // flip windows path separators - if (options.flipBackslashes && isWin32 && str.indexOf(slash) < 0) { - str = str.replace(backslash, slash); + if (!stash.length) return queue; + if (!queue.length) { + return enclose ? utils.flatten(stash).map(ele => `{${ele}}`) : stash; } - // special case for strings ending in enclosure containing path separator - if (enclosure.test(str)) { - str += slash; + for (let item of queue) { + if (Array.isArray(item)) { + for (let value of item) { + result.push(append(value, stash, enclose)); + } + } else { + for (let ele of stash) { + if (enclose === true && typeof ele === 'string') ele = `{${ele}}`; + result.push(Array.isArray(ele) ? append(item, ele, enclose) : (item + ele)); + } + } } + return utils.flatten(result); +}; - // preserves full path in case of trailing path separator - str += 'a'; +const expand = (ast, options = {}) => { + let rangeLimit = options.rangeLimit === void 0 ? 1000 : options.rangeLimit; - // remove path parts that are globby - do { - str = pathPosixDirname(str); - } while (isGlob(str) || globby.test(str)); + let walk = (node, parent = {}) => { + node.queue = []; - // remove escape chars and return result - return str.replace(escaped, '$1'); -}; + let p = parent; + let q = parent.queue; + while (p.type !== 'brace' && p.type !== 'root' && p.parent) { + p = p.parent; + q = p.queue; + } -/***/ }), -/* 301 */ -/***/ (function(module, exports, __webpack_require__) { + if (node.invalid || node.dollar) { + q.push(append(q.pop(), stringify(node, options))); + return; + } -/*! - * is-glob - * - * Copyright (c) 2014-2017, Jon Schlinkert. - * Released under the MIT License. - */ + if (node.type === 'brace' && node.invalid !== true && node.nodes.length === 2) { + q.push(append(q.pop(), ['{}'])); + return; + } -var isExtglob = __webpack_require__(302); -var chars = { '{': '}', '(': ')', '[': ']'}; -var strictRegex = /\\(.)|(^!|\*|[\].+)]\?|\[[^\\\]]+\]|\{[^\\}]+\}|\(\?[:!=][^\\)]+\)|\([^|]+\|[^\\)]+\))/; -var relaxedRegex = /\\(.)|(^!|[*?{}()[\]]|\(\?)/; - -module.exports = function isGlob(str, options) { - if (typeof str !== 'string' || str === '') { - return false; - } + if (node.nodes && node.ranges > 0) { + let args = utils.reduce(node.nodes); - if (isExtglob(str)) { - return true; - } + if (utils.exceedsLimit(...args, options.step, rangeLimit)) { + throw new RangeError('expanded array length exceeds range limit. Use options.rangeLimit to increase or disable the limit.'); + } - var regex = strictRegex; - var match; + let range = fill(...args, options); + if (range.length === 0) { + range = stringify(node, options); + } - // optionally relax regex - if (options && options.strict === false) { - regex = relaxedRegex; - } + q.push(append(q.pop(), range)); + node.nodes = []; + return; + } - while ((match = regex.exec(str))) { - if (match[2]) return true; - var idx = match.index + match[0].length; + let enclose = utils.encloseBrace(node); + let queue = node.queue; + let block = node; - // if an open bracket/brace/paren is escaped, - // set the index to the next closing character - var open = match[1]; - var close = open ? chars[open] : null; - if (open && close) { - var n = str.indexOf(close, idx); - if (n !== -1) { - idx = n + 1; - } + while (block.type !== 'brace' && block.type !== 'root' && block.parent) { + block = block.parent; + queue = block.queue; } - str = str.slice(idx); - } - return false; -}; + for (let i = 0; i < node.nodes.length; i++) { + let child = node.nodes[i]; + if (child.type === 'comma' && node.type === 'brace') { + if (i === 1) queue.push(''); + queue.push(''); + continue; + } -/***/ }), -/* 302 */ -/***/ (function(module, exports) { + if (child.type === 'close') { + q.push(append(q.pop(), queue, enclose)); + continue; + } -/*! - * is-extglob - * - * Copyright (c) 2014-2016, Jon Schlinkert. - * Licensed under the MIT License. - */ + if (child.value && child.type !== 'open') { + queue.push(append(queue.pop(), child.value)); + continue; + } -module.exports = function isExtglob(str) { - if (typeof str !== 'string' || str === '') { - return false; - } + if (child.nodes) { + walk(child, node); + } + } - var match; - while ((match = /(\\).|([@?!+*]\(.*\))/g.exec(str))) { - if (match[2]) return true; - str = str.slice(match.index + match[0].length); - } + return queue; + }; - return false; + return utils.flatten(walk(ast)); }; +module.exports = expand; + /***/ }), -/* 303 */ +/* 305 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const util = __webpack_require__(111); -const braces = __webpack_require__(304); -const picomatch = __webpack_require__(314); -const utils = __webpack_require__(317); -const isEmptyString = val => typeof val === 'string' && (val === '' || val === './'); +const stringify = __webpack_require__(298); /** - * Returns an array of strings that match one or more glob patterns. - * - * ```js - * const mm = require('micromatch'); - * // mm(list, patterns[, options]); - * - * console.log(mm(['a.js', 'a.txt'], ['*.js'])); - * //=> [ 'a.js' ] - * ``` - * @param {String|Array} list List of strings to match. - * @param {String|Array} patterns One or more glob patterns to use for matching. - * @param {Object} options See available [options](#options) - * @return {Array} Returns an array of matches - * @summary false - * @api public + * Constants */ -const micromatch = (list, patterns, options) => { - patterns = [].concat(patterns); - list = [].concat(list); +const { + MAX_LENGTH, + CHAR_BACKSLASH, /* \ */ + CHAR_BACKTICK, /* ` */ + CHAR_COMMA, /* , */ + CHAR_DOT, /* . */ + CHAR_LEFT_PARENTHESES, /* ( */ + CHAR_RIGHT_PARENTHESES, /* ) */ + CHAR_LEFT_CURLY_BRACE, /* { */ + CHAR_RIGHT_CURLY_BRACE, /* } */ + CHAR_LEFT_SQUARE_BRACKET, /* [ */ + CHAR_RIGHT_SQUARE_BRACKET, /* ] */ + CHAR_DOUBLE_QUOTE, /* " */ + CHAR_SINGLE_QUOTE, /* ' */ + CHAR_NO_BREAK_SPACE, + CHAR_ZERO_WIDTH_NOBREAK_SPACE +} = __webpack_require__(306); - let omit = new Set(); - let keep = new Set(); - let items = new Set(); - let negatives = 0; +/** + * parse + */ - let onResult = state => { - items.add(state.output); - if (options && options.onResult) { - options.onResult(state); - } - }; +const parse = (input, options = {}) => { + if (typeof input !== 'string') { + throw new TypeError('Expected a string'); + } - for (let i = 0; i < patterns.length; i++) { - let isMatch = picomatch(String(patterns[i]), { ...options, onResult }, true); - let negated = isMatch.state.negated || isMatch.state.negatedExtglob; - if (negated) negatives++; + let opts = options || {}; + let max = typeof opts.maxLength === 'number' ? Math.min(MAX_LENGTH, opts.maxLength) : MAX_LENGTH; + if (input.length > max) { + throw new SyntaxError(`Input length (${input.length}), exceeds max characters (${max})`); + } - for (let item of list) { - let matched = isMatch(item, true); + let ast = { type: 'root', input, nodes: [] }; + let stack = [ast]; + let block = ast; + let prev = ast; + let brackets = 0; + let length = input.length; + let index = 0; + let depth = 0; + let value; + let memo = {}; - let match = negated ? !matched.isMatch : matched.isMatch; - if (!match) continue; + /** + * Helpers + */ - if (negated) { - omit.add(matched.output); - } else { - omit.delete(matched.output); - keep.add(matched.output); - } + const advance = () => input[index++]; + const push = node => { + if (node.type === 'text' && prev.type === 'dot') { + prev.type = 'text'; } - } - let result = negatives === patterns.length ? [...items] : [...keep]; - let matches = result.filter(item => !omit.has(item)); - - if (options && matches.length === 0) { - if (options.failglob === true) { - throw new Error(`No matches found for "${patterns.join(', ')}"`); + if (prev && prev.type === 'text' && node.type === 'text') { + prev.value += node.value; + return; } - if (options.nonull === true || options.nullglob === true) { - return options.unescape ? patterns.map(p => p.replace(/\\/g, '')) : patterns; - } - } + block.nodes.push(node); + node.parent = block; + node.prev = prev; + prev = node; + return node; + }; - return matches; -}; + push({ type: 'bos' }); -/** - * Backwards compatibility - */ + while (index < length) { + block = stack[stack.length - 1]; + value = advance(); -micromatch.match = micromatch; + /** + * Invalid chars + */ -/** - * Returns a matcher function from the given glob `pattern` and `options`. - * The returned function takes a string to match as its only argument and returns - * true if the string is a match. - * - * ```js - * const mm = require('micromatch'); - * // mm.matcher(pattern[, options]); - * - * const isMatch = mm.matcher('*.!(*a)'); - * console.log(isMatch('a.a')); //=> false - * console.log(isMatch('a.b')); //=> true - * ``` - * @param {String} `pattern` Glob pattern - * @param {Object} `options` - * @return {Function} Returns a matcher function. - * @api public - */ + if (value === CHAR_ZERO_WIDTH_NOBREAK_SPACE || value === CHAR_NO_BREAK_SPACE) { + continue; + } -micromatch.matcher = (pattern, options) => picomatch(pattern, options); + /** + * Escaped chars + */ -/** - * Returns true if **any** of the given glob `patterns` match the specified `string`. - * - * ```js - * const mm = require('micromatch'); - * // mm.isMatch(string, patterns[, options]); - * - * console.log(mm.isMatch('a.a', ['b.*', '*.a'])); //=> true - * console.log(mm.isMatch('a.a', 'b.*')); //=> false - * ``` - * @param {String} str The string to test. - * @param {String|Array} patterns One or more glob patterns to use for matching. - * @param {Object} [options] See available [options](#options). - * @return {Boolean} Returns true if any patterns match `str` - * @api public - */ + if (value === CHAR_BACKSLASH) { + push({ type: 'text', value: (options.keepEscaping ? value : '') + advance() }); + continue; + } -micromatch.isMatch = (str, patterns, options) => picomatch(patterns, options)(str); + /** + * Right square bracket (literal): ']' + */ -/** - * Backwards compatibility - */ + if (value === CHAR_RIGHT_SQUARE_BRACKET) { + push({ type: 'text', value: '\\' + value }); + continue; + } -micromatch.any = micromatch.isMatch; + /** + * Left square bracket: '[' + */ -/** - * Returns a list of strings that _**do not match any**_ of the given `patterns`. - * - * ```js - * const mm = require('micromatch'); - * // mm.not(list, patterns[, options]); - * - * console.log(mm.not(['a.a', 'b.b', 'c.c'], '*.a')); - * //=> ['b.b', 'c.c'] - * ``` - * @param {Array} `list` Array of strings to match. - * @param {String|Array} `patterns` One or more glob pattern to use for matching. - * @param {Object} `options` See available [options](#options) for changing how matches are performed - * @return {Array} Returns an array of strings that **do not match** the given patterns. - * @api public - */ + if (value === CHAR_LEFT_SQUARE_BRACKET) { + brackets++; -micromatch.not = (list, patterns, options = {}) => { - patterns = [].concat(patterns).map(String); - let result = new Set(); - let items = []; + let closed = true; + let next; - let onResult = state => { - if (options.onResult) options.onResult(state); - items.push(state.output); - }; + while (index < length && (next = advance())) { + value += next; - let matches = micromatch(list, patterns, { ...options, onResult }); + if (next === CHAR_LEFT_SQUARE_BRACKET) { + brackets++; + continue; + } - for (let item of items) { - if (!matches.includes(item)) { - result.add(item); - } - } - return [...result]; -}; + if (next === CHAR_BACKSLASH) { + value += advance(); + continue; + } -/** - * Returns true if the given `string` contains the given pattern. Similar - * to [.isMatch](#isMatch) but the pattern can match any part of the string. - * - * ```js - * var mm = require('micromatch'); - * // mm.contains(string, pattern[, options]); - * - * console.log(mm.contains('aa/bb/cc', '*b')); - * //=> true - * console.log(mm.contains('aa/bb/cc', '*d')); - * //=> false - * ``` - * @param {String} `str` The string to match. - * @param {String|Array} `patterns` Glob pattern to use for matching. - * @param {Object} `options` See available [options](#options) for changing how matches are performed - * @return {Boolean} Returns true if the patter matches any part of `str`. - * @api public - */ + if (next === CHAR_RIGHT_SQUARE_BRACKET) { + brackets--; -micromatch.contains = (str, pattern, options) => { - if (typeof str !== 'string') { - throw new TypeError(`Expected a string: "${util.inspect(str)}"`); - } + if (brackets === 0) { + break; + } + } + } - if (Array.isArray(pattern)) { - return pattern.some(p => micromatch.contains(str, p, options)); - } + push({ type: 'text', value }); + continue; + } - if (typeof pattern === 'string') { - if (isEmptyString(str) || isEmptyString(pattern)) { - return false; + /** + * Parentheses + */ + + if (value === CHAR_LEFT_PARENTHESES) { + block = push({ type: 'paren', nodes: [] }); + stack.push(block); + push({ type: 'text', value }); + continue; } - if (str.includes(pattern) || (str.startsWith('./') && str.slice(2).includes(pattern))) { - return true; + if (value === CHAR_RIGHT_PARENTHESES) { + if (block.type !== 'paren') { + push({ type: 'text', value }); + continue; + } + block = stack.pop(); + push({ type: 'text', value }); + block = stack[stack.length - 1]; + continue; } - } - return micromatch.isMatch(str, pattern, { ...options, contains: true }); -}; + /** + * Quotes: '|"|` + */ -/** - * Filter the keys of the given object with the given `glob` pattern - * and `options`. Does not attempt to match nested keys. If you need this feature, - * use [glob-object][] instead. - * - * ```js - * const mm = require('micromatch'); - * // mm.matchKeys(object, patterns[, options]); - * - * const obj = { aa: 'a', ab: 'b', ac: 'c' }; - * console.log(mm.matchKeys(obj, '*b')); - * //=> { ab: 'b' } - * ``` - * @param {Object} `object` The object with keys to filter. - * @param {String|Array} `patterns` One or more glob patterns to use for matching. - * @param {Object} `options` See available [options](#options) for changing how matches are performed - * @return {Object} Returns an object with only keys that match the given patterns. - * @api public - */ + if (value === CHAR_DOUBLE_QUOTE || value === CHAR_SINGLE_QUOTE || value === CHAR_BACKTICK) { + let open = value; + let next; -micromatch.matchKeys = (obj, patterns, options) => { - if (!utils.isObject(obj)) { - throw new TypeError('Expected the first argument to be an object'); - } - let keys = micromatch(Object.keys(obj), patterns, options); - let res = {}; - for (let key of keys) res[key] = obj[key]; - return res; -}; + if (options.keepQuotes !== true) { + value = ''; + } -/** - * Returns true if some of the strings in the given `list` match any of the given glob `patterns`. - * - * ```js - * const mm = require('micromatch'); - * // mm.some(list, patterns[, options]); - * - * console.log(mm.some(['foo.js', 'bar.js'], ['*.js', '!foo.js'])); - * // true - * console.log(mm.some(['foo.js'], ['*.js', '!foo.js'])); - * // false - * ``` - * @param {String|Array} `list` The string or array of strings to test. Returns as soon as the first match is found. - * @param {String|Array} `patterns` One or more glob patterns to use for matching. - * @param {Object} `options` See available [options](#options) for changing how matches are performed - * @return {Boolean} Returns true if any patterns match `str` - * @api public - */ + while (index < length && (next = advance())) { + if (next === CHAR_BACKSLASH) { + value += next + advance(); + continue; + } -micromatch.some = (list, patterns, options) => { - let items = [].concat(list); + if (next === open) { + if (options.keepQuotes === true) value += next; + break; + } - for (let pattern of [].concat(patterns)) { - let isMatch = picomatch(String(pattern), options); - if (items.some(item => isMatch(item))) { - return true; + value += next; + } + + push({ type: 'text', value }); + continue; } - } - return false; -}; -/** - * Returns true if every string in the given `list` matches - * any of the given glob `patterns`. - * - * ```js - * const mm = require('micromatch'); - * // mm.every(list, patterns[, options]); - * - * console.log(mm.every('foo.js', ['foo.js'])); - * // true - * console.log(mm.every(['foo.js', 'bar.js'], ['*.js'])); - * // true - * console.log(mm.every(['foo.js', 'bar.js'], ['*.js', '!foo.js'])); - * // false - * console.log(mm.every(['foo.js'], ['*.js', '!foo.js'])); - * // false - * ``` - * @param {String|Array} `list` The string or array of strings to test. - * @param {String|Array} `patterns` One or more glob patterns to use for matching. - * @param {Object} `options` See available [options](#options) for changing how matches are performed - * @return {Boolean} Returns true if any patterns match `str` - * @api public - */ + /** + * Left curly brace: '{' + */ -micromatch.every = (list, patterns, options) => { - let items = [].concat(list); + if (value === CHAR_LEFT_CURLY_BRACE) { + depth++; - for (let pattern of [].concat(patterns)) { - let isMatch = picomatch(String(pattern), options); - if (!items.every(item => isMatch(item))) { - return false; - } - } - return true; -}; + let dollar = prev.value && prev.value.slice(-1) === '$' || block.dollar === true; + let brace = { + type: 'brace', + open: true, + close: false, + dollar, + depth, + commas: 0, + ranges: 0, + nodes: [] + }; -/** - * Returns true if **all** of the given `patterns` match - * the specified string. - * - * ```js - * const mm = require('micromatch'); - * // mm.all(string, patterns[, options]); - * - * console.log(mm.all('foo.js', ['foo.js'])); - * // true - * - * console.log(mm.all('foo.js', ['*.js', '!foo.js'])); - * // false - * - * console.log(mm.all('foo.js', ['*.js', 'foo.js'])); - * // true - * - * console.log(mm.all('foo.js', ['*.js', 'f*', '*o*', '*o.js'])); - * // true - * ``` - * @param {String|Array} `str` The string to test. - * @param {String|Array} `patterns` One or more glob patterns to use for matching. - * @param {Object} `options` See available [options](#options) for changing how matches are performed - * @return {Boolean} Returns true if any patterns match `str` - * @api public - */ + block = push(brace); + stack.push(block); + push({ type: 'open', value }); + continue; + } -micromatch.all = (str, patterns, options) => { - if (typeof str !== 'string') { - throw new TypeError(`Expected a string: "${util.inspect(str)}"`); - } + /** + * Right curly brace: '}' + */ - return [].concat(patterns).every(p => picomatch(p, options)(str)); -}; + if (value === CHAR_RIGHT_CURLY_BRACE) { + if (block.type !== 'brace') { + push({ type: 'text', value }); + continue; + } -/** - * Returns an array of matches captured by `pattern` in `string, or `null` if the pattern did not match. - * - * ```js - * const mm = require('micromatch'); - * // mm.capture(pattern, string[, options]); - * - * console.log(mm.capture('test/*.js', 'test/foo.js')); - * //=> ['foo'] - * console.log(mm.capture('test/*.js', 'foo/bar.css')); - * //=> null - * ``` - * @param {String} `glob` Glob pattern to use for matching. - * @param {String} `input` String to match - * @param {Object} `options` See available [options](#options) for changing how matches are performed - * @return {Boolean} Returns an array of captures if the input matches the glob pattern, otherwise `null`. - * @api public - */ + let type = 'close'; + block = stack.pop(); + block.close = true; -micromatch.capture = (glob, input, options) => { - let posix = utils.isWindows(options); - let regex = picomatch.makeRe(String(glob), { ...options, capture: true }); - let match = regex.exec(posix ? utils.toPosixSlashes(input) : input); + push({ type, value }); + depth--; - if (match) { - return match.slice(1).map(v => v === void 0 ? '' : v); - } -}; + block = stack[stack.length - 1]; + continue; + } -/** - * Create a regular expression from the given glob `pattern`. - * - * ```js - * const mm = require('micromatch'); - * // mm.makeRe(pattern[, options]); - * - * console.log(mm.makeRe('*.js')); - * //=> /^(?:(\.[\\\/])?(?!\.)(?=.)[^\/]*?\.js)$/ - * ``` - * @param {String} `pattern` A glob pattern to convert to regex. - * @param {Object} `options` - * @return {RegExp} Returns a regex created from the given pattern. - * @api public - */ + /** + * Comma: ',' + */ -micromatch.makeRe = (...args) => picomatch.makeRe(...args); + if (value === CHAR_COMMA && depth > 0) { + if (block.ranges > 0) { + block.ranges = 0; + let open = block.nodes.shift(); + block.nodes = [open, { type: 'text', value: stringify(block) }]; + } -/** - * Scan a glob pattern to separate the pattern into segments. Used - * by the [split](#split) method. - * - * ```js - * const mm = require('micromatch'); - * const state = mm.scan(pattern[, options]); - * ``` - * @param {String} `pattern` - * @param {Object} `options` - * @return {Object} Returns an object with - * @api public - */ + push({ type: 'comma', value }); + block.commas++; + continue; + } -micromatch.scan = (...args) => picomatch.scan(...args); + /** + * Dot: '.' + */ -/** - * Parse a glob pattern to create the source string for a regular - * expression. - * - * ```js - * const mm = require('micromatch'); - * const state = mm(pattern[, options]); - * ``` - * @param {String} `glob` - * @param {Object} `options` - * @return {Object} Returns an object with useful properties and output to be used as regex source string. - * @api public - */ + if (value === CHAR_DOT && depth > 0 && block.commas === 0) { + let siblings = block.nodes; -micromatch.parse = (patterns, options) => { - let res = []; - for (let pattern of [].concat(patterns || [])) { - for (let str of braces(String(pattern), options)) { - res.push(picomatch.parse(str, options)); + if (depth === 0 || siblings.length === 0) { + push({ type: 'text', value }); + continue; + } + + if (prev.type === 'dot') { + block.range = []; + prev.value += value; + prev.type = 'range'; + + if (block.nodes.length !== 3 && block.nodes.length !== 5) { + block.invalid = true; + block.ranges = 0; + prev.type = 'text'; + continue; + } + + block.ranges++; + block.args = []; + continue; + } + + if (prev.type === 'range') { + siblings.pop(); + + let before = siblings[siblings.length - 1]; + before.value += prev.value + value; + prev = before; + block.ranges--; + continue; + } + + push({ type: 'dot', value }); + continue; } - } - return res; -}; -/** - * Process the given brace `pattern`. - * - * ```js - * const { braces } = require('micromatch'); - * console.log(braces('foo/{a,b,c}/bar')); - * //=> [ 'foo/(a|b|c)/bar' ] - * - * console.log(braces('foo/{a,b,c}/bar', { expand: true })); - * //=> [ 'foo/a/bar', 'foo/b/bar', 'foo/c/bar' ] - * ``` - * @param {String} `pattern` String with brace pattern to process. - * @param {Object} `options` Any [options](#options) to change how expansion is performed. See the [braces][] library for all available options. - * @return {Array} - * @api public - */ + /** + * Text + */ -micromatch.braces = (pattern, options) => { - if (typeof pattern !== 'string') throw new TypeError('Expected a string'); - if ((options && options.nobrace === true) || !/\{.*\}/.test(pattern)) { - return [pattern]; + push({ type: 'text', value }); } - return braces(pattern, options); + + // Mark imbalanced braces and brackets as invalid + do { + block = stack.pop(); + + if (block.type !== 'root') { + block.nodes.forEach(node => { + if (!node.nodes) { + if (node.type === 'open') node.isOpen = true; + if (node.type === 'close') node.isClose = true; + if (!node.nodes) node.type = 'text'; + node.invalid = true; + } + }); + + // get the location of the block on parent.nodes (block's siblings) + let parent = stack[stack.length - 1]; + let index = parent.nodes.indexOf(block); + // replace the (invalid) block with it's nodes + parent.nodes.splice(index, 1, ...block.nodes); + } + } while (stack.length > 0); + + push({ type: 'eos' }); + return ast; }; -/** - * Expand braces - */ +module.exports = parse; -micromatch.braceExpand = (pattern, options) => { - if (typeof pattern !== 'string') throw new TypeError('Expected a string'); - return micromatch.braces(pattern, { ...options, expand: true }); + +/***/ }), +/* 306 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +module.exports = { + MAX_LENGTH: 1024 * 64, + + // Digits + CHAR_0: '0', /* 0 */ + CHAR_9: '9', /* 9 */ + + // Alphabet chars. + CHAR_UPPERCASE_A: 'A', /* A */ + CHAR_LOWERCASE_A: 'a', /* a */ + CHAR_UPPERCASE_Z: 'Z', /* Z */ + CHAR_LOWERCASE_Z: 'z', /* z */ + + CHAR_LEFT_PARENTHESES: '(', /* ( */ + CHAR_RIGHT_PARENTHESES: ')', /* ) */ + + CHAR_ASTERISK: '*', /* * */ + + // Non-alphabetic chars. + CHAR_AMPERSAND: '&', /* & */ + CHAR_AT: '@', /* @ */ + CHAR_BACKSLASH: '\\', /* \ */ + CHAR_BACKTICK: '`', /* ` */ + CHAR_CARRIAGE_RETURN: '\r', /* \r */ + CHAR_CIRCUMFLEX_ACCENT: '^', /* ^ */ + CHAR_COLON: ':', /* : */ + CHAR_COMMA: ',', /* , */ + CHAR_DOLLAR: '$', /* . */ + CHAR_DOT: '.', /* . */ + CHAR_DOUBLE_QUOTE: '"', /* " */ + CHAR_EQUAL: '=', /* = */ + CHAR_EXCLAMATION_MARK: '!', /* ! */ + CHAR_FORM_FEED: '\f', /* \f */ + CHAR_FORWARD_SLASH: '/', /* / */ + CHAR_HASH: '#', /* # */ + CHAR_HYPHEN_MINUS: '-', /* - */ + CHAR_LEFT_ANGLE_BRACKET: '<', /* < */ + CHAR_LEFT_CURLY_BRACE: '{', /* { */ + CHAR_LEFT_SQUARE_BRACKET: '[', /* [ */ + CHAR_LINE_FEED: '\n', /* \n */ + CHAR_NO_BREAK_SPACE: '\u00A0', /* \u00A0 */ + CHAR_PERCENT: '%', /* % */ + CHAR_PLUS: '+', /* + */ + CHAR_QUESTION_MARK: '?', /* ? */ + CHAR_RIGHT_ANGLE_BRACKET: '>', /* > */ + CHAR_RIGHT_CURLY_BRACE: '}', /* } */ + CHAR_RIGHT_SQUARE_BRACKET: ']', /* ] */ + CHAR_SEMICOLON: ';', /* ; */ + CHAR_SINGLE_QUOTE: '\'', /* ' */ + CHAR_SPACE: ' ', /* */ + CHAR_TAB: '\t', /* \t */ + CHAR_UNDERSCORE: '_', /* _ */ + CHAR_VERTICAL_LINE: '|', /* | */ + CHAR_ZERO_WIDTH_NOBREAK_SPACE: '\uFEFF' /* \uFEFF */ }; -/** - * Expose micromatch - */ -module.exports = micromatch; +/***/ }), +/* 307 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +module.exports = __webpack_require__(308); /***/ }), -/* 304 */ +/* 308 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const stringify = __webpack_require__(305); -const compile = __webpack_require__(307); -const expand = __webpack_require__(311); +const path = __webpack_require__(4); +const scan = __webpack_require__(309); const parse = __webpack_require__(312); +const utils = __webpack_require__(310); +const constants = __webpack_require__(311); +const isObject = val => val && typeof val === 'object' && !Array.isArray(val); /** - * Expand the given pattern or create a regex-compatible string. + * Creates a matcher function from one or more glob patterns. The + * returned function takes a string to match as its first argument, + * and returns true if the string is a match. The returned matcher + * function also takes a boolean as the second argument that, when true, + * returns an object with additional information. * * ```js - * const braces = require('braces'); - * console.log(braces('{a,b,c}', { compile: true })); //=> ['(a|b|c)'] - * console.log(braces('{a,b,c}')); //=> ['a', 'b', 'c'] + * const picomatch = require('picomatch'); + * // picomatch(glob[, options]); + * + * const isMatch = picomatch('*.!(*a)'); + * console.log(isMatch('a.a')); //=> false + * console.log(isMatch('a.b')); //=> true * ``` - * @param {String} `str` - * @param {Object} `options` - * @return {String} + * @name picomatch + * @param {String|Array} `globs` One or more glob patterns. + * @param {Object=} `options` + * @return {Function=} Returns a matcher function. * @api public */ -const braces = (input, options = {}) => { - let output = []; +const picomatch = (glob, options, returnState = false) => { + if (Array.isArray(glob)) { + const fns = glob.map(input => picomatch(input, options, returnState)); + const arrayMatcher = str => { + for (const isMatch of fns) { + const state = isMatch(str); + if (state) return state; + } + return false; + }; + return arrayMatcher; + } - if (Array.isArray(input)) { - for (let pattern of input) { - let result = braces.create(pattern, options); - if (Array.isArray(result)) { - output.push(...result); - } else { - output.push(result); + const isState = isObject(glob) && glob.tokens && glob.input; + + if (glob === '' || (typeof glob !== 'string' && !isState)) { + throw new TypeError('Expected pattern to be a non-empty string'); + } + + const opts = options || {}; + const posix = utils.isWindows(options); + const regex = isState + ? picomatch.compileRe(glob, options) + : picomatch.makeRe(glob, options, false, true); + + const state = regex.state; + delete regex.state; + + let isIgnored = () => false; + if (opts.ignore) { + const ignoreOpts = { ...options, ignore: null, onMatch: null, onResult: null }; + isIgnored = picomatch(opts.ignore, ignoreOpts, returnState); + } + + const matcher = (input, returnObject = false) => { + const { isMatch, match, output } = picomatch.test(input, regex, options, { glob, posix }); + const result = { glob, state, regex, posix, input, output, match, isMatch }; + + if (typeof opts.onResult === 'function') { + opts.onResult(result); + } + + if (isMatch === false) { + result.isMatch = false; + return returnObject ? result : false; + } + + if (isIgnored(input)) { + if (typeof opts.onIgnore === 'function') { + opts.onIgnore(result); } + result.isMatch = false; + return returnObject ? result : false; } - } else { - output = [].concat(braces.create(input, options)); - } - if (options && options.expand === true && options.nodupes === true) { - output = [...new Set(output)]; + if (typeof opts.onMatch === 'function') { + opts.onMatch(result); + } + return returnObject ? result : true; + }; + + if (returnState) { + matcher.state = state; } - return output; + + return matcher; }; /** - * Parse the given `str` with the given `options`. + * Test `input` with the given `regex`. This is used by the main + * `picomatch()` function to test the input string. * * ```js - * // braces.parse(pattern, [, options]); - * const ast = braces.parse('a/{b,c}/d'); - * console.log(ast); + * const picomatch = require('picomatch'); + * // picomatch.test(input, regex[, options]); + * + * console.log(picomatch.test('foo/bar', /^(?:([^/]*?)\/([^/]*?))$/)); + * // { isMatch: true, match: [ 'foo/', 'foo', 'bar' ], output: 'foo/bar' } * ``` - * @param {String} pattern Brace pattern to parse - * @param {Object} options - * @return {Object} Returns an AST + * @param {String} `input` String to test. + * @param {RegExp} `regex` + * @return {Object} Returns an object with matching info. * @api public */ -braces.parse = (input, options = {}) => parse(input, options); +picomatch.test = (input, regex, options, { glob, posix } = {}) => { + if (typeof input !== 'string') { + throw new TypeError('Expected input to be a string'); + } + + if (input === '') { + return { isMatch: false, output: '' }; + } + + const opts = options || {}; + const format = opts.format || (posix ? utils.toPosixSlashes : null); + let match = input === glob; + let output = (match && format) ? format(input) : input; + + if (match === false) { + output = format ? format(input) : input; + match = output === glob; + } + + if (match === false || opts.capture === true) { + if (opts.matchBase === true || opts.basename === true) { + match = picomatch.matchBase(input, regex, options, posix); + } else { + match = regex.exec(output); + } + } + + return { isMatch: Boolean(match), match, output }; +}; /** - * Creates a braces string from an AST, or an AST node. + * Match the basename of a filepath. * * ```js - * const braces = require('braces'); - * let ast = braces.parse('foo/{a,b}/bar'); - * console.log(stringify(ast.nodes[2])); //=> '{a,b}' + * const picomatch = require('picomatch'); + * // picomatch.matchBase(input, glob[, options]); + * console.log(picomatch.matchBase('foo/bar.js', '*.js'); // true * ``` - * @param {String} `input` Brace pattern or AST. - * @param {Object} `options` - * @return {Array} Returns an array of expanded values. + * @param {String} `input` String to test. + * @param {RegExp|String} `glob` Glob pattern or regex created by [.makeRe](#makeRe). + * @return {Boolean} * @api public */ -braces.stringify = (input, options = {}) => { - if (typeof input === 'string') { - return stringify(braces.parse(input, options), options); - } - return stringify(input, options); +picomatch.matchBase = (input, glob, options, posix = utils.isWindows(options)) => { + const regex = glob instanceof RegExp ? glob : picomatch.makeRe(glob, options); + return regex.test(path.basename(input)); }; /** - * Compiles a brace pattern into a regex-compatible, optimized string. - * This method is called by the main [braces](#braces) function by default. + * Returns true if **any** of the given glob `patterns` match the specified `string`. * * ```js - * const braces = require('braces'); - * console.log(braces.compile('a/{b,c}/d')); - * //=> ['a/(b|c)/d'] + * const picomatch = require('picomatch'); + * // picomatch.isMatch(string, patterns[, options]); + * + * console.log(picomatch.isMatch('a.a', ['b.*', '*.a'])); //=> true + * console.log(picomatch.isMatch('a.a', 'b.*')); //=> false * ``` - * @param {String} `input` Brace pattern or AST. - * @param {Object} `options` - * @return {Array} Returns an array of expanded values. + * @param {String|Array} str The string to test. + * @param {String|Array} patterns One or more glob patterns to use for matching. + * @param {Object} [options] See available [options](#options). + * @return {Boolean} Returns true if any patterns match `str` * @api public */ -braces.compile = (input, options = {}) => { - if (typeof input === 'string') { - input = braces.parse(input, options); - } - return compile(input, options); -}; +picomatch.isMatch = (str, patterns, options) => picomatch(patterns, options)(str); /** - * Expands a brace pattern into an array. This method is called by the - * main [braces](#braces) function when `options.expand` is true. Before - * using this method it's recommended that you read the [performance notes](#performance)) - * and advantages of using [.compile](#compile) instead. - * + * Parse a glob pattern to create the source string for a regular + * expression. + * * ```js - * const braces = require('braces'); - * console.log(braces.expand('a/{b,c}/d')); - * //=> ['a/b/d', 'a/c/d']; + * const picomatch = require('picomatch'); + * const result = picomatch.parse(pattern[, options]); * ``` - * @param {String} `pattern` Brace pattern + * @param {String} `pattern` * @param {Object} `options` - * @return {Array} Returns an array of expanded values. + * @return {Object} Returns an object with useful properties and output to be used as a regex source string. * @api public */ -braces.expand = (input, options = {}) => { - if (typeof input === 'string') { - input = braces.parse(input, options); - } - - let result = expand(input, options); - - // filter out empty strings if specified - if (options.noempty === true) { - result = result.filter(Boolean); - } - - // filter out duplicates if specified - if (options.nodupes === true) { - result = [...new Set(result)]; - } - - return result; +picomatch.parse = (pattern, options) => { + if (Array.isArray(pattern)) return pattern.map(p => picomatch.parse(p, options)); + return parse(pattern, { ...options, fastpaths: false }); }; /** - * Processes a brace pattern and returns either an expanded array - * (if `options.expand` is true), a highly optimized regex-compatible string. - * This method is called by the main [braces](#braces) function. + * Scan a glob pattern to separate the pattern into segments. * * ```js - * const braces = require('braces'); - * console.log(braces.create('user-{200..300}/project-{a,b,c}-{1..10}')) - * //=> 'user-(20[0-9]|2[1-9][0-9]|300)/project-(a|b|c)-([1-9]|10)' + * const picomatch = require('picomatch'); + * // picomatch.scan(input[, options]); + * + * const result = picomatch.scan('!./foo/*.js'); + * console.log(result); + * { prefix: '!./', + * input: '!./foo/*.js', + * start: 3, + * base: 'foo', + * glob: '*.js', + * isBrace: false, + * isBracket: false, + * isGlob: true, + * isExtglob: false, + * isGlobstar: false, + * negated: true } * ``` - * @param {String} `pattern` Brace pattern + * @param {String} `input` Glob pattern to scan. * @param {Object} `options` - * @return {Array} Returns an array of expanded values. + * @return {Object} Returns an object with * @api public */ -braces.create = (input, options = {}) => { - if (input === '' || input.length < 3) { - return [input]; - } - - return options.expand !== true - ? braces.compile(input, options) - : braces.expand(input, options); -}; +picomatch.scan = (input, options) => scan(input, options); /** - * Expose "braces" + * Create a regular expression from a parsed glob pattern. + * + * ```js + * const picomatch = require('picomatch'); + * const state = picomatch.parse('*.js'); + * // picomatch.compileRe(state[, options]); + * + * console.log(picomatch.compileRe(state)); + * //=> /^(?:(?!\.)(?=.)[^/]*?\.js)$/ + * ``` + * @param {String} `state` The object returned from the `.parse` method. + * @param {Object} `options` + * @return {RegExp} Returns a regex created from the given pattern. + * @api public */ -module.exports = braces; - - -/***/ }), -/* 305 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -const utils = __webpack_require__(306); - -module.exports = (ast, options = {}) => { - let stringify = (node, parent = {}) => { - let invalidBlock = options.escapeInvalid && utils.isInvalidBrace(parent); - let invalidNode = node.invalid === true && options.escapeInvalid === true; - let output = ''; +picomatch.compileRe = (parsed, options, returnOutput = false, returnState = false) => { + if (returnOutput === true) { + return parsed.output; + } - if (node.value) { - if ((invalidBlock || invalidNode) && utils.isOpenOrClose(node)) { - return '\\' + node.value; - } - return node.value; - } + const opts = options || {}; + const prepend = opts.contains ? '' : '^'; + const append = opts.contains ? '' : '$'; - if (node.value) { - return node.value; - } + let source = `${prepend}(?:${parsed.output})${append}`; + if (parsed && parsed.negated === true) { + source = `^(?!${source}).*$`; + } - if (node.nodes) { - for (let child of node.nodes) { - output += stringify(child); - } - } - return output; - }; + const regex = picomatch.toRegex(source, options); + if (returnState === true) { + regex.state = parsed; + } - return stringify(ast); + return regex; }; +picomatch.makeRe = (input, options, returnOutput = false, returnState = false) => { + if (!input || typeof input !== 'string') { + throw new TypeError('Expected a non-empty string'); + } + const opts = options || {}; + let parsed = { negated: false, fastpaths: true }; + let prefix = ''; + let output; -/***/ }), -/* 306 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - + if (input.startsWith('./')) { + input = input.slice(2); + prefix = parsed.prefix = './'; + } -exports.isInteger = num => { - if (typeof num === 'number') { - return Number.isInteger(num); + if (opts.fastpaths !== false && (input[0] === '.' || input[0] === '*')) { + output = parse.fastpaths(input, options); } - if (typeof num === 'string' && num.trim() !== '') { - return Number.isInteger(Number(num)); + + if (output === undefined) { + parsed = parse(input, options); + parsed.prefix = prefix + (parsed.prefix || ''); + } else { + parsed.output = output; } - return false; + + return picomatch.compileRe(parsed, options, returnOutput, returnState); }; /** - * Find a node of the given type + * Create a regular expression from the given regex source string. + * + * ```js + * const picomatch = require('picomatch'); + * // picomatch.toRegex(source[, options]); + * + * const { output } = picomatch.parse('*.js'); + * console.log(picomatch.toRegex(output)); + * //=> /^(?:(?!\.)(?=.)[^/]*?\.js)$/ + * ``` + * @param {String} `source` Regular expression source string. + * @param {Object} `options` + * @return {RegExp} + * @api public */ -exports.find = (node, type) => node.nodes.find(node => node.type === type); +picomatch.toRegex = (source, options) => { + try { + const opts = options || {}; + return new RegExp(source, opts.flags || (opts.nocase ? 'i' : '')); + } catch (err) { + if (options && options.debug === true) throw err; + return /$^/; + } +}; /** - * Find a node of the given type + * Picomatch constants. + * @return {Object} */ -exports.exceedsLimit = (min, max, step = 1, limit) => { - if (limit === false) return false; - if (!exports.isInteger(min) || !exports.isInteger(max)) return false; - return ((Number(max) - Number(min)) / Number(step)) >= limit; -}; +picomatch.constants = constants; /** - * Escape the given node with '\\' before node.value + * Expose "picomatch" */ -exports.escapeNode = (block, n = 0, type) => { - let node = block.nodes[n]; - if (!node) return; +module.exports = picomatch; - if ((type && node.type === type) || node.type === 'open' || node.type === 'close') { - if (node.escaped !== true) { - node.value = '\\' + node.value; - node.escaped = true; - } - } -}; -/** - * Returns true if the given brace node should be enclosed in literal braces - */ +/***/ }), +/* 309 */ +/***/ (function(module, exports, __webpack_require__) { -exports.encloseBrace = node => { - if (node.type !== 'brace') return false; - if ((node.commas >> 0 + node.ranges >> 0) === 0) { - node.invalid = true; - return true; - } - return false; -}; +"use strict"; -/** - * Returns true if a brace node is invalid. - */ -exports.isInvalidBrace = block => { - if (block.type !== 'brace') return false; - if (block.invalid === true || block.dollar) return true; - if ((block.commas >> 0 + block.ranges >> 0) === 0) { - block.invalid = true; - return true; - } - if (block.open !== true || block.close !== true) { - block.invalid = true; - return true; - } - return false; -}; +const utils = __webpack_require__(310); +const { + CHAR_ASTERISK, /* * */ + CHAR_AT, /* @ */ + CHAR_BACKWARD_SLASH, /* \ */ + CHAR_COMMA, /* , */ + CHAR_DOT, /* . */ + CHAR_EXCLAMATION_MARK, /* ! */ + CHAR_FORWARD_SLASH, /* / */ + CHAR_LEFT_CURLY_BRACE, /* { */ + CHAR_LEFT_PARENTHESES, /* ( */ + CHAR_LEFT_SQUARE_BRACKET, /* [ */ + CHAR_PLUS, /* + */ + CHAR_QUESTION_MARK, /* ? */ + CHAR_RIGHT_CURLY_BRACE, /* } */ + CHAR_RIGHT_PARENTHESES, /* ) */ + CHAR_RIGHT_SQUARE_BRACKET /* ] */ +} = __webpack_require__(311); -/** - * Returns true if a node is an open or close node - */ +const isPathSeparator = code => { + return code === CHAR_FORWARD_SLASH || code === CHAR_BACKWARD_SLASH; +}; -exports.isOpenOrClose = node => { - if (node.type === 'open' || node.type === 'close') { - return true; +const depth = token => { + if (token.isPrefix !== true) { + token.depth = token.isGlobstar ? Infinity : 1; } - return node.open === true || node.close === true; }; /** - * Reduce an array of text nodes. + * Quickly scans a glob pattern and returns an object with a handful of + * useful properties, like `isGlob`, `path` (the leading non-glob, if it exists), + * `glob` (the actual pattern), and `negated` (true if the path starts with `!`). + * + * ```js + * const pm = require('picomatch'); + * console.log(pm.scan('foo/bar/*.js')); + * { isGlob: true, input: 'foo/bar/*.js', base: 'foo/bar', glob: '*.js' } + * ``` + * @param {String} `str` + * @param {Object} `options` + * @return {Object} Returns an object with tokens and regex source string. + * @api public */ -exports.reduce = nodes => nodes.reduce((acc, node) => { - if (node.type === 'text') acc.push(node.value); - if (node.type === 'range') node.type = 'text'; - return acc; -}, []); +const scan = (input, options) => { + const opts = options || {}; -/** - * Flatten an array - */ + const length = input.length - 1; + const scanToEnd = opts.parts === true || opts.scanToEnd === true; + const slashes = []; + const tokens = []; + const parts = []; -exports.flatten = (...args) => { - const result = []; - const flat = arr => { - for (let i = 0; i < arr.length; i++) { - let ele = arr[i]; - Array.isArray(ele) ? flat(ele, result) : ele !== void 0 && result.push(ele); - } - return result; + let str = input; + let index = -1; + let start = 0; + let lastIndex = 0; + let isBrace = false; + let isBracket = false; + let isGlob = false; + let isExtglob = false; + let isGlobstar = false; + let braceEscaped = false; + let backslashes = false; + let negated = false; + let finished = false; + let braces = 0; + let prev; + let code; + let token = { value: '', depth: 0, isGlob: false }; + + const eos = () => index >= length; + const peek = () => str.charCodeAt(index + 1); + const advance = () => { + prev = code; + return str.charCodeAt(++index); }; - flat(args); - return result; -}; + while (index < length) { + code = advance(); + let next; -/***/ }), -/* 307 */ -/***/ (function(module, exports, __webpack_require__) { + if (code === CHAR_BACKWARD_SLASH) { + backslashes = token.backslashes = true; + code = advance(); -"use strict"; + if (code === CHAR_LEFT_CURLY_BRACE) { + braceEscaped = true; + } + continue; + } + if (braceEscaped === true || code === CHAR_LEFT_CURLY_BRACE) { + braces++; -const fill = __webpack_require__(308); -const utils = __webpack_require__(306); + while (eos() !== true && (code = advance())) { + if (code === CHAR_BACKWARD_SLASH) { + backslashes = token.backslashes = true; + advance(); + continue; + } -const compile = (ast, options = {}) => { - let walk = (node, parent = {}) => { - let invalidBlock = utils.isInvalidBrace(parent); - let invalidNode = node.invalid === true && options.escapeInvalid === true; - let invalid = invalidBlock === true || invalidNode === true; - let prefix = options.escapeInvalid === true ? '\\' : ''; - let output = ''; + if (code === CHAR_LEFT_CURLY_BRACE) { + braces++; + continue; + } - if (node.isOpen === true) { - return prefix + node.value; - } - if (node.isClose === true) { - return prefix + node.value; - } + if (braceEscaped !== true && code === CHAR_DOT && (code = advance()) === CHAR_DOT) { + isBrace = token.isBrace = true; + isGlob = token.isGlob = true; + finished = true; - if (node.type === 'open') { - return invalid ? (prefix + node.value) : '('; - } + if (scanToEnd === true) { + continue; + } - if (node.type === 'close') { - return invalid ? (prefix + node.value) : ')'; - } + break; + } - if (node.type === 'comma') { - return node.prev.type === 'comma' ? '' : (invalid ? node.value : '|'); - } + if (braceEscaped !== true && code === CHAR_COMMA) { + isBrace = token.isBrace = true; + isGlob = token.isGlob = true; + finished = true; - if (node.value) { - return node.value; - } + if (scanToEnd === true) { + continue; + } - if (node.nodes && node.ranges > 0) { - let args = utils.reduce(node.nodes); - let range = fill(...args, { ...options, wrap: false, toRegex: true }); + break; + } - if (range.length !== 0) { - return args.length > 1 && range.length > 1 ? `(${range})` : range; + if (code === CHAR_RIGHT_CURLY_BRACE) { + braces--; + + if (braces === 0) { + braceEscaped = false; + isBrace = token.isBrace = true; + finished = true; + break; + } + } } - } - if (node.nodes) { - for (let child of node.nodes) { - output += walk(child, node); + if (scanToEnd === true) { + continue; } - } - return output; - }; - return walk(ast); -}; + break; + } -module.exports = compile; + if (code === CHAR_FORWARD_SLASH) { + slashes.push(index); + tokens.push(token); + token = { value: '', depth: 0, isGlob: false }; + if (finished === true) continue; + if (prev === CHAR_DOT && index === (start + 1)) { + start += 2; + continue; + } -/***/ }), -/* 308 */ -/***/ (function(module, exports, __webpack_require__) { + lastIndex = index + 1; + continue; + } -"use strict"; -/*! - * fill-range - * - * Copyright (c) 2014-present, Jon Schlinkert. - * Licensed under the MIT License. - */ + if (opts.noext !== true) { + const isExtglobChar = code === CHAR_PLUS + || code === CHAR_AT + || code === CHAR_ASTERISK + || code === CHAR_QUESTION_MARK + || code === CHAR_EXCLAMATION_MARK; + if (isExtglobChar === true && peek() === CHAR_LEFT_PARENTHESES) { + isGlob = token.isGlob = true; + isExtglob = token.isExtglob = true; + finished = true; + if (scanToEnd === true) { + while (eos() !== true && (code = advance())) { + if (code === CHAR_BACKWARD_SLASH) { + backslashes = token.backslashes = true; + code = advance(); + continue; + } -const util = __webpack_require__(111); -const toRegexRange = __webpack_require__(309); + if (code === CHAR_RIGHT_PARENTHESES) { + isGlob = token.isGlob = true; + finished = true; + break; + } + } + continue; + } + break; + } + } -const isObject = val => val !== null && typeof val === 'object' && !Array.isArray(val); + if (code === CHAR_ASTERISK) { + if (prev === CHAR_ASTERISK) isGlobstar = token.isGlobstar = true; + isGlob = token.isGlob = true; + finished = true; -const transform = toNumber => { - return value => toNumber === true ? Number(value) : String(value); -}; + if (scanToEnd === true) { + continue; + } + break; + } -const isValidValue = value => { - return typeof value === 'number' || (typeof value === 'string' && value !== ''); -}; + if (code === CHAR_QUESTION_MARK) { + isGlob = token.isGlob = true; + finished = true; -const isNumber = num => Number.isInteger(+num); + if (scanToEnd === true) { + continue; + } + break; + } -const zeros = input => { - let value = `${input}`; - let index = -1; - if (value[0] === '-') value = value.slice(1); - if (value === '0') return false; - while (value[++index] === '0'); - return index > 0; -}; + if (code === CHAR_LEFT_SQUARE_BRACKET) { + while (eos() !== true && (next = advance())) { + if (next === CHAR_BACKWARD_SLASH) { + backslashes = token.backslashes = true; + advance(); + continue; + } -const stringify = (start, end, options) => { - if (typeof start === 'string' || typeof end === 'string') { - return true; - } - return options.stringify === true; -}; + if (next === CHAR_RIGHT_SQUARE_BRACKET) { + isBracket = token.isBracket = true; + isGlob = token.isGlob = true; + finished = true; -const pad = (input, maxLength, toNumber) => { - if (maxLength > 0) { - let dash = input[0] === '-' ? '-' : ''; - if (dash) input = input.slice(1); - input = (dash + input.padStart(dash ? maxLength - 1 : maxLength, '0')); - } - if (toNumber === false) { - return String(input); - } - return input; -}; + if (scanToEnd === true) { + continue; + } + break; + } + } + } -const toMaxLen = (input, maxLength) => { - let negative = input[0] === '-' ? '-' : ''; - if (negative) { - input = input.slice(1); - maxLength--; - } - while (input.length < maxLength) input = '0' + input; - return negative ? ('-' + input) : input; -}; + if (opts.nonegate !== true && code === CHAR_EXCLAMATION_MARK && index === start) { + negated = token.negated = true; + start++; + continue; + } -const toSequence = (parts, options) => { - parts.negatives.sort((a, b) => a < b ? -1 : a > b ? 1 : 0); - parts.positives.sort((a, b) => a < b ? -1 : a > b ? 1 : 0); + if (opts.noparen !== true && code === CHAR_LEFT_PARENTHESES) { + isGlob = token.isGlob = true; - let prefix = options.capture ? '' : '?:'; - let positives = ''; - let negatives = ''; - let result; + if (scanToEnd === true) { + while (eos() !== true && (code = advance())) { + if (code === CHAR_LEFT_PARENTHESES) { + backslashes = token.backslashes = true; + code = advance(); + continue; + } - if (parts.positives.length) { - positives = parts.positives.join('|'); - } + if (code === CHAR_RIGHT_PARENTHESES) { + finished = true; + break; + } + } + continue; + } + break; + } - if (parts.negatives.length) { - negatives = `-(${prefix}${parts.negatives.join('|')})`; - } + if (isGlob === true) { + finished = true; - if (positives && negatives) { - result = `${positives}|${negatives}`; - } else { - result = positives || negatives; - } + if (scanToEnd === true) { + continue; + } - if (options.wrap) { - return `(${prefix}${result})`; + break; + } } - return result; -}; - -const toRange = (a, b, isNumbers, options) => { - if (isNumbers) { - return toRegexRange(a, b, { wrap: false, ...options }); + if (opts.noext === true) { + isExtglob = false; + isGlob = false; } - let start = String.fromCharCode(a); - if (a === b) return start; - - let stop = String.fromCharCode(b); - return `[${start}-${stop}]`; -}; + let base = str; + let prefix = ''; + let glob = ''; -const toRegex = (start, end, options) => { - if (Array.isArray(start)) { - let wrap = options.wrap === true; - let prefix = options.capture ? '' : '?:'; - return wrap ? `(${prefix}${start.join('|')})` : start.join('|'); + if (start > 0) { + prefix = str.slice(0, start); + str = str.slice(start); + lastIndex -= start; } - return toRegexRange(start, end, options); -}; - -const rangeError = (...args) => { - return new RangeError('Invalid range arguments: ' + util.inspect(...args)); -}; -const invalidRange = (start, end, options) => { - if (options.strictRanges === true) throw rangeError([start, end]); - return []; -}; + if (base && isGlob === true && lastIndex > 0) { + base = str.slice(0, lastIndex); + glob = str.slice(lastIndex); + } else if (isGlob === true) { + base = ''; + glob = str; + } else { + base = str; + } -const invalidStep = (step, options) => { - if (options.strictRanges === true) { - throw new TypeError(`Expected step "${step}" to be a number`); + if (base && base !== '' && base !== '/' && base !== str) { + if (isPathSeparator(base.charCodeAt(base.length - 1))) { + base = base.slice(0, -1); + } } - return []; -}; -const fillNumbers = (start, end, step = 1, options = {}) => { - let a = Number(start); - let b = Number(end); + if (opts.unescape === true) { + if (glob) glob = utils.removeBackslashes(glob); - if (!Number.isInteger(a) || !Number.isInteger(b)) { - if (options.strictRanges === true) throw rangeError([start, end]); - return []; + if (base && backslashes === true) { + base = utils.removeBackslashes(base); + } } - // fix negative zero - if (a === 0) a = 0; - if (b === 0) b = 0; + const state = { + prefix, + input, + start, + base, + glob, + isBrace, + isBracket, + isGlob, + isExtglob, + isGlobstar, + negated + }; - let descending = a > b; - let startString = String(start); - let endString = String(end); - let stepString = String(step); - step = Math.max(Math.abs(step), 1); + if (opts.tokens === true) { + state.maxDepth = 0; + if (!isPathSeparator(code)) { + tokens.push(token); + } + state.tokens = tokens; + } - let padded = zeros(startString) || zeros(endString) || zeros(stepString); - let maxLen = padded ? Math.max(startString.length, endString.length, stepString.length) : 0; - let toNumber = padded === false && stringify(start, end, options) === false; - let format = options.transform || transform(toNumber); + if (opts.parts === true || opts.tokens === true) { + let prevIndex; - if (options.toRegex && step === 1) { - return toRange(toMaxLen(start, maxLen), toMaxLen(end, maxLen), true, options); - } + for (let idx = 0; idx < slashes.length; idx++) { + const n = prevIndex ? prevIndex + 1 : start; + const i = slashes[idx]; + const value = input.slice(n, i); + if (opts.tokens) { + if (idx === 0 && start !== 0) { + tokens[idx].isPrefix = true; + tokens[idx].value = prefix; + } else { + tokens[idx].value = value; + } + depth(tokens[idx]); + state.maxDepth += tokens[idx].depth; + } + if (idx !== 0 || value !== '') { + parts.push(value); + } + prevIndex = i; + } - let parts = { negatives: [], positives: [] }; - let push = num => parts[num < 0 ? 'negatives' : 'positives'].push(Math.abs(num)); - let range = []; - let index = 0; + if (prevIndex && prevIndex + 1 < input.length) { + const value = input.slice(prevIndex + 1); + parts.push(value); - while (descending ? a >= b : a <= b) { - if (options.toRegex === true && step > 1) { - push(a); - } else { - range.push(pad(format(a, index), maxLen, toNumber)); + if (opts.tokens) { + tokens[tokens.length - 1].value = value; + depth(tokens[tokens.length - 1]); + state.maxDepth += tokens[tokens.length - 1].depth; + } } - a = descending ? a - step : a + step; - index++; - } - if (options.toRegex === true) { - return step > 1 - ? toSequence(parts, options) - : toRegex(range, null, { wrap: false, ...options }); + state.slashes = slashes; + state.parts = parts; } - return range; + return state; }; -const fillLetters = (start, end, step = 1, options = {}) => { - if ((!isNumber(start) && start.length > 1) || (!isNumber(end) && end.length > 1)) { - return invalidRange(start, end, options); - } - +module.exports = scan; - let format = options.transform || (val => String.fromCharCode(val)); - let a = `${start}`.charCodeAt(0); - let b = `${end}`.charCodeAt(0); - let descending = a > b; - let min = Math.min(a, b); - let max = Math.max(a, b); +/***/ }), +/* 310 */ +/***/ (function(module, exports, __webpack_require__) { - if (options.toRegex && step === 1) { - return toRange(min, max, false, options); - } +"use strict"; - let range = []; - let index = 0; - while (descending ? a >= b : a <= b) { - range.push(format(a, index)); - a = descending ? a - step : a + step; - index++; - } +const path = __webpack_require__(4); +const win32 = process.platform === 'win32'; +const { + REGEX_BACKSLASH, + REGEX_REMOVE_BACKSLASH, + REGEX_SPECIAL_CHARS, + REGEX_SPECIAL_CHARS_GLOBAL +} = __webpack_require__(311); - if (options.toRegex === true) { - return toRegex(range, null, { wrap: false, options }); - } +exports.isObject = val => val !== null && typeof val === 'object' && !Array.isArray(val); +exports.hasRegexChars = str => REGEX_SPECIAL_CHARS.test(str); +exports.isRegexChar = str => str.length === 1 && exports.hasRegexChars(str); +exports.escapeRegex = str => str.replace(REGEX_SPECIAL_CHARS_GLOBAL, '\\$1'); +exports.toPosixSlashes = str => str.replace(REGEX_BACKSLASH, '/'); - return range; +exports.removeBackslashes = str => { + return str.replace(REGEX_REMOVE_BACKSLASH, match => { + return match === '\\' ? '' : match; + }); }; -const fill = (start, end, step, options = {}) => { - if (end == null && isValidValue(start)) { - return [start]; +exports.supportsLookbehinds = () => { + const segs = process.version.slice(1).split('.').map(Number); + if (segs.length === 3 && segs[0] >= 9 || (segs[0] === 8 && segs[1] >= 10)) { + return true; } + return false; +}; - if (!isValidValue(start) || !isValidValue(end)) { - return invalidRange(start, end, options); +exports.isWindows = options => { + if (options && typeof options.windows === 'boolean') { + return options.windows; } + return win32 === true || path.sep === '\\'; +}; - if (typeof step === 'function') { - return fill(start, end, 1, { transform: step }); - } +exports.escapeLast = (input, char, lastIdx) => { + const idx = input.lastIndexOf(char, lastIdx); + if (idx === -1) return input; + if (input[idx - 1] === '\\') return exports.escapeLast(input, char, idx - 1); + return `${input.slice(0, idx)}\\${input.slice(idx)}`; +}; - if (isObject(step)) { - return fill(start, end, 0, step); +exports.removePrefix = (input, state = {}) => { + let output = input; + if (output.startsWith('./')) { + output = output.slice(2); + state.prefix = './'; } + return output; +}; - let opts = { ...options }; - if (opts.capture === true) opts.wrap = true; - step = step || opts.step || 1; - - if (!isNumber(step)) { - if (step != null && !isObject(step)) return invalidStep(step, opts); - return fill(start, end, 1, step); - } +exports.wrapOutput = (input, state = {}, options = {}) => { + const prepend = options.contains ? '' : '^'; + const append = options.contains ? '' : '$'; - if (isNumber(start) && isNumber(end)) { - return fillNumbers(start, end, step, opts); + let output = `${prepend}(?:${input})${append}`; + if (state.negated === true) { + output = `(?:^(?!${output}).*$)`; } - - return fillLetters(start, end, Math.max(Math.abs(step), 1), opts); + return output; }; -module.exports = fill; - /***/ }), -/* 309 */ +/* 311 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -/*! - * to-regex-range - * - * Copyright (c) 2015-present, Jon Schlinkert. - * Released under the MIT License. - */ +const path = __webpack_require__(4); +const WIN_SLASH = '\\\\/'; +const WIN_NO_SLASH = `[^${WIN_SLASH}]`; -const isNumber = __webpack_require__(310); +/** + * Posix glob regex + */ -const toRegexRange = (min, max, options) => { - if (isNumber(min) === false) { - throw new TypeError('toRegexRange: expected the first argument to be a number'); - } +const DOT_LITERAL = '\\.'; +const PLUS_LITERAL = '\\+'; +const QMARK_LITERAL = '\\?'; +const SLASH_LITERAL = '\\/'; +const ONE_CHAR = '(?=.)'; +const QMARK = '[^/]'; +const END_ANCHOR = `(?:${SLASH_LITERAL}|$)`; +const START_ANCHOR = `(?:^|${SLASH_LITERAL})`; +const DOTS_SLASH = `${DOT_LITERAL}{1,2}${END_ANCHOR}`; +const NO_DOT = `(?!${DOT_LITERAL})`; +const NO_DOTS = `(?!${START_ANCHOR}${DOTS_SLASH})`; +const NO_DOT_SLASH = `(?!${DOT_LITERAL}{0,1}${END_ANCHOR})`; +const NO_DOTS_SLASH = `(?!${DOTS_SLASH})`; +const QMARK_NO_DOT = `[^.${SLASH_LITERAL}]`; +const STAR = `${QMARK}*?`; - if (max === void 0 || min === max) { - return String(min); - } +const POSIX_CHARS = { + DOT_LITERAL, + PLUS_LITERAL, + QMARK_LITERAL, + SLASH_LITERAL, + ONE_CHAR, + QMARK, + END_ANCHOR, + DOTS_SLASH, + NO_DOT, + NO_DOTS, + NO_DOT_SLASH, + NO_DOTS_SLASH, + QMARK_NO_DOT, + STAR, + START_ANCHOR +}; - if (isNumber(max) === false) { - throw new TypeError('toRegexRange: expected the second argument to be a number.'); - } +/** + * Windows glob regex + */ - let opts = { relaxZeros: true, ...options }; - if (typeof opts.strictZeros === 'boolean') { - opts.relaxZeros = opts.strictZeros === false; - } +const WINDOWS_CHARS = { + ...POSIX_CHARS, - let relax = String(opts.relaxZeros); - let shorthand = String(opts.shorthand); - let capture = String(opts.capture); - let wrap = String(opts.wrap); - let cacheKey = min + ':' + max + '=' + relax + shorthand + capture + wrap; + SLASH_LITERAL: `[${WIN_SLASH}]`, + QMARK: WIN_NO_SLASH, + STAR: `${WIN_NO_SLASH}*?`, + DOTS_SLASH: `${DOT_LITERAL}{1,2}(?:[${WIN_SLASH}]|$)`, + NO_DOT: `(?!${DOT_LITERAL})`, + NO_DOTS: `(?!(?:^|[${WIN_SLASH}])${DOT_LITERAL}{1,2}(?:[${WIN_SLASH}]|$))`, + NO_DOT_SLASH: `(?!${DOT_LITERAL}{0,1}(?:[${WIN_SLASH}]|$))`, + NO_DOTS_SLASH: `(?!${DOT_LITERAL}{1,2}(?:[${WIN_SLASH}]|$))`, + QMARK_NO_DOT: `[^.${WIN_SLASH}]`, + START_ANCHOR: `(?:^|[${WIN_SLASH}])`, + END_ANCHOR: `(?:[${WIN_SLASH}]|$)` +}; - if (toRegexRange.cache.hasOwnProperty(cacheKey)) { - return toRegexRange.cache[cacheKey].result; - } +/** + * POSIX Bracket Regex + */ - let a = Math.min(min, max); - let b = Math.max(min, max); +const POSIX_REGEX_SOURCE = { + alnum: 'a-zA-Z0-9', + alpha: 'a-zA-Z', + ascii: '\\x00-\\x7F', + blank: ' \\t', + cntrl: '\\x00-\\x1F\\x7F', + digit: '0-9', + graph: '\\x21-\\x7E', + lower: 'a-z', + print: '\\x20-\\x7E ', + punct: '\\-!"#$%&\'()\\*+,./:;<=>?@[\\]^_`{|}~', + space: ' \\t\\r\\n\\v\\f', + upper: 'A-Z', + word: 'A-Za-z0-9_', + xdigit: 'A-Fa-f0-9' +}; - if (Math.abs(a - b) === 1) { - let result = min + '|' + max; - if (opts.capture) { - return `(${result})`; - } - if (opts.wrap === false) { - return result; - } - return `(?:${result})`; - } +module.exports = { + MAX_LENGTH: 1024 * 64, + POSIX_REGEX_SOURCE, - let isPadded = hasPadding(min) || hasPadding(max); - let state = { min, max, a, b }; - let positives = []; - let negatives = []; + // regular expressions + REGEX_BACKSLASH: /\\(?![*+?^${}(|)[\]])/g, + REGEX_NON_SPECIAL_CHARS: /^[^@![\].,$*+?^{}()|\\/]+/, + REGEX_SPECIAL_CHARS: /[-*+?.^${}(|)[\]]/, + REGEX_SPECIAL_CHARS_BACKREF: /(\\?)((\W)(\3*))/g, + REGEX_SPECIAL_CHARS_GLOBAL: /([-*+?.^${}(|)[\]])/g, + REGEX_REMOVE_BACKSLASH: /(?:\[.*?[^\\]\]|\\(?=.))/g, - if (isPadded) { - state.isPadded = isPadded; - state.maxLen = String(state.max).length; - } + // Replace globs with equivalent patterns to reduce parsing time. + REPLACEMENTS: { + '***': '*', + '**/**': '**', + '**/**/**': '**' + }, - if (a < 0) { - let newMin = b < 0 ? Math.abs(b) : 1; - negatives = splitToPatterns(newMin, Math.abs(a), state, opts); - a = state.a = 0; - } + // Digits + CHAR_0: 48, /* 0 */ + CHAR_9: 57, /* 9 */ - if (b >= 0) { - positives = splitToPatterns(a, b, state, opts); - } + // Alphabet chars. + CHAR_UPPERCASE_A: 65, /* A */ + CHAR_LOWERCASE_A: 97, /* a */ + CHAR_UPPERCASE_Z: 90, /* Z */ + CHAR_LOWERCASE_Z: 122, /* z */ - state.negatives = negatives; - state.positives = positives; - state.result = collatePatterns(negatives, positives, opts); - - if (opts.capture === true) { - state.result = `(${state.result})`; - } else if (opts.wrap !== false && (positives.length + negatives.length) > 1) { - state.result = `(?:${state.result})`; - } + CHAR_LEFT_PARENTHESES: 40, /* ( */ + CHAR_RIGHT_PARENTHESES: 41, /* ) */ - toRegexRange.cache[cacheKey] = state; - return state.result; -}; + CHAR_ASTERISK: 42, /* * */ -function collatePatterns(neg, pos, options) { - let onlyNegative = filterPatterns(neg, pos, '-', false, options) || []; - let onlyPositive = filterPatterns(pos, neg, '', false, options) || []; - let intersected = filterPatterns(neg, pos, '-?', true, options) || []; - let subpatterns = onlyNegative.concat(intersected).concat(onlyPositive); - return subpatterns.join('|'); -} + // Non-alphabetic chars. + CHAR_AMPERSAND: 38, /* & */ + CHAR_AT: 64, /* @ */ + CHAR_BACKWARD_SLASH: 92, /* \ */ + CHAR_CARRIAGE_RETURN: 13, /* \r */ + CHAR_CIRCUMFLEX_ACCENT: 94, /* ^ */ + CHAR_COLON: 58, /* : */ + CHAR_COMMA: 44, /* , */ + CHAR_DOT: 46, /* . */ + CHAR_DOUBLE_QUOTE: 34, /* " */ + CHAR_EQUAL: 61, /* = */ + CHAR_EXCLAMATION_MARK: 33, /* ! */ + CHAR_FORM_FEED: 12, /* \f */ + CHAR_FORWARD_SLASH: 47, /* / */ + CHAR_GRAVE_ACCENT: 96, /* ` */ + CHAR_HASH: 35, /* # */ + CHAR_HYPHEN_MINUS: 45, /* - */ + CHAR_LEFT_ANGLE_BRACKET: 60, /* < */ + CHAR_LEFT_CURLY_BRACE: 123, /* { */ + CHAR_LEFT_SQUARE_BRACKET: 91, /* [ */ + CHAR_LINE_FEED: 10, /* \n */ + CHAR_NO_BREAK_SPACE: 160, /* \u00A0 */ + CHAR_PERCENT: 37, /* % */ + CHAR_PLUS: 43, /* + */ + CHAR_QUESTION_MARK: 63, /* ? */ + CHAR_RIGHT_ANGLE_BRACKET: 62, /* > */ + CHAR_RIGHT_CURLY_BRACE: 125, /* } */ + CHAR_RIGHT_SQUARE_BRACKET: 93, /* ] */ + CHAR_SEMICOLON: 59, /* ; */ + CHAR_SINGLE_QUOTE: 39, /* ' */ + CHAR_SPACE: 32, /* */ + CHAR_TAB: 9, /* \t */ + CHAR_UNDERSCORE: 95, /* _ */ + CHAR_VERTICAL_LINE: 124, /* | */ + CHAR_ZERO_WIDTH_NOBREAK_SPACE: 65279, /* \uFEFF */ -function splitToRanges(min, max) { - let nines = 1; - let zeros = 1; + SEP: path.sep, - let stop = countNines(min, nines); - let stops = new Set([max]); + /** + * Create EXTGLOB_CHARS + */ - while (min <= stop && stop <= max) { - stops.add(stop); - nines += 1; - stop = countNines(min, nines); - } + extglobChars(chars) { + return { + '!': { type: 'negate', open: '(?:(?!(?:', close: `))${chars.STAR})` }, + '?': { type: 'qmark', open: '(?:', close: ')?' }, + '+': { type: 'plus', open: '(?:', close: ')+' }, + '*': { type: 'star', open: '(?:', close: ')*' }, + '@': { type: 'at', open: '(?:', close: ')' } + }; + }, - stop = countZeros(max + 1, zeros) - 1; + /** + * Create GLOB_CHARS + */ - while (min < stop && stop <= max) { - stops.add(stop); - zeros += 1; - stop = countZeros(max + 1, zeros) - 1; + globChars(win32) { + return win32 === true ? WINDOWS_CHARS : POSIX_CHARS; } +}; - stops = [...stops]; - stops.sort(compare); - return stops; -} -/** - * Convert a range to a regex pattern - * @param {Number} `start` - * @param {Number} `stop` - * @return {String} - */ +/***/ }), +/* 312 */ +/***/ (function(module, exports, __webpack_require__) { -function rangeToPattern(start, stop, options) { - if (start === stop) { - return { pattern: start, count: [], digits: 0 }; - } +"use strict"; - let zipped = zip(start, stop); - let digits = zipped.length; - let pattern = ''; - let count = 0; - for (let i = 0; i < digits; i++) { - let [startDigit, stopDigit] = zipped[i]; +const constants = __webpack_require__(311); +const utils = __webpack_require__(310); - if (startDigit === stopDigit) { - pattern += startDigit; +/** + * Constants + */ - } else if (startDigit !== '0' || stopDigit !== '9') { - pattern += toCharacterClass(startDigit, stopDigit, options); +const { + MAX_LENGTH, + POSIX_REGEX_SOURCE, + REGEX_NON_SPECIAL_CHARS, + REGEX_SPECIAL_CHARS_BACKREF, + REPLACEMENTS +} = constants; - } else { - count++; - } - } +/** + * Helpers + */ - if (count) { - pattern += options.shorthand === true ? '\\d' : '[0-9]'; +const expandRange = (args, options) => { + if (typeof options.expandRange === 'function') { + return options.expandRange(...args, options); } - return { pattern, count: [count], digits }; -} + args.sort(); + const value = `[${args.join('-')}]`; -function splitToPatterns(min, max, tok, options) { - let ranges = splitToRanges(min, max); - let tokens = []; - let start = min; - let prev; + try { + /* eslint-disable-next-line no-new */ + new RegExp(value); + } catch (ex) { + return args.map(v => utils.escapeRegex(v)).join('..'); + } - for (let i = 0; i < ranges.length; i++) { - let max = ranges[i]; - let obj = rangeToPattern(String(start), String(max), options); - let zeros = ''; + return value; +}; - if (!tok.isPadded && prev && prev.pattern === obj.pattern) { - if (prev.count.length > 1) { - prev.count.pop(); - } +/** + * Create the message for a syntax error + */ - prev.count.push(obj.count[0]); - prev.string = prev.pattern + toQuantifier(prev.count); - start = max + 1; - continue; - } +const syntaxError = (type, char) => { + return `Missing ${type}: "${char}" - use "\\\\${char}" to match literal characters`; +}; - if (tok.isPadded) { - zeros = padZeros(max, tok, options); - } +/** + * Parse the given input string. + * @param {String} input + * @param {Object} options + * @return {Object} + */ - obj.string = zeros + obj.pattern + toQuantifier(obj.count); - tokens.push(obj); - start = max + 1; - prev = obj; +const parse = (input, options) => { + if (typeof input !== 'string') { + throw new TypeError('Expected a string'); } - return tokens; -} - -function filterPatterns(arr, comparison, prefix, intersection, options) { - let result = []; - - for (let ele of arr) { - let { string } = ele; + input = REPLACEMENTS[input] || input; - // only push if _both_ are negative... - if (!intersection && !contains(comparison, 'string', string)) { - result.push(prefix + string); - } + const opts = { ...options }; + const max = typeof opts.maxLength === 'number' ? Math.min(MAX_LENGTH, opts.maxLength) : MAX_LENGTH; - // or _both_ are positive - if (intersection && contains(comparison, 'string', string)) { - result.push(prefix + string); - } + let len = input.length; + if (len > max) { + throw new SyntaxError(`Input length: ${len}, exceeds maximum allowed length: ${max}`); } - return result; -} -/** - * Zip strings - */ + const bos = { type: 'bos', value: '', output: opts.prepend || '' }; + const tokens = [bos]; -function zip(a, b) { - let arr = []; - for (let i = 0; i < a.length; i++) arr.push([a[i], b[i]]); - return arr; -} + const capture = opts.capture ? '' : '?:'; + const win32 = utils.isWindows(options); -function compare(a, b) { - return a > b ? 1 : b > a ? -1 : 0; -} + // create constants based on platform, for windows or posix + const PLATFORM_CHARS = constants.globChars(win32); + const EXTGLOB_CHARS = constants.extglobChars(PLATFORM_CHARS); -function contains(arr, key, val) { - return arr.some(ele => ele[key] === val); -} + const { + DOT_LITERAL, + PLUS_LITERAL, + SLASH_LITERAL, + ONE_CHAR, + DOTS_SLASH, + NO_DOT, + NO_DOT_SLASH, + NO_DOTS_SLASH, + QMARK, + QMARK_NO_DOT, + STAR, + START_ANCHOR + } = PLATFORM_CHARS; -function countNines(min, len) { - return Number(String(min).slice(0, -len) + '9'.repeat(len)); -} + const globstar = (opts) => { + return `(${capture}(?:(?!${START_ANCHOR}${opts.dot ? DOTS_SLASH : DOT_LITERAL}).)*?)`; + }; -function countZeros(integer, zeros) { - return integer - (integer % Math.pow(10, zeros)); -} + const nodot = opts.dot ? '' : NO_DOT; + const qmarkNoDot = opts.dot ? QMARK : QMARK_NO_DOT; + let star = opts.bash === true ? globstar(opts) : STAR; -function toQuantifier(digits) { - let [start = 0, stop = ''] = digits; - if (stop || start > 1) { - return `{${start + (stop ? ',' + stop : '')}}`; + if (opts.capture) { + star = `(${star})`; } - return ''; -} - -function toCharacterClass(a, b, options) { - return `[${a}${(b - a === 1) ? '' : '-'}${b}]`; -} - -function hasPadding(str) { - return /^-?(0+)\d/.test(str); -} -function padZeros(value, tok, options) { - if (!tok.isPadded) { - return value; + // minimatch options support + if (typeof opts.noext === 'boolean') { + opts.noextglob = opts.noext; } - let diff = Math.abs(tok.maxLen - String(value).length); - let relax = options.relaxZeros !== false; + const state = { + input, + index: -1, + start: 0, + dot: opts.dot === true, + consumed: '', + output: '', + prefix: '', + backtrack: false, + negated: false, + brackets: 0, + braces: 0, + parens: 0, + quotes: 0, + globstar: false, + tokens + }; - switch (diff) { - case 0: - return ''; - case 1: - return relax ? '0?' : '0'; - case 2: - return relax ? '0{0,2}' : '00'; - default: { - return relax ? `0{0,${diff}}` : `0{${diff}}`; - } - } -} + input = utils.removePrefix(input, state); + len = input.length; -/** - * Cache - */ + const extglobs = []; + const braces = []; + const stack = []; + let prev = bos; + let value; -toRegexRange.cache = {}; -toRegexRange.clearCache = () => (toRegexRange.cache = {}); + /** + * Tokenizing helpers + */ -/** - * Expose `toRegexRange` - */ + const eos = () => state.index === len - 1; + const peek = state.peek = (n = 1) => input[state.index + n]; + const advance = state.advance = () => input[++state.index]; + const remaining = () => input.slice(state.index + 1); + const consume = (value = '', num = 0) => { + state.consumed += value; + state.index += num; + }; + const append = token => { + state.output += token.output != null ? token.output : token.value; + consume(token.value); + }; -module.exports = toRegexRange; + const negate = () => { + let count = 1; + while (peek() === '!' && (peek(2) !== '(' || peek(3) === '?')) { + advance(); + state.start++; + count++; + } -/***/ }), -/* 310 */ -/***/ (function(module, exports, __webpack_require__) { + if (count % 2 === 0) { + return false; + } -"use strict"; -/*! - * is-number - * - * Copyright (c) 2014-present, Jon Schlinkert. - * Released under the MIT License. - */ + state.negated = true; + state.start++; + return true; + }; + const increment = type => { + state[type]++; + stack.push(type); + }; + const decrement = type => { + state[type]--; + stack.pop(); + }; -module.exports = function(num) { - if (typeof num === 'number') { - return num - num === 0; - } - if (typeof num === 'string' && num.trim() !== '') { - return Number.isFinite ? Number.isFinite(+num) : isFinite(+num); - } - return false; -}; + /** + * Push tokens onto the tokens array. This helper speeds up + * tokenizing by 1) helping us avoid backtracking as much as possible, + * and 2) helping us avoid creating extra tokens when consecutive + * characters are plain text. This improves performance and simplifies + * lookbehinds. + */ + const push = tok => { + if (prev.type === 'globstar') { + const isBrace = state.braces > 0 && (tok.type === 'comma' || tok.type === 'brace'); + const isExtglob = tok.extglob === true || (extglobs.length && (tok.type === 'pipe' || tok.type === 'paren')); -/***/ }), -/* 311 */ -/***/ (function(module, exports, __webpack_require__) { + if (tok.type !== 'slash' && tok.type !== 'paren' && !isBrace && !isExtglob) { + state.output = state.output.slice(0, -prev.output.length); + prev.type = 'star'; + prev.value = '*'; + prev.output = star; + state.output += prev.output; + } + } -"use strict"; + if (extglobs.length && tok.type !== 'paren' && !EXTGLOB_CHARS[tok.value]) { + extglobs[extglobs.length - 1].inner += tok.value; + } + if (tok.value || tok.output) append(tok); + if (prev && prev.type === 'text' && tok.type === 'text') { + prev.value += tok.value; + prev.output = (prev.output || '') + tok.value; + return; + } -const fill = __webpack_require__(308); -const stringify = __webpack_require__(305); -const utils = __webpack_require__(306); + tok.prev = prev; + tokens.push(tok); + prev = tok; + }; -const append = (queue = '', stash = '', enclose = false) => { - let result = []; + const extglobOpen = (type, value) => { + const token = { ...EXTGLOB_CHARS[value], conditions: 1, inner: '' }; - queue = [].concat(queue); - stash = [].concat(stash); + token.prev = prev; + token.parens = state.parens; + token.output = state.output; + const output = (opts.capture ? '(' : '') + token.open; - if (!stash.length) return queue; - if (!queue.length) { - return enclose ? utils.flatten(stash).map(ele => `{${ele}}`) : stash; - } + increment('parens'); + push({ type, value, output: state.output ? '' : ONE_CHAR }); + push({ type: 'paren', extglob: true, value: advance(), output }); + extglobs.push(token); + }; - for (let item of queue) { - if (Array.isArray(item)) { - for (let value of item) { - result.push(append(value, stash, enclose)); - } - } else { - for (let ele of stash) { - if (enclose === true && typeof ele === 'string') ele = `{${ele}}`; - result.push(Array.isArray(ele) ? append(item, ele, enclose) : (item + ele)); - } - } - } - return utils.flatten(result); -}; + const extglobClose = token => { + let output = token.close + (opts.capture ? ')' : ''); -const expand = (ast, options = {}) => { - let rangeLimit = options.rangeLimit === void 0 ? 1000 : options.rangeLimit; + if (token.type === 'negate') { + let extglobStar = star; - let walk = (node, parent = {}) => { - node.queue = []; + if (token.inner && token.inner.length > 1 && token.inner.includes('/')) { + extglobStar = globstar(opts); + } - let p = parent; - let q = parent.queue; + if (extglobStar !== star || eos() || /^\)+$/.test(remaining())) { + output = token.close = `)$))${extglobStar}`; + } - while (p.type !== 'brace' && p.type !== 'root' && p.parent) { - p = p.parent; - q = p.queue; + if (token.prev.type === 'bos' && eos()) { + state.negatedExtglob = true; + } } - if (node.invalid || node.dollar) { - q.push(append(q.pop(), stringify(node, options))); - return; - } + push({ type: 'paren', extglob: true, value, output }); + decrement('parens'); + }; - if (node.type === 'brace' && node.invalid !== true && node.nodes.length === 2) { - q.push(append(q.pop(), ['{}'])); - return; - } + /** + * Fast paths + */ - if (node.nodes && node.ranges > 0) { - let args = utils.reduce(node.nodes); + if (opts.fastpaths !== false && !/(^[*!]|[/()[\]{}"])/.test(input)) { + let backslashes = false; - if (utils.exceedsLimit(...args, options.step, rangeLimit)) { - throw new RangeError('expanded array length exceeds range limit. Use options.rangeLimit to increase or disable the limit.'); + let output = input.replace(REGEX_SPECIAL_CHARS_BACKREF, (m, esc, chars, first, rest, index) => { + if (first === '\\') { + backslashes = true; + return m; } - let range = fill(...args, options); - if (range.length === 0) { - range = stringify(node, options); + if (first === '?') { + if (esc) { + return esc + first + (rest ? QMARK.repeat(rest.length) : ''); + } + if (index === 0) { + return qmarkNoDot + (rest ? QMARK.repeat(rest.length) : ''); + } + return QMARK.repeat(chars.length); } - q.push(append(q.pop(), range)); - node.nodes = []; - return; - } - - let enclose = utils.encloseBrace(node); - let queue = node.queue; - let block = node; - - while (block.type !== 'brace' && block.type !== 'root' && block.parent) { - block = block.parent; - queue = block.queue; - } - - for (let i = 0; i < node.nodes.length; i++) { - let child = node.nodes[i]; - - if (child.type === 'comma' && node.type === 'brace') { - if (i === 1) queue.push(''); - queue.push(''); - continue; - } - - if (child.type === 'close') { - q.push(append(q.pop(), queue, enclose)); - continue; + if (first === '.') { + return DOT_LITERAL.repeat(chars.length); } - if (child.value && child.type !== 'open') { - queue.push(append(queue.pop(), child.value)); - continue; + if (first === '*') { + if (esc) { + return esc + first + (rest ? star : ''); + } + return star; } + return esc ? m : `\\${m}`; + }); - if (child.nodes) { - walk(child, node); + if (backslashes === true) { + if (opts.unescape === true) { + output = output.replace(/\\/g, ''); + } else { + output = output.replace(/\\+/g, m => { + return m.length % 2 === 0 ? '\\\\' : (m ? '\\' : ''); + }); } } - return queue; - }; + if (output === input && opts.contains === true) { + state.output = input; + return state; + } - return utils.flatten(walk(ast)); -}; + state.output = utils.wrapOutput(output, state, options); + return state; + } -module.exports = expand; + /** + * Tokenize input until we reach end-of-string + */ + while (!eos()) { + value = advance(); -/***/ }), -/* 312 */ -/***/ (function(module, exports, __webpack_require__) { + if (value === '\u0000') { + continue; + } -"use strict"; + /** + * Escaped characters + */ + if (value === '\\') { + const next = peek(); -const stringify = __webpack_require__(305); + if (next === '/' && opts.bash !== true) { + continue; + } -/** - * Constants - */ + if (next === '.' || next === ';') { + continue; + } -const { - MAX_LENGTH, - CHAR_BACKSLASH, /* \ */ - CHAR_BACKTICK, /* ` */ - CHAR_COMMA, /* , */ - CHAR_DOT, /* . */ - CHAR_LEFT_PARENTHESES, /* ( */ - CHAR_RIGHT_PARENTHESES, /* ) */ - CHAR_LEFT_CURLY_BRACE, /* { */ - CHAR_RIGHT_CURLY_BRACE, /* } */ - CHAR_LEFT_SQUARE_BRACKET, /* [ */ - CHAR_RIGHT_SQUARE_BRACKET, /* ] */ - CHAR_DOUBLE_QUOTE, /* " */ - CHAR_SINGLE_QUOTE, /* ' */ - CHAR_NO_BREAK_SPACE, - CHAR_ZERO_WIDTH_NOBREAK_SPACE -} = __webpack_require__(313); + if (!next) { + value += '\\'; + push({ type: 'text', value }); + continue; + } -/** - * parse - */ + // collapse slashes to reduce potential for exploits + const match = /^\\+/.exec(remaining()); + let slashes = 0; -const parse = (input, options = {}) => { - if (typeof input !== 'string') { - throw new TypeError('Expected a string'); - } + if (match && match[0].length > 2) { + slashes = match[0].length; + state.index += slashes; + if (slashes % 2 !== 0) { + value += '\\'; + } + } - let opts = options || {}; - let max = typeof opts.maxLength === 'number' ? Math.min(MAX_LENGTH, opts.maxLength) : MAX_LENGTH; - if (input.length > max) { - throw new SyntaxError(`Input length (${input.length}), exceeds max characters (${max})`); - } + if (opts.unescape === true) { + value = advance() || ''; + } else { + value += advance() || ''; + } - let ast = { type: 'root', input, nodes: [] }; - let stack = [ast]; - let block = ast; - let prev = ast; - let brackets = 0; - let length = input.length; - let index = 0; - let depth = 0; - let value; - let memo = {}; + if (state.brackets === 0) { + push({ type: 'text', value }); + continue; + } + } - /** - * Helpers - */ + /** + * If we're inside a regex character class, continue + * until we reach the closing bracket. + */ - const advance = () => input[index++]; - const push = node => { - if (node.type === 'text' && prev.type === 'dot') { - prev.type = 'text'; - } + if (state.brackets > 0 && (value !== ']' || prev.value === '[' || prev.value === '[^')) { + if (opts.posix !== false && value === ':') { + const inner = prev.value.slice(1); + if (inner.includes('[')) { + prev.posix = true; - if (prev && prev.type === 'text' && node.type === 'text') { - prev.value += node.value; - return; - } + if (inner.includes(':')) { + const idx = prev.value.lastIndexOf('['); + const pre = prev.value.slice(0, idx); + const rest = prev.value.slice(idx + 2); + const posix = POSIX_REGEX_SOURCE[rest]; + if (posix) { + prev.value = pre + posix; + state.backtrack = true; + advance(); - block.nodes.push(node); - node.parent = block; - node.prev = prev; - prev = node; - return node; - }; + if (!bos.output && tokens.indexOf(prev) === 1) { + bos.output = ONE_CHAR; + } + continue; + } + } + } + } - push({ type: 'bos' }); + if ((value === '[' && peek() !== ':') || (value === '-' && peek() === ']')) { + value = `\\${value}`; + } - while (index < length) { - block = stack[stack.length - 1]; - value = advance(); + if (value === ']' && (prev.value === '[' || prev.value === '[^')) { + value = `\\${value}`; + } - /** - * Invalid chars - */ + if (opts.posix === true && value === '!' && prev.value === '[') { + value = '^'; + } - if (value === CHAR_ZERO_WIDTH_NOBREAK_SPACE || value === CHAR_NO_BREAK_SPACE) { + prev.value += value; + append({ value }); continue; } /** - * Escaped chars + * If we're inside a quoted string, continue + * until we reach the closing double quote. */ - if (value === CHAR_BACKSLASH) { - push({ type: 'text', value: (options.keepEscaping ? value : '') + advance() }); + if (state.quotes === 1 && value !== '"') { + value = utils.escapeRegex(value); + prev.value += value; + append({ value }); continue; } /** - * Right square bracket (literal): ']' + * Double quotes */ - if (value === CHAR_RIGHT_SQUARE_BRACKET) { - push({ type: 'text', value: '\\' + value }); + if (value === '"') { + state.quotes = state.quotes === 1 ? 0 : 1; + if (opts.keepQuotes === true) { + push({ type: 'text', value }); + } continue; } /** - * Left square bracket: '[' + * Parentheses */ - if (value === CHAR_LEFT_SQUARE_BRACKET) { - brackets++; - - let closed = true; - let next; - - while (index < length && (next = advance())) { - value += next; - - if (next === CHAR_LEFT_SQUARE_BRACKET) { - brackets++; - continue; - } - - if (next === CHAR_BACKSLASH) { - value += advance(); - continue; - } + if (value === '(') { + increment('parens'); + push({ type: 'paren', value }); + continue; + } - if (next === CHAR_RIGHT_SQUARE_BRACKET) { - brackets--; + if (value === ')') { + if (state.parens === 0 && opts.strictBrackets === true) { + throw new SyntaxError(syntaxError('opening', '(')); + } - if (brackets === 0) { - break; - } - } + const extglob = extglobs[extglobs.length - 1]; + if (extglob && state.parens === extglob.parens + 1) { + extglobClose(extglobs.pop()); + continue; } - push({ type: 'text', value }); + push({ type: 'paren', value, output: state.parens ? ')' : '\\)' }); + decrement('parens'); continue; } /** - * Parentheses + * Square brackets */ - if (value === CHAR_LEFT_PARENTHESES) { - block = push({ type: 'paren', nodes: [] }); - stack.push(block); - push({ type: 'text', value }); + if (value === '[') { + if (opts.nobracket === true || !remaining().includes(']')) { + if (opts.nobracket !== true && opts.strictBrackets === true) { + throw new SyntaxError(syntaxError('closing', ']')); + } + + value = `\\${value}`; + } else { + increment('brackets'); + } + + push({ type: 'bracket', value }); continue; } - if (value === CHAR_RIGHT_PARENTHESES) { - if (block.type !== 'paren') { - push({ type: 'text', value }); + if (value === ']') { + if (opts.nobracket === true || (prev && prev.type === 'bracket' && prev.value.length === 1)) { + push({ type: 'text', value, output: `\\${value}` }); continue; } - block = stack.pop(); - push({ type: 'text', value }); - block = stack[stack.length - 1]; - continue; - } - /** - * Quotes: '|"|` - */ + if (state.brackets === 0) { + if (opts.strictBrackets === true) { + throw new SyntaxError(syntaxError('opening', '[')); + } - if (value === CHAR_DOUBLE_QUOTE || value === CHAR_SINGLE_QUOTE || value === CHAR_BACKTICK) { - let open = value; - let next; + push({ type: 'text', value, output: `\\${value}` }); + continue; + } - if (options.keepQuotes !== true) { - value = ''; + decrement('brackets'); + + const prevValue = prev.value.slice(1); + if (prev.posix !== true && prevValue[0] === '^' && !prevValue.includes('/')) { + value = `/${value}`; } - while (index < length && (next = advance())) { - if (next === CHAR_BACKSLASH) { - value += next + advance(); - continue; - } + prev.value += value; + append({ value }); - if (next === open) { - if (options.keepQuotes === true) value += next; - break; - } + // when literal brackets are explicitly disabled + // assume we should match with a regex character class + if (opts.literalBrackets === false || utils.hasRegexChars(prevValue)) { + continue; + } - value += next; + const escaped = utils.escapeRegex(prev.value); + state.output = state.output.slice(0, -prev.value.length); + + // when literal brackets are explicitly enabled + // assume we should escape the brackets to match literal characters + if (opts.literalBrackets === true) { + state.output += escaped; + prev.value = escaped; + continue; } - push({ type: 'text', value }); + // when the user specifies nothing, try to match both + prev.value = `(${capture}${escaped}|${prev.value})`; + state.output += prev.value; continue; } /** - * Left curly brace: '{' + * Braces */ - if (value === CHAR_LEFT_CURLY_BRACE) { - depth++; + if (value === '{' && opts.nobrace !== true) { + increment('braces'); - let dollar = prev.value && prev.value.slice(-1) === '$' || block.dollar === true; - let brace = { + const open = { type: 'brace', - open: true, - close: false, - dollar, - depth, - commas: 0, - ranges: 0, - nodes: [] + value, + output: '(', + outputIndex: state.output.length, + tokensIndex: state.tokens.length }; - block = push(brace); - stack.push(block); - push({ type: 'open', value }); + braces.push(open); + push(open); continue; } - /** - * Right curly brace: '}' - */ + if (value === '}') { + const brace = braces[braces.length - 1]; - if (value === CHAR_RIGHT_CURLY_BRACE) { - if (block.type !== 'brace') { - push({ type: 'text', value }); + if (opts.nobrace === true || !brace) { + push({ type: 'text', value, output: value }); continue; } - let type = 'close'; - block = stack.pop(); - block.close = true; + let output = ')'; - push({ type, value }); - depth--; + if (brace.dots === true) { + const arr = tokens.slice(); + const range = []; - block = stack[stack.length - 1]; + for (let i = arr.length - 1; i >= 0; i--) { + tokens.pop(); + if (arr[i].type === 'brace') { + break; + } + if (arr[i].type !== 'dots') { + range.unshift(arr[i].value); + } + } + + output = expandRange(range, opts); + state.backtrack = true; + } + + if (brace.comma !== true && brace.dots !== true) { + const out = state.output.slice(0, brace.outputIndex); + const toks = state.tokens.slice(brace.tokensIndex); + brace.value = brace.output = '\\{'; + value = output = '\\}'; + state.output = out; + for (const t of toks) { + state.output += (t.output || t.value); + } + } + + push({ type: 'brace', value, output }); + decrement('braces'); + braces.pop(); continue; } /** - * Comma: ',' + * Pipes */ - if (value === CHAR_COMMA && depth > 0) { - if (block.ranges > 0) { - block.ranges = 0; - let open = block.nodes.shift(); - block.nodes = [open, { type: 'text', value: stringify(block) }]; + if (value === '|') { + if (extglobs.length > 0) { + extglobs[extglobs.length - 1].conditions++; } - - push({ type: 'comma', value }); - block.commas++; + push({ type: 'text', value }); continue; } /** - * Dot: '.' + * Commas */ - if (value === CHAR_DOT && depth > 0 && block.commas === 0) { - let siblings = block.nodes; + if (value === ',') { + let output = value; - if (depth === 0 || siblings.length === 0) { - push({ type: 'text', value }); - continue; + const brace = braces[braces.length - 1]; + if (brace && stack[stack.length - 1] === 'braces') { + brace.comma = true; + output = '|'; } - if (prev.type === 'dot') { - block.range = []; - prev.value += value; - prev.type = 'range'; + push({ type: 'comma', value, output }); + continue; + } - if (block.nodes.length !== 3 && block.nodes.length !== 5) { - block.invalid = true; - block.ranges = 0; - prev.type = 'text'; - continue; - } + /** + * Slashes + */ - block.ranges++; - block.args = []; + if (value === '/') { + // if the beginning of the glob is "./", advance the start + // to the current index, and don't add the "./" characters + // to the state. This greatly simplifies lookbehinds when + // checking for BOS characters like "!" and "." (not "./") + if (prev.type === 'dot' && state.index === state.start + 1) { + state.start = state.index + 1; + state.consumed = ''; + state.output = ''; + tokens.pop(); + prev = bos; // reset "prev" to the first token continue; } - if (prev.type === 'range') { - siblings.pop(); + push({ type: 'slash', value, output: SLASH_LITERAL }); + continue; + } - let before = siblings[siblings.length - 1]; - before.value += prev.value + value; - prev = before; - block.ranges--; + /** + * Dots + */ + + if (value === '.') { + if (state.braces > 0 && prev.type === 'dot') { + if (prev.value === '.') prev.output = DOT_LITERAL; + const brace = braces[braces.length - 1]; + prev.type = 'dots'; + prev.output += value; + prev.value += value; + brace.dots = true; continue; } - push({ type: 'dot', value }); + if ((state.braces + state.parens) === 0 && prev.type !== 'bos' && prev.type !== 'slash') { + push({ type: 'text', value, output: DOT_LITERAL }); + continue; + } + + push({ type: 'dot', value, output: DOT_LITERAL }); continue; } /** - * Text + * Question marks */ - push({ type: 'text', value }); - } - - // Mark imbalanced braces and brackets as invalid - do { - block = stack.pop(); + if (value === '?') { + const isGroup = prev && prev.value === '('; + if (!isGroup && opts.noextglob !== true && peek() === '(' && peek(2) !== '?') { + extglobOpen('qmark', value); + continue; + } - if (block.type !== 'root') { - block.nodes.forEach(node => { - if (!node.nodes) { - if (node.type === 'open') node.isOpen = true; - if (node.type === 'close') node.isClose = true; - if (!node.nodes) node.type = 'text'; - node.invalid = true; + if (prev && prev.type === 'paren') { + const next = peek(); + let output = value; + + if (next === '<' && !utils.supportsLookbehinds()) { + throw new Error('Node.js v10 or higher is required for regex lookbehinds'); } - }); - // get the location of the block on parent.nodes (block's siblings) - let parent = stack[stack.length - 1]; - let index = parent.nodes.indexOf(block); - // replace the (invalid) block with it's nodes - parent.nodes.splice(index, 1, ...block.nodes); + if ((prev.value === '(' && !/[!=<:]/.test(next)) || (next === '<' && !/<([!=]|\w+>)/.test(remaining()))) { + output = `\\${value}`; + } + + push({ type: 'text', value, output }); + continue; + } + + if (opts.dot !== true && (prev.type === 'slash' || prev.type === 'bos')) { + push({ type: 'qmark', value, output: QMARK_NO_DOT }); + continue; + } + + push({ type: 'qmark', value, output: QMARK }); + continue; } - } while (stack.length > 0); - push({ type: 'eos' }); - return ast; -}; + /** + * Exclamation + */ -module.exports = parse; + if (value === '!') { + if (opts.noextglob !== true && peek() === '(') { + if (peek(2) !== '?' || !/[!=<:]/.test(peek(3))) { + extglobOpen('negate', value); + continue; + } + } + if (opts.nonegate !== true && state.index === 0) { + negate(); + continue; + } + } -/***/ }), -/* 313 */ -/***/ (function(module, exports, __webpack_require__) { + /** + * Plus + */ -"use strict"; + if (value === '+') { + if (opts.noextglob !== true && peek() === '(' && peek(2) !== '?') { + extglobOpen('plus', value); + continue; + } + if ((prev && prev.value === '(') || opts.regex === false) { + push({ type: 'plus', value, output: PLUS_LITERAL }); + continue; + } -module.exports = { - MAX_LENGTH: 1024 * 64, + if ((prev && (prev.type === 'bracket' || prev.type === 'paren' || prev.type === 'brace')) || state.parens > 0) { + push({ type: 'plus', value }); + continue; + } - // Digits - CHAR_0: '0', /* 0 */ - CHAR_9: '9', /* 9 */ + push({ type: 'plus', value: PLUS_LITERAL }); + continue; + } - // Alphabet chars. - CHAR_UPPERCASE_A: 'A', /* A */ - CHAR_LOWERCASE_A: 'a', /* a */ - CHAR_UPPERCASE_Z: 'Z', /* Z */ - CHAR_LOWERCASE_Z: 'z', /* z */ + /** + * Plain text + */ - CHAR_LEFT_PARENTHESES: '(', /* ( */ - CHAR_RIGHT_PARENTHESES: ')', /* ) */ + if (value === '@') { + if (opts.noextglob !== true && peek() === '(' && peek(2) !== '?') { + push({ type: 'at', extglob: true, value, output: '' }); + continue; + } - CHAR_ASTERISK: '*', /* * */ + push({ type: 'text', value }); + continue; + } - // Non-alphabetic chars. - CHAR_AMPERSAND: '&', /* & */ - CHAR_AT: '@', /* @ */ - CHAR_BACKSLASH: '\\', /* \ */ - CHAR_BACKTICK: '`', /* ` */ - CHAR_CARRIAGE_RETURN: '\r', /* \r */ - CHAR_CIRCUMFLEX_ACCENT: '^', /* ^ */ - CHAR_COLON: ':', /* : */ - CHAR_COMMA: ',', /* , */ - CHAR_DOLLAR: '$', /* . */ - CHAR_DOT: '.', /* . */ - CHAR_DOUBLE_QUOTE: '"', /* " */ - CHAR_EQUAL: '=', /* = */ - CHAR_EXCLAMATION_MARK: '!', /* ! */ - CHAR_FORM_FEED: '\f', /* \f */ - CHAR_FORWARD_SLASH: '/', /* / */ - CHAR_HASH: '#', /* # */ - CHAR_HYPHEN_MINUS: '-', /* - */ - CHAR_LEFT_ANGLE_BRACKET: '<', /* < */ - CHAR_LEFT_CURLY_BRACE: '{', /* { */ - CHAR_LEFT_SQUARE_BRACKET: '[', /* [ */ - CHAR_LINE_FEED: '\n', /* \n */ - CHAR_NO_BREAK_SPACE: '\u00A0', /* \u00A0 */ - CHAR_PERCENT: '%', /* % */ - CHAR_PLUS: '+', /* + */ - CHAR_QUESTION_MARK: '?', /* ? */ - CHAR_RIGHT_ANGLE_BRACKET: '>', /* > */ - CHAR_RIGHT_CURLY_BRACE: '}', /* } */ - CHAR_RIGHT_SQUARE_BRACKET: ']', /* ] */ - CHAR_SEMICOLON: ';', /* ; */ - CHAR_SINGLE_QUOTE: '\'', /* ' */ - CHAR_SPACE: ' ', /* */ - CHAR_TAB: '\t', /* \t */ - CHAR_UNDERSCORE: '_', /* _ */ - CHAR_VERTICAL_LINE: '|', /* | */ - CHAR_ZERO_WIDTH_NOBREAK_SPACE: '\uFEFF' /* \uFEFF */ -}; + /** + * Plain text + */ + if (value !== '*') { + if (value === '$' || value === '^') { + value = `\\${value}`; + } -/***/ }), -/* 314 */ -/***/ (function(module, exports, __webpack_require__) { + const match = REGEX_NON_SPECIAL_CHARS.exec(remaining()); + if (match) { + value += match[0]; + state.index += match[0].length; + } -"use strict"; + push({ type: 'text', value }); + continue; + } + /** + * Stars + */ -module.exports = __webpack_require__(315); + if (prev && (prev.type === 'globstar' || prev.star === true)) { + prev.type = 'star'; + prev.star = true; + prev.value += value; + prev.output = star; + state.backtrack = true; + state.globstar = true; + consume(value); + continue; + } + let rest = remaining(); + if (opts.noextglob !== true && /^\([^?]/.test(rest)) { + extglobOpen('star', value); + continue; + } -/***/ }), -/* 315 */ -/***/ (function(module, exports, __webpack_require__) { + if (prev.type === 'star') { + if (opts.noglobstar === true) { + consume(value); + continue; + } -"use strict"; + const prior = prev.prev; + const before = prior.prev; + const isStart = prior.type === 'slash' || prior.type === 'bos'; + const afterStar = before && (before.type === 'star' || before.type === 'globstar'); + if (opts.bash === true && (!isStart || (rest[0] && rest[0] !== '/'))) { + push({ type: 'star', value, output: '' }); + continue; + } -const path = __webpack_require__(4); -const scan = __webpack_require__(316); -const parse = __webpack_require__(319); -const utils = __webpack_require__(317); -const constants = __webpack_require__(318); -const isObject = val => val && typeof val === 'object' && !Array.isArray(val); + const isBrace = state.braces > 0 && (prior.type === 'comma' || prior.type === 'brace'); + const isExtglob = extglobs.length && (prior.type === 'pipe' || prior.type === 'paren'); + if (!isStart && prior.type !== 'paren' && !isBrace && !isExtglob) { + push({ type: 'star', value, output: '' }); + continue; + } -/** - * Creates a matcher function from one or more glob patterns. The - * returned function takes a string to match as its first argument, - * and returns true if the string is a match. The returned matcher - * function also takes a boolean as the second argument that, when true, - * returns an object with additional information. - * - * ```js - * const picomatch = require('picomatch'); - * // picomatch(glob[, options]); - * - * const isMatch = picomatch('*.!(*a)'); - * console.log(isMatch('a.a')); //=> false - * console.log(isMatch('a.b')); //=> true - * ``` - * @name picomatch - * @param {String|Array} `globs` One or more glob patterns. - * @param {Object=} `options` - * @return {Function=} Returns a matcher function. - * @api public - */ + // strip consecutive `/**/` + while (rest.slice(0, 3) === '/**') { + const after = input[state.index + 4]; + if (after && after !== '/') { + break; + } + rest = rest.slice(3); + consume('/**', 3); + } -const picomatch = (glob, options, returnState = false) => { - if (Array.isArray(glob)) { - const fns = glob.map(input => picomatch(input, options, returnState)); - const arrayMatcher = str => { - for (const isMatch of fns) { - const state = isMatch(str); - if (state) return state; + if (prior.type === 'bos' && eos()) { + prev.type = 'globstar'; + prev.value += value; + prev.output = globstar(opts); + state.output = prev.output; + state.globstar = true; + consume(value); + continue; } - return false; - }; - return arrayMatcher; - } - const isState = isObject(glob) && glob.tokens && glob.input; + if (prior.type === 'slash' && prior.prev.type !== 'bos' && !afterStar && eos()) { + state.output = state.output.slice(0, -(prior.output + prev.output).length); + prior.output = `(?:${prior.output}`; - if (glob === '' || (typeof glob !== 'string' && !isState)) { - throw new TypeError('Expected pattern to be a non-empty string'); - } + prev.type = 'globstar'; + prev.output = globstar(opts) + (opts.strictSlashes ? ')' : '|$)'); + prev.value += value; + state.globstar = true; + state.output += prior.output + prev.output; + consume(value); + continue; + } - const opts = options || {}; - const posix = utils.isWindows(options); - const regex = isState - ? picomatch.compileRe(glob, options) - : picomatch.makeRe(glob, options, false, true); + if (prior.type === 'slash' && prior.prev.type !== 'bos' && rest[0] === '/') { + const end = rest[1] !== void 0 ? '|$' : ''; - const state = regex.state; - delete regex.state; + state.output = state.output.slice(0, -(prior.output + prev.output).length); + prior.output = `(?:${prior.output}`; - let isIgnored = () => false; - if (opts.ignore) { - const ignoreOpts = { ...options, ignore: null, onMatch: null, onResult: null }; - isIgnored = picomatch(opts.ignore, ignoreOpts, returnState); - } + prev.type = 'globstar'; + prev.output = `${globstar(opts)}${SLASH_LITERAL}|${SLASH_LITERAL}${end})`; + prev.value += value; - const matcher = (input, returnObject = false) => { - const { isMatch, match, output } = picomatch.test(input, regex, options, { glob, posix }); - const result = { glob, state, regex, posix, input, output, match, isMatch }; + state.output += prior.output + prev.output; + state.globstar = true; - if (typeof opts.onResult === 'function') { - opts.onResult(result); - } + consume(value + advance()); - if (isMatch === false) { - result.isMatch = false; - return returnObject ? result : false; + push({ type: 'slash', value: '/', output: '' }); + continue; + } + + if (prior.type === 'bos' && rest[0] === '/') { + prev.type = 'globstar'; + prev.value += value; + prev.output = `(?:^|${SLASH_LITERAL}|${globstar(opts)}${SLASH_LITERAL})`; + state.output = prev.output; + state.globstar = true; + consume(value + advance()); + push({ type: 'slash', value: '/', output: '' }); + continue; + } + + // remove single star from output + state.output = state.output.slice(0, -prev.output.length); + + // reset previous token to globstar + prev.type = 'globstar'; + prev.output = globstar(opts); + prev.value += value; + + // reset output with globstar + state.output += prev.output; + state.globstar = true; + consume(value); + continue; } - if (isIgnored(input)) { - if (typeof opts.onIgnore === 'function') { - opts.onIgnore(result); + const token = { type: 'star', value, output: star }; + + if (opts.bash === true) { + token.output = '.*?'; + if (prev.type === 'bos' || prev.type === 'slash') { + token.output = nodot + token.output; } - result.isMatch = false; - return returnObject ? result : false; + push(token); + continue; } - if (typeof opts.onMatch === 'function') { - opts.onMatch(result); + if (prev && (prev.type === 'bracket' || prev.type === 'paren') && opts.regex === true) { + token.output = value; + push(token); + continue; } - return returnObject ? result : true; - }; - if (returnState) { - matcher.state = state; - } + if (state.index === state.start || prev.type === 'slash' || prev.type === 'dot') { + if (prev.type === 'dot') { + state.output += NO_DOT_SLASH; + prev.output += NO_DOT_SLASH; - return matcher; -}; + } else if (opts.dot === true) { + state.output += NO_DOTS_SLASH; + prev.output += NO_DOTS_SLASH; -/** - * Test `input` with the given `regex`. This is used by the main - * `picomatch()` function to test the input string. - * - * ```js - * const picomatch = require('picomatch'); - * // picomatch.test(input, regex[, options]); - * - * console.log(picomatch.test('foo/bar', /^(?:([^/]*?)\/([^/]*?))$/)); - * // { isMatch: true, match: [ 'foo/', 'foo', 'bar' ], output: 'foo/bar' } - * ``` - * @param {String} `input` String to test. - * @param {RegExp} `regex` - * @return {Object} Returns an object with matching info. - * @api public - */ + } else { + state.output += nodot; + prev.output += nodot; + } -picomatch.test = (input, regex, options, { glob, posix } = {}) => { - if (typeof input !== 'string') { - throw new TypeError('Expected input to be a string'); + if (peek() !== '*') { + state.output += ONE_CHAR; + prev.output += ONE_CHAR; + } + } + + push(token); } - if (input === '') { - return { isMatch: false, output: '' }; + while (state.brackets > 0) { + if (opts.strictBrackets === true) throw new SyntaxError(syntaxError('closing', ']')); + state.output = utils.escapeLast(state.output, '['); + decrement('brackets'); } - const opts = options || {}; - const format = opts.format || (posix ? utils.toPosixSlashes : null); - let match = input === glob; - let output = (match && format) ? format(input) : input; + while (state.parens > 0) { + if (opts.strictBrackets === true) throw new SyntaxError(syntaxError('closing', ')')); + state.output = utils.escapeLast(state.output, '('); + decrement('parens'); + } - if (match === false) { - output = format ? format(input) : input; - match = output === glob; + while (state.braces > 0) { + if (opts.strictBrackets === true) throw new SyntaxError(syntaxError('closing', '}')); + state.output = utils.escapeLast(state.output, '{'); + decrement('braces'); } - if (match === false || opts.capture === true) { - if (opts.matchBase === true || opts.basename === true) { - match = picomatch.matchBase(input, regex, options, posix); - } else { - match = regex.exec(output); - } + if (opts.strictSlashes !== true && (prev.type === 'star' || prev.type === 'bracket')) { + push({ type: 'maybe_slash', value: '', output: `${SLASH_LITERAL}?` }); } - return { isMatch: Boolean(match), match, output }; -}; + // rebuild the output if we had to backtrack at any point + if (state.backtrack === true) { + state.output = ''; -/** - * Match the basename of a filepath. - * - * ```js - * const picomatch = require('picomatch'); - * // picomatch.matchBase(input, glob[, options]); - * console.log(picomatch.matchBase('foo/bar.js', '*.js'); // true - * ``` - * @param {String} `input` String to test. - * @param {RegExp|String} `glob` Glob pattern or regex created by [.makeRe](#makeRe). - * @return {Boolean} - * @api public - */ + for (const token of state.tokens) { + state.output += token.output != null ? token.output : token.value; -picomatch.matchBase = (input, glob, options, posix = utils.isWindows(options)) => { - const regex = glob instanceof RegExp ? glob : picomatch.makeRe(glob, options); - return regex.test(path.basename(input)); + if (token.suffix) { + state.output += token.suffix; + } + } + } + + return state; }; /** - * Returns true if **any** of the given glob `patterns` match the specified `string`. - * - * ```js - * const picomatch = require('picomatch'); - * // picomatch.isMatch(string, patterns[, options]); - * - * console.log(picomatch.isMatch('a.a', ['b.*', '*.a'])); //=> true - * console.log(picomatch.isMatch('a.a', 'b.*')); //=> false - * ``` - * @param {String|Array} str The string to test. - * @param {String|Array} patterns One or more glob patterns to use for matching. - * @param {Object} [options] See available [options](#options). - * @return {Boolean} Returns true if any patterns match `str` - * @api public + * Fast paths for creating regular expressions for common glob patterns. + * This can significantly speed up processing and has very little downside + * impact when none of the fast paths match. */ -picomatch.isMatch = (str, patterns, options) => picomatch(patterns, options)(str); +parse.fastpaths = (input, options) => { + const opts = { ...options }; + const max = typeof opts.maxLength === 'number' ? Math.min(MAX_LENGTH, opts.maxLength) : MAX_LENGTH; + const len = input.length; + if (len > max) { + throw new SyntaxError(`Input length: ${len}, exceeds maximum allowed length: ${max}`); + } -/** - * Parse a glob pattern to create the source string for a regular - * expression. - * - * ```js - * const picomatch = require('picomatch'); - * const result = picomatch.parse(pattern[, options]); - * ``` - * @param {String} `pattern` - * @param {Object} `options` - * @return {Object} Returns an object with useful properties and output to be used as a regex source string. - * @api public - */ + input = REPLACEMENTS[input] || input; + const win32 = utils.isWindows(options); -picomatch.parse = (pattern, options) => { - if (Array.isArray(pattern)) return pattern.map(p => picomatch.parse(p, options)); - return parse(pattern, { ...options, fastpaths: false }); -}; + // create constants based on platform, for windows or posix + const { + DOT_LITERAL, + SLASH_LITERAL, + ONE_CHAR, + DOTS_SLASH, + NO_DOT, + NO_DOTS, + NO_DOTS_SLASH, + STAR, + START_ANCHOR + } = constants.globChars(win32); -/** - * Scan a glob pattern to separate the pattern into segments. - * - * ```js - * const picomatch = require('picomatch'); - * // picomatch.scan(input[, options]); - * - * const result = picomatch.scan('!./foo/*.js'); - * console.log(result); - * { prefix: '!./', - * input: '!./foo/*.js', - * start: 3, - * base: 'foo', - * glob: '*.js', - * isBrace: false, - * isBracket: false, - * isGlob: true, - * isExtglob: false, - * isGlobstar: false, - * negated: true } - * ``` - * @param {String} `input` Glob pattern to scan. - * @param {Object} `options` - * @return {Object} Returns an object with - * @api public - */ + const nodot = opts.dot ? NO_DOTS : NO_DOT; + const slashDot = opts.dot ? NO_DOTS_SLASH : NO_DOT; + const capture = opts.capture ? '' : '?:'; + const state = { negated: false, prefix: '' }; + let star = opts.bash === true ? '.*?' : STAR; -picomatch.scan = (input, options) => scan(input, options); + if (opts.capture) { + star = `(${star})`; + } -/** - * Create a regular expression from a parsed glob pattern. - * - * ```js - * const picomatch = require('picomatch'); - * const state = picomatch.parse('*.js'); - * // picomatch.compileRe(state[, options]); - * - * console.log(picomatch.compileRe(state)); - * //=> /^(?:(?!\.)(?=.)[^/]*?\.js)$/ - * ``` - * @param {String} `state` The object returned from the `.parse` method. - * @param {Object} `options` - * @return {RegExp} Returns a regex created from the given pattern. - * @api public - */ + const globstar = (opts) => { + if (opts.noglobstar === true) return star; + return `(${capture}(?:(?!${START_ANCHOR}${opts.dot ? DOTS_SLASH : DOT_LITERAL}).)*?)`; + }; -picomatch.compileRe = (parsed, options, returnOutput = false, returnState = false) => { - if (returnOutput === true) { - return parsed.output; - } + const create = str => { + switch (str) { + case '*': + return `${nodot}${ONE_CHAR}${star}`; - const opts = options || {}; - const prepend = opts.contains ? '' : '^'; - const append = opts.contains ? '' : '$'; + case '.*': + return `${DOT_LITERAL}${ONE_CHAR}${star}`; - let source = `${prepend}(?:${parsed.output})${append}`; - if (parsed && parsed.negated === true) { - source = `^(?!${source}).*$`; - } + case '*.*': + return `${nodot}${star}${DOT_LITERAL}${ONE_CHAR}${star}`; - const regex = picomatch.toRegex(source, options); - if (returnState === true) { - regex.state = parsed; - } + case '*/*': + return `${nodot}${star}${SLASH_LITERAL}${ONE_CHAR}${slashDot}${star}`; - return regex; -}; + case '**': + return nodot + globstar(opts); -picomatch.makeRe = (input, options, returnOutput = false, returnState = false) => { - if (!input || typeof input !== 'string') { - throw new TypeError('Expected a non-empty string'); - } + case '**/*': + return `(?:${nodot}${globstar(opts)}${SLASH_LITERAL})?${slashDot}${ONE_CHAR}${star}`; - const opts = options || {}; - let parsed = { negated: false, fastpaths: true }; - let prefix = ''; - let output; + case '**/*.*': + return `(?:${nodot}${globstar(opts)}${SLASH_LITERAL})?${slashDot}${star}${DOT_LITERAL}${ONE_CHAR}${star}`; - if (input.startsWith('./')) { - input = input.slice(2); - prefix = parsed.prefix = './'; - } + case '**/.*': + return `(?:${nodot}${globstar(opts)}${SLASH_LITERAL})?${DOT_LITERAL}${ONE_CHAR}${star}`; - if (opts.fastpaths !== false && (input[0] === '.' || input[0] === '*')) { - output = parse.fastpaths(input, options); - } + default: { + const match = /^(.*?)\.(\w+)$/.exec(str); + if (!match) return; - if (output === undefined) { - parsed = parse(input, options); - parsed.prefix = prefix + (parsed.prefix || ''); - } else { - parsed.output = output; - } + const source = create(match[1]); + if (!source) return; - return picomatch.compileRe(parsed, options, returnOutput, returnState); -}; + return source + DOT_LITERAL + match[2]; + } + } + }; -/** - * Create a regular expression from the given regex source string. - * - * ```js - * const picomatch = require('picomatch'); - * // picomatch.toRegex(source[, options]); - * - * const { output } = picomatch.parse('*.js'); - * console.log(picomatch.toRegex(output)); - * //=> /^(?:(?!\.)(?=.)[^/]*?\.js)$/ - * ``` - * @param {String} `source` Regular expression source string. - * @param {Object} `options` - * @return {RegExp} - * @api public - */ + const output = utils.removePrefix(input, state); + let source = create(output); -picomatch.toRegex = (source, options) => { - try { - const opts = options || {}; - return new RegExp(source, opts.flags || (opts.nocase ? 'i' : '')); - } catch (err) { - if (options && options.debug === true) throw err; - return /$^/; + if (source && opts.strictSlashes !== true) { + source += `${SLASH_LITERAL}?`; } + + return source; }; -/** - * Picomatch constants. - * @return {Object} - */ +module.exports = parse; -picomatch.constants = constants; -/** - * Expose "picomatch" - */ +/***/ }), +/* 313 */ +/***/ (function(module, exports, __webpack_require__) { -module.exports = picomatch; +"use strict"; + +Object.defineProperty(exports, "__esModule", { value: true }); +const merge2 = __webpack_require__(284); +function merge(streams) { + const mergedStream = merge2(streams); + streams.forEach((stream) => { + stream.once('error', (error) => mergedStream.emit('error', error)); + }); + mergedStream.once('close', () => propagateCloseEventToSources(streams)); + mergedStream.once('end', () => propagateCloseEventToSources(streams)); + return mergedStream; +} +exports.merge = merge; +function propagateCloseEventToSources(streams) { + streams.forEach((stream) => stream.emit('close')); +} /***/ }), -/* 316 */ +/* 314 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; + +Object.defineProperty(exports, "__esModule", { value: true }); +function isString(input) { + return typeof input === 'string'; +} +exports.isString = isString; +function isEmpty(input) { + return input === ''; +} +exports.isEmpty = isEmpty; -const utils = __webpack_require__(317); -const { - CHAR_ASTERISK, /* * */ - CHAR_AT, /* @ */ - CHAR_BACKWARD_SLASH, /* \ */ - CHAR_COMMA, /* , */ - CHAR_DOT, /* . */ - CHAR_EXCLAMATION_MARK, /* ! */ - CHAR_FORWARD_SLASH, /* / */ - CHAR_LEFT_CURLY_BRACE, /* { */ - CHAR_LEFT_PARENTHESES, /* ( */ - CHAR_LEFT_SQUARE_BRACKET, /* [ */ - CHAR_PLUS, /* + */ - CHAR_QUESTION_MARK, /* ? */ - CHAR_RIGHT_CURLY_BRACE, /* } */ - CHAR_RIGHT_PARENTHESES, /* ) */ - CHAR_RIGHT_SQUARE_BRACKET /* ] */ -} = __webpack_require__(318); +/***/ }), +/* 315 */ +/***/ (function(module, exports, __webpack_require__) { -const isPathSeparator = code => { - return code === CHAR_FORWARD_SLASH || code === CHAR_BACKWARD_SLASH; -}; +"use strict"; + +Object.defineProperty(exports, "__esModule", { value: true }); +const stream_1 = __webpack_require__(316); +const provider_1 = __webpack_require__(343); +class ProviderAsync extends provider_1.default { + constructor() { + super(...arguments); + this._reader = new stream_1.default(this._settings); + } + read(task) { + const root = this._getRootDirectory(task); + const options = this._getReaderOptions(task); + const entries = []; + return new Promise((resolve, reject) => { + const stream = this.api(root, task, options); + stream.once('error', reject); + stream.on('data', (entry) => entries.push(options.transform(entry))); + stream.once('end', () => resolve(entries)); + }); + } + api(root, task, options) { + if (task.dynamic) { + return this._reader.dynamic(root, options); + } + return this._reader.static(task.patterns, options); + } +} +exports.default = ProviderAsync; -const depth = token => { - if (token.isPrefix !== true) { - token.depth = token.isGlobstar ? Infinity : 1; - } -}; -/** - * Quickly scans a glob pattern and returns an object with a handful of - * useful properties, like `isGlob`, `path` (the leading non-glob, if it exists), - * `glob` (the actual pattern), and `negated` (true if the path starts with `!`). - * - * ```js - * const pm = require('picomatch'); - * console.log(pm.scan('foo/bar/*.js')); - * { isGlob: true, input: 'foo/bar/*.js', base: 'foo/bar', glob: '*.js' } - * ``` - * @param {String} `str` - * @param {Object} `options` - * @return {Object} Returns an object with tokens and regex source string. - * @api public - */ +/***/ }), +/* 316 */ +/***/ (function(module, exports, __webpack_require__) { -const scan = (input, options) => { - const opts = options || {}; +"use strict"; + +Object.defineProperty(exports, "__esModule", { value: true }); +const stream_1 = __webpack_require__(138); +const fsStat = __webpack_require__(317); +const fsWalk = __webpack_require__(322); +const reader_1 = __webpack_require__(342); +class ReaderStream extends reader_1.default { + constructor() { + super(...arguments); + this._walkStream = fsWalk.walkStream; + this._stat = fsStat.stat; + } + dynamic(root, options) { + return this._walkStream(root, options); + } + static(patterns, options) { + const filepaths = patterns.map(this._getFullEntryPath, this); + const stream = new stream_1.PassThrough({ objectMode: true }); + stream._write = (index, _enc, done) => { + return this._getEntry(filepaths[index], patterns[index], options) + .then((entry) => { + if (entry !== null && options.entryFilter(entry)) { + stream.push(entry); + } + if (index === filepaths.length - 1) { + stream.end(); + } + done(); + }) + .catch(done); + }; + for (let i = 0; i < filepaths.length; i++) { + stream.write(i); + } + return stream; + } + _getEntry(filepath, pattern, options) { + return this._getStat(filepath) + .then((stats) => this._makeEntry(stats, pattern)) + .catch((error) => { + if (options.errorFilter(error)) { + return null; + } + throw error; + }); + } + _getStat(filepath) { + return new Promise((resolve, reject) => { + this._stat(filepath, this._fsStatSettings, (error, stats) => { + return error === null ? resolve(stats) : reject(error); + }); + }); + } +} +exports.default = ReaderStream; - const length = input.length - 1; - const scanToEnd = opts.parts === true || opts.scanToEnd === true; - const slashes = []; - const tokens = []; - const parts = []; - let str = input; - let index = -1; - let start = 0; - let lastIndex = 0; - let isBrace = false; - let isBracket = false; - let isGlob = false; - let isExtglob = false; - let isGlobstar = false; - let braceEscaped = false; - let backslashes = false; - let negated = false; - let finished = false; - let braces = 0; - let prev; - let code; - let token = { value: '', depth: 0, isGlob: false }; +/***/ }), +/* 317 */ +/***/ (function(module, exports, __webpack_require__) { - const eos = () => index >= length; - const peek = () => str.charCodeAt(index + 1); - const advance = () => { - prev = code; - return str.charCodeAt(++index); - }; +"use strict"; + +Object.defineProperty(exports, "__esModule", { value: true }); +const async = __webpack_require__(318); +const sync = __webpack_require__(319); +const settings_1 = __webpack_require__(320); +exports.Settings = settings_1.default; +function stat(path, optionsOrSettingsOrCallback, callback) { + if (typeof optionsOrSettingsOrCallback === 'function') { + return async.read(path, getSettings(), optionsOrSettingsOrCallback); + } + async.read(path, getSettings(optionsOrSettingsOrCallback), callback); +} +exports.stat = stat; +function statSync(path, optionsOrSettings) { + const settings = getSettings(optionsOrSettings); + return sync.read(path, settings); +} +exports.statSync = statSync; +function getSettings(settingsOrOptions = {}) { + if (settingsOrOptions instanceof settings_1.default) { + return settingsOrOptions; + } + return new settings_1.default(settingsOrOptions); +} - while (index < length) { - code = advance(); - let next; - if (code === CHAR_BACKWARD_SLASH) { - backslashes = token.backslashes = true; - code = advance(); +/***/ }), +/* 318 */ +/***/ (function(module, exports, __webpack_require__) { - if (code === CHAR_LEFT_CURLY_BRACE) { - braceEscaped = true; - } - continue; - } +"use strict"; + +Object.defineProperty(exports, "__esModule", { value: true }); +function read(path, settings, callback) { + settings.fs.lstat(path, (lstatError, lstat) => { + if (lstatError !== null) { + return callFailureCallback(callback, lstatError); + } + if (!lstat.isSymbolicLink() || !settings.followSymbolicLink) { + return callSuccessCallback(callback, lstat); + } + settings.fs.stat(path, (statError, stat) => { + if (statError !== null) { + if (settings.throwErrorOnBrokenSymbolicLink) { + return callFailureCallback(callback, statError); + } + return callSuccessCallback(callback, lstat); + } + if (settings.markSymbolicLink) { + stat.isSymbolicLink = () => true; + } + callSuccessCallback(callback, stat); + }); + }); +} +exports.read = read; +function callFailureCallback(callback, error) { + callback(error); +} +function callSuccessCallback(callback, result) { + callback(null, result); +} - if (braceEscaped === true || code === CHAR_LEFT_CURLY_BRACE) { - braces++; - while (eos() !== true && (code = advance())) { - if (code === CHAR_BACKWARD_SLASH) { - backslashes = token.backslashes = true; - advance(); - continue; - } +/***/ }), +/* 319 */ +/***/ (function(module, exports, __webpack_require__) { - if (code === CHAR_LEFT_CURLY_BRACE) { - braces++; - continue; - } +"use strict"; + +Object.defineProperty(exports, "__esModule", { value: true }); +function read(path, settings) { + const lstat = settings.fs.lstatSync(path); + if (!lstat.isSymbolicLink() || !settings.followSymbolicLink) { + return lstat; + } + try { + const stat = settings.fs.statSync(path); + if (settings.markSymbolicLink) { + stat.isSymbolicLink = () => true; + } + return stat; + } + catch (error) { + if (!settings.throwErrorOnBrokenSymbolicLink) { + return lstat; + } + throw error; + } +} +exports.read = read; - if (braceEscaped !== true && code === CHAR_DOT && (code = advance()) === CHAR_DOT) { - isBrace = token.isBrace = true; - isGlob = token.isGlob = true; - finished = true; - if (scanToEnd === true) { - continue; - } +/***/ }), +/* 320 */ +/***/ (function(module, exports, __webpack_require__) { - break; - } +"use strict"; + +Object.defineProperty(exports, "__esModule", { value: true }); +const fs = __webpack_require__(321); +class Settings { + constructor(_options = {}) { + this._options = _options; + this.followSymbolicLink = this._getValue(this._options.followSymbolicLink, true); + this.fs = fs.createFileSystemAdapter(this._options.fs); + this.markSymbolicLink = this._getValue(this._options.markSymbolicLink, false); + this.throwErrorOnBrokenSymbolicLink = this._getValue(this._options.throwErrorOnBrokenSymbolicLink, true); + } + _getValue(option, value) { + return option === undefined ? value : option; + } +} +exports.default = Settings; - if (braceEscaped !== true && code === CHAR_COMMA) { - isBrace = token.isBrace = true; - isGlob = token.isGlob = true; - finished = true; - if (scanToEnd === true) { - continue; - } +/***/ }), +/* 321 */ +/***/ (function(module, exports, __webpack_require__) { - break; - } +"use strict"; + +Object.defineProperty(exports, "__esModule", { value: true }); +const fs = __webpack_require__(134); +exports.FILE_SYSTEM_ADAPTER = { + lstat: fs.lstat, + stat: fs.stat, + lstatSync: fs.lstatSync, + statSync: fs.statSync +}; +function createFileSystemAdapter(fsMethods) { + if (fsMethods === undefined) { + return exports.FILE_SYSTEM_ADAPTER; + } + return Object.assign(Object.assign({}, exports.FILE_SYSTEM_ADAPTER), fsMethods); +} +exports.createFileSystemAdapter = createFileSystemAdapter; - if (code === CHAR_RIGHT_CURLY_BRACE) { - braces--; - if (braces === 0) { - braceEscaped = false; - isBrace = token.isBrace = true; - finished = true; - break; - } - } - } - - if (scanToEnd === true) { - continue; - } +/***/ }), +/* 322 */ +/***/ (function(module, exports, __webpack_require__) { - break; - } +"use strict"; + +Object.defineProperty(exports, "__esModule", { value: true }); +const async_1 = __webpack_require__(323); +const stream_1 = __webpack_require__(338); +const sync_1 = __webpack_require__(339); +const settings_1 = __webpack_require__(341); +exports.Settings = settings_1.default; +function walk(directory, optionsOrSettingsOrCallback, callback) { + if (typeof optionsOrSettingsOrCallback === 'function') { + return new async_1.default(directory, getSettings()).read(optionsOrSettingsOrCallback); + } + new async_1.default(directory, getSettings(optionsOrSettingsOrCallback)).read(callback); +} +exports.walk = walk; +function walkSync(directory, optionsOrSettings) { + const settings = getSettings(optionsOrSettings); + const provider = new sync_1.default(directory, settings); + return provider.read(); +} +exports.walkSync = walkSync; +function walkStream(directory, optionsOrSettings) { + const settings = getSettings(optionsOrSettings); + const provider = new stream_1.default(directory, settings); + return provider.read(); +} +exports.walkStream = walkStream; +function getSettings(settingsOrOptions = {}) { + if (settingsOrOptions instanceof settings_1.default) { + return settingsOrOptions; + } + return new settings_1.default(settingsOrOptions); +} - if (code === CHAR_FORWARD_SLASH) { - slashes.push(index); - tokens.push(token); - token = { value: '', depth: 0, isGlob: false }; - if (finished === true) continue; - if (prev === CHAR_DOT && index === (start + 1)) { - start += 2; - continue; - } +/***/ }), +/* 323 */ +/***/ (function(module, exports, __webpack_require__) { - lastIndex = index + 1; - continue; - } +"use strict"; + +Object.defineProperty(exports, "__esModule", { value: true }); +const async_1 = __webpack_require__(324); +class AsyncProvider { + constructor(_root, _settings) { + this._root = _root; + this._settings = _settings; + this._reader = new async_1.default(this._root, this._settings); + this._storage = new Set(); + } + read(callback) { + this._reader.onError((error) => { + callFailureCallback(callback, error); + }); + this._reader.onEntry((entry) => { + this._storage.add(entry); + }); + this._reader.onEnd(() => { + callSuccessCallback(callback, [...this._storage]); + }); + this._reader.read(); + } +} +exports.default = AsyncProvider; +function callFailureCallback(callback, error) { + callback(error); +} +function callSuccessCallback(callback, entries) { + callback(null, entries); +} - if (opts.noext !== true) { - const isExtglobChar = code === CHAR_PLUS - || code === CHAR_AT - || code === CHAR_ASTERISK - || code === CHAR_QUESTION_MARK - || code === CHAR_EXCLAMATION_MARK; - if (isExtglobChar === true && peek() === CHAR_LEFT_PARENTHESES) { - isGlob = token.isGlob = true; - isExtglob = token.isExtglob = true; - finished = true; +/***/ }), +/* 324 */ +/***/ (function(module, exports, __webpack_require__) { - if (scanToEnd === true) { - while (eos() !== true && (code = advance())) { - if (code === CHAR_BACKWARD_SLASH) { - backslashes = token.backslashes = true; - code = advance(); - continue; - } +"use strict"; + +Object.defineProperty(exports, "__esModule", { value: true }); +const events_1 = __webpack_require__(156); +const fsScandir = __webpack_require__(325); +const fastq = __webpack_require__(334); +const common = __webpack_require__(336); +const reader_1 = __webpack_require__(337); +class AsyncReader extends reader_1.default { + constructor(_root, _settings) { + super(_root, _settings); + this._settings = _settings; + this._scandir = fsScandir.scandir; + this._emitter = new events_1.EventEmitter(); + this._queue = fastq(this._worker.bind(this), this._settings.concurrency); + this._isFatalError = false; + this._isDestroyed = false; + this._queue.drain = () => { + if (!this._isFatalError) { + this._emitter.emit('end'); + } + }; + } + read() { + this._isFatalError = false; + this._isDestroyed = false; + setImmediate(() => { + this._pushToQueue(this._root, this._settings.basePath); + }); + return this._emitter; + } + destroy() { + if (this._isDestroyed) { + throw new Error('The reader is already destroyed'); + } + this._isDestroyed = true; + this._queue.killAndDrain(); + } + onEntry(callback) { + this._emitter.on('entry', callback); + } + onError(callback) { + this._emitter.once('error', callback); + } + onEnd(callback) { + this._emitter.once('end', callback); + } + _pushToQueue(directory, base) { + const queueItem = { directory, base }; + this._queue.push(queueItem, (error) => { + if (error !== null) { + this._handleError(error); + } + }); + } + _worker(item, done) { + this._scandir(item.directory, this._settings.fsScandirSettings, (error, entries) => { + if (error !== null) { + return done(error, undefined); + } + for (const entry of entries) { + this._handleEntry(entry, item.base); + } + done(null, undefined); + }); + } + _handleError(error) { + if (!common.isFatalError(this._settings, error)) { + return; + } + this._isFatalError = true; + this._isDestroyed = true; + this._emitter.emit('error', error); + } + _handleEntry(entry, base) { + if (this._isDestroyed || this._isFatalError) { + return; + } + const fullpath = entry.path; + if (base !== undefined) { + entry.path = common.joinPathSegments(base, entry.name, this._settings.pathSegmentSeparator); + } + if (common.isAppliedFilter(this._settings.entryFilter, entry)) { + this._emitEntry(entry); + } + if (entry.dirent.isDirectory() && common.isAppliedFilter(this._settings.deepFilter, entry)) { + this._pushToQueue(fullpath, entry.path); + } + } + _emitEntry(entry) { + this._emitter.emit('entry', entry); + } +} +exports.default = AsyncReader; - if (code === CHAR_RIGHT_PARENTHESES) { - isGlob = token.isGlob = true; - finished = true; - break; - } - } - continue; - } - break; - } - } - if (code === CHAR_ASTERISK) { - if (prev === CHAR_ASTERISK) isGlobstar = token.isGlobstar = true; - isGlob = token.isGlob = true; - finished = true; +/***/ }), +/* 325 */ +/***/ (function(module, exports, __webpack_require__) { - if (scanToEnd === true) { - continue; - } - break; - } +"use strict"; + +Object.defineProperty(exports, "__esModule", { value: true }); +const async = __webpack_require__(326); +const sync = __webpack_require__(331); +const settings_1 = __webpack_require__(332); +exports.Settings = settings_1.default; +function scandir(path, optionsOrSettingsOrCallback, callback) { + if (typeof optionsOrSettingsOrCallback === 'function') { + return async.read(path, getSettings(), optionsOrSettingsOrCallback); + } + async.read(path, getSettings(optionsOrSettingsOrCallback), callback); +} +exports.scandir = scandir; +function scandirSync(path, optionsOrSettings) { + const settings = getSettings(optionsOrSettings); + return sync.read(path, settings); +} +exports.scandirSync = scandirSync; +function getSettings(settingsOrOptions = {}) { + if (settingsOrOptions instanceof settings_1.default) { + return settingsOrOptions; + } + return new settings_1.default(settingsOrOptions); +} - if (code === CHAR_QUESTION_MARK) { - isGlob = token.isGlob = true; - finished = true; - if (scanToEnd === true) { - continue; - } - break; - } +/***/ }), +/* 326 */ +/***/ (function(module, exports, __webpack_require__) { - if (code === CHAR_LEFT_SQUARE_BRACKET) { - while (eos() !== true && (next = advance())) { - if (next === CHAR_BACKWARD_SLASH) { - backslashes = token.backslashes = true; - advance(); - continue; - } +"use strict"; + +Object.defineProperty(exports, "__esModule", { value: true }); +const fsStat = __webpack_require__(317); +const rpl = __webpack_require__(327); +const constants_1 = __webpack_require__(328); +const utils = __webpack_require__(329); +function read(directory, settings, callback) { + if (!settings.stats && constants_1.IS_SUPPORT_READDIR_WITH_FILE_TYPES) { + return readdirWithFileTypes(directory, settings, callback); + } + return readdir(directory, settings, callback); +} +exports.read = read; +function readdirWithFileTypes(directory, settings, callback) { + settings.fs.readdir(directory, { withFileTypes: true }, (readdirError, dirents) => { + if (readdirError !== null) { + return callFailureCallback(callback, readdirError); + } + const entries = dirents.map((dirent) => ({ + dirent, + name: dirent.name, + path: `${directory}${settings.pathSegmentSeparator}${dirent.name}` + })); + if (!settings.followSymbolicLinks) { + return callSuccessCallback(callback, entries); + } + const tasks = entries.map((entry) => makeRplTaskEntry(entry, settings)); + rpl(tasks, (rplError, rplEntries) => { + if (rplError !== null) { + return callFailureCallback(callback, rplError); + } + callSuccessCallback(callback, rplEntries); + }); + }); +} +exports.readdirWithFileTypes = readdirWithFileTypes; +function makeRplTaskEntry(entry, settings) { + return (done) => { + if (!entry.dirent.isSymbolicLink()) { + return done(null, entry); + } + settings.fs.stat(entry.path, (statError, stats) => { + if (statError !== null) { + if (settings.throwErrorOnBrokenSymbolicLink) { + return done(statError); + } + return done(null, entry); + } + entry.dirent = utils.fs.createDirentFromStats(entry.name, stats); + return done(null, entry); + }); + }; +} +function readdir(directory, settings, callback) { + settings.fs.readdir(directory, (readdirError, names) => { + if (readdirError !== null) { + return callFailureCallback(callback, readdirError); + } + const filepaths = names.map((name) => `${directory}${settings.pathSegmentSeparator}${name}`); + const tasks = filepaths.map((filepath) => { + return (done) => fsStat.stat(filepath, settings.fsStatSettings, done); + }); + rpl(tasks, (rplError, results) => { + if (rplError !== null) { + return callFailureCallback(callback, rplError); + } + const entries = []; + names.forEach((name, index) => { + const stats = results[index]; + const entry = { + name, + path: filepaths[index], + dirent: utils.fs.createDirentFromStats(name, stats) + }; + if (settings.stats) { + entry.stats = stats; + } + entries.push(entry); + }); + callSuccessCallback(callback, entries); + }); + }); +} +exports.readdir = readdir; +function callFailureCallback(callback, error) { + callback(error); +} +function callSuccessCallback(callback, result) { + callback(null, result); +} - if (next === CHAR_RIGHT_SQUARE_BRACKET) { - isBracket = token.isBracket = true; - isGlob = token.isGlob = true; - finished = true; - if (scanToEnd === true) { - continue; - } - break; - } - } - } +/***/ }), +/* 327 */ +/***/ (function(module, exports) { - if (opts.nonegate !== true && code === CHAR_EXCLAMATION_MARK && index === start) { - negated = token.negated = true; - start++; - continue; - } +module.exports = runParallel - if (opts.noparen !== true && code === CHAR_LEFT_PARENTHESES) { - isGlob = token.isGlob = true; +function runParallel (tasks, cb) { + var results, pending, keys + var isSync = true - if (scanToEnd === true) { - while (eos() !== true && (code = advance())) { - if (code === CHAR_LEFT_PARENTHESES) { - backslashes = token.backslashes = true; - code = advance(); - continue; - } + if (Array.isArray(tasks)) { + results = [] + pending = tasks.length + } else { + keys = Object.keys(tasks) + results = {} + pending = keys.length + } - if (code === CHAR_RIGHT_PARENTHESES) { - finished = true; - break; - } - } - continue; - } - break; + function done (err) { + function end () { + if (cb) cb(err, results) + cb = null } + if (isSync) process.nextTick(end) + else end() + } - if (isGlob === true) { - finished = true; - - if (scanToEnd === true) { - continue; - } - - break; + function each (i, err, result) { + results[i] = result + if (--pending === 0 || err) { + done(err) } } - if (opts.noext === true) { - isExtglob = false; - isGlob = false; + if (!pending) { + // empty + done(null) + } else if (keys) { + // object + keys.forEach(function (key) { + tasks[key](function (err, result) { each(key, err, result) }) + }) + } else { + // array + tasks.forEach(function (task, i) { + task(function (err, result) { each(i, err, result) }) + }) } - let base = str; - let prefix = ''; - let glob = ''; + isSync = false +} - if (start > 0) { - prefix = str.slice(0, start); - str = str.slice(start); - lastIndex -= start; - } - if (base && isGlob === true && lastIndex > 0) { - base = str.slice(0, lastIndex); - glob = str.slice(lastIndex); - } else if (isGlob === true) { - base = ''; - glob = str; - } else { - base = str; - } +/***/ }), +/* 328 */ +/***/ (function(module, exports, __webpack_require__) { - if (base && base !== '' && base !== '/' && base !== str) { - if (isPathSeparator(base.charCodeAt(base.length - 1))) { - base = base.slice(0, -1); - } - } +"use strict"; + +Object.defineProperty(exports, "__esModule", { value: true }); +const NODE_PROCESS_VERSION_PARTS = process.versions.node.split('.'); +const MAJOR_VERSION = parseInt(NODE_PROCESS_VERSION_PARTS[0], 10); +const MINOR_VERSION = parseInt(NODE_PROCESS_VERSION_PARTS[1], 10); +const SUPPORTED_MAJOR_VERSION = 10; +const SUPPORTED_MINOR_VERSION = 10; +const IS_MATCHED_BY_MAJOR = MAJOR_VERSION > SUPPORTED_MAJOR_VERSION; +const IS_MATCHED_BY_MAJOR_AND_MINOR = MAJOR_VERSION === SUPPORTED_MAJOR_VERSION && MINOR_VERSION >= SUPPORTED_MINOR_VERSION; +/** + * IS `true` for Node.js 10.10 and greater. + */ +exports.IS_SUPPORT_READDIR_WITH_FILE_TYPES = IS_MATCHED_BY_MAJOR || IS_MATCHED_BY_MAJOR_AND_MINOR; - if (opts.unescape === true) { - if (glob) glob = utils.removeBackslashes(glob); - if (base && backslashes === true) { - base = utils.removeBackslashes(base); - } - } +/***/ }), +/* 329 */ +/***/ (function(module, exports, __webpack_require__) { - const state = { - prefix, - input, - start, - base, - glob, - isBrace, - isBracket, - isGlob, - isExtglob, - isGlobstar, - negated - }; +"use strict"; + +Object.defineProperty(exports, "__esModule", { value: true }); +const fs = __webpack_require__(330); +exports.fs = fs; - if (opts.tokens === true) { - state.maxDepth = 0; - if (!isPathSeparator(code)) { - tokens.push(token); - } - state.tokens = tokens; - } - if (opts.parts === true || opts.tokens === true) { - let prevIndex; +/***/ }), +/* 330 */ +/***/ (function(module, exports, __webpack_require__) { - for (let idx = 0; idx < slashes.length; idx++) { - const n = prevIndex ? prevIndex + 1 : start; - const i = slashes[idx]; - const value = input.slice(n, i); - if (opts.tokens) { - if (idx === 0 && start !== 0) { - tokens[idx].isPrefix = true; - tokens[idx].value = prefix; - } else { - tokens[idx].value = value; - } - depth(tokens[idx]); - state.maxDepth += tokens[idx].depth; - } - if (idx !== 0 || value !== '') { - parts.push(value); - } - prevIndex = i; - } +"use strict"; + +Object.defineProperty(exports, "__esModule", { value: true }); +class DirentFromStats { + constructor(name, stats) { + this.name = name; + this.isBlockDevice = stats.isBlockDevice.bind(stats); + this.isCharacterDevice = stats.isCharacterDevice.bind(stats); + this.isDirectory = stats.isDirectory.bind(stats); + this.isFIFO = stats.isFIFO.bind(stats); + this.isFile = stats.isFile.bind(stats); + this.isSocket = stats.isSocket.bind(stats); + this.isSymbolicLink = stats.isSymbolicLink.bind(stats); + } +} +function createDirentFromStats(name, stats) { + return new DirentFromStats(name, stats); +} +exports.createDirentFromStats = createDirentFromStats; - if (prevIndex && prevIndex + 1 < input.length) { - const value = input.slice(prevIndex + 1); - parts.push(value); - if (opts.tokens) { - tokens[tokens.length - 1].value = value; - depth(tokens[tokens.length - 1]); - state.maxDepth += tokens[tokens.length - 1].depth; - } - } +/***/ }), +/* 331 */ +/***/ (function(module, exports, __webpack_require__) { - state.slashes = slashes; - state.parts = parts; - } +"use strict"; + +Object.defineProperty(exports, "__esModule", { value: true }); +const fsStat = __webpack_require__(317); +const constants_1 = __webpack_require__(328); +const utils = __webpack_require__(329); +function read(directory, settings) { + if (!settings.stats && constants_1.IS_SUPPORT_READDIR_WITH_FILE_TYPES) { + return readdirWithFileTypes(directory, settings); + } + return readdir(directory, settings); +} +exports.read = read; +function readdirWithFileTypes(directory, settings) { + const dirents = settings.fs.readdirSync(directory, { withFileTypes: true }); + return dirents.map((dirent) => { + const entry = { + dirent, + name: dirent.name, + path: `${directory}${settings.pathSegmentSeparator}${dirent.name}` + }; + if (entry.dirent.isSymbolicLink() && settings.followSymbolicLinks) { + try { + const stats = settings.fs.statSync(entry.path); + entry.dirent = utils.fs.createDirentFromStats(entry.name, stats); + } + catch (error) { + if (settings.throwErrorOnBrokenSymbolicLink) { + throw error; + } + } + } + return entry; + }); +} +exports.readdirWithFileTypes = readdirWithFileTypes; +function readdir(directory, settings) { + const names = settings.fs.readdirSync(directory); + return names.map((name) => { + const entryPath = `${directory}${settings.pathSegmentSeparator}${name}`; + const stats = fsStat.statSync(entryPath, settings.fsStatSettings); + const entry = { + name, + path: entryPath, + dirent: utils.fs.createDirentFromStats(name, stats) + }; + if (settings.stats) { + entry.stats = stats; + } + return entry; + }); +} +exports.readdir = readdir; - return state; -}; -module.exports = scan; +/***/ }), +/* 332 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +Object.defineProperty(exports, "__esModule", { value: true }); +const path = __webpack_require__(4); +const fsStat = __webpack_require__(317); +const fs = __webpack_require__(333); +class Settings { + constructor(_options = {}) { + this._options = _options; + this.followSymbolicLinks = this._getValue(this._options.followSymbolicLinks, false); + this.fs = fs.createFileSystemAdapter(this._options.fs); + this.pathSegmentSeparator = this._getValue(this._options.pathSegmentSeparator, path.sep); + this.stats = this._getValue(this._options.stats, false); + this.throwErrorOnBrokenSymbolicLink = this._getValue(this._options.throwErrorOnBrokenSymbolicLink, true); + this.fsStatSettings = new fsStat.Settings({ + followSymbolicLink: this.followSymbolicLinks, + fs: this.fs, + throwErrorOnBrokenSymbolicLink: this.throwErrorOnBrokenSymbolicLink + }); + } + _getValue(option, value) { + return option === undefined ? value : option; + } +} +exports.default = Settings; /***/ }), -/* 317 */ +/* 333 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; + +Object.defineProperty(exports, "__esModule", { value: true }); +const fs = __webpack_require__(134); +exports.FILE_SYSTEM_ADAPTER = { + lstat: fs.lstat, + stat: fs.stat, + lstatSync: fs.lstatSync, + statSync: fs.statSync, + readdir: fs.readdir, + readdirSync: fs.readdirSync +}; +function createFileSystemAdapter(fsMethods) { + if (fsMethods === undefined) { + return exports.FILE_SYSTEM_ADAPTER; + } + return Object.assign(Object.assign({}, exports.FILE_SYSTEM_ADAPTER), fsMethods); +} +exports.createFileSystemAdapter = createFileSystemAdapter; -const path = __webpack_require__(4); -const win32 = process.platform === 'win32'; -const { - REGEX_BACKSLASH, - REGEX_REMOVE_BACKSLASH, - REGEX_SPECIAL_CHARS, - REGEX_SPECIAL_CHARS_GLOBAL -} = __webpack_require__(318); +/***/ }), +/* 334 */ +/***/ (function(module, exports, __webpack_require__) { -exports.isObject = val => val !== null && typeof val === 'object' && !Array.isArray(val); -exports.hasRegexChars = str => REGEX_SPECIAL_CHARS.test(str); -exports.isRegexChar = str => str.length === 1 && exports.hasRegexChars(str); -exports.escapeRegex = str => str.replace(REGEX_SPECIAL_CHARS_GLOBAL, '\\$1'); -exports.toPosixSlashes = str => str.replace(REGEX_BACKSLASH, '/'); +"use strict"; -exports.removeBackslashes = str => { - return str.replace(REGEX_REMOVE_BACKSLASH, match => { - return match === '\\' ? '' : match; - }); -}; -exports.supportsLookbehinds = () => { - const segs = process.version.slice(1).split('.').map(Number); - if (segs.length === 3 && segs[0] >= 9 || (segs[0] === 8 && segs[1] >= 10)) { - return true; - } - return false; -}; +var reusify = __webpack_require__(335) -exports.isWindows = options => { - if (options && typeof options.windows === 'boolean') { - return options.windows; +function fastqueue (context, worker, concurrency) { + if (typeof context === 'function') { + concurrency = worker + worker = context + context = null } - return win32 === true || path.sep === '\\'; -}; -exports.escapeLast = (input, char, lastIdx) => { - const idx = input.lastIndexOf(char, lastIdx); - if (idx === -1) return input; - if (input[idx - 1] === '\\') return exports.escapeLast(input, char, idx - 1); - return `${input.slice(0, idx)}\\${input.slice(idx)}`; -}; + var cache = reusify(Task) + var queueHead = null + var queueTail = null + var _running = 0 -exports.removePrefix = (input, state = {}) => { - let output = input; - if (output.startsWith('./')) { - output = output.slice(2); - state.prefix = './'; + var self = { + push: push, + drain: noop, + saturated: noop, + pause: pause, + paused: false, + concurrency: concurrency, + running: running, + resume: resume, + idle: idle, + length: length, + unshift: unshift, + empty: noop, + kill: kill, + killAndDrain: killAndDrain } - return output; -}; -exports.wrapOutput = (input, state = {}, options = {}) => { - const prepend = options.contains ? '' : '^'; - const append = options.contains ? '' : '$'; + return self - let output = `${prepend}(?:${input})${append}`; - if (state.negated === true) { - output = `(?:^(?!${output}).*$)`; + function running () { + return _running } - return output; -}; + function pause () { + self.paused = true + } -/***/ }), -/* 318 */ -/***/ (function(module, exports, __webpack_require__) { + function length () { + var current = queueHead + var counter = 0 -"use strict"; + while (current) { + current = current.next + counter++ + } + return counter + } -const path = __webpack_require__(4); -const WIN_SLASH = '\\\\/'; -const WIN_NO_SLASH = `[^${WIN_SLASH}]`; + function resume () { + if (!self.paused) return + self.paused = false + for (var i = 0; i < self.concurrency; i++) { + _running++ + release() + } + } -/** - * Posix glob regex - */ + function idle () { + return _running === 0 && self.length() === 0 + } -const DOT_LITERAL = '\\.'; -const PLUS_LITERAL = '\\+'; -const QMARK_LITERAL = '\\?'; -const SLASH_LITERAL = '\\/'; -const ONE_CHAR = '(?=.)'; -const QMARK = '[^/]'; -const END_ANCHOR = `(?:${SLASH_LITERAL}|$)`; -const START_ANCHOR = `(?:^|${SLASH_LITERAL})`; -const DOTS_SLASH = `${DOT_LITERAL}{1,2}${END_ANCHOR}`; -const NO_DOT = `(?!${DOT_LITERAL})`; -const NO_DOTS = `(?!${START_ANCHOR}${DOTS_SLASH})`; -const NO_DOT_SLASH = `(?!${DOT_LITERAL}{0,1}${END_ANCHOR})`; -const NO_DOTS_SLASH = `(?!${DOTS_SLASH})`; -const QMARK_NO_DOT = `[^.${SLASH_LITERAL}]`; -const STAR = `${QMARK}*?`; + function push (value, done) { + var current = cache.get() -const POSIX_CHARS = { - DOT_LITERAL, - PLUS_LITERAL, - QMARK_LITERAL, - SLASH_LITERAL, - ONE_CHAR, - QMARK, - END_ANCHOR, - DOTS_SLASH, - NO_DOT, - NO_DOTS, - NO_DOT_SLASH, - NO_DOTS_SLASH, - QMARK_NO_DOT, - STAR, - START_ANCHOR -}; + current.context = context + current.release = release + current.value = value + current.callback = done || noop -/** - * Windows glob regex - */ + if (_running === self.concurrency || self.paused) { + if (queueTail) { + queueTail.next = current + queueTail = current + } else { + queueHead = current + queueTail = current + self.saturated() + } + } else { + _running++ + worker.call(context, current.value, current.worked) + } + } -const WINDOWS_CHARS = { - ...POSIX_CHARS, + function unshift (value, done) { + var current = cache.get() - SLASH_LITERAL: `[${WIN_SLASH}]`, - QMARK: WIN_NO_SLASH, - STAR: `${WIN_NO_SLASH}*?`, - DOTS_SLASH: `${DOT_LITERAL}{1,2}(?:[${WIN_SLASH}]|$)`, - NO_DOT: `(?!${DOT_LITERAL})`, - NO_DOTS: `(?!(?:^|[${WIN_SLASH}])${DOT_LITERAL}{1,2}(?:[${WIN_SLASH}]|$))`, - NO_DOT_SLASH: `(?!${DOT_LITERAL}{0,1}(?:[${WIN_SLASH}]|$))`, - NO_DOTS_SLASH: `(?!${DOT_LITERAL}{1,2}(?:[${WIN_SLASH}]|$))`, - QMARK_NO_DOT: `[^.${WIN_SLASH}]`, - START_ANCHOR: `(?:^|[${WIN_SLASH}])`, - END_ANCHOR: `(?:[${WIN_SLASH}]|$)` -}; + current.context = context + current.release = release + current.value = value + current.callback = done || noop -/** - * POSIX Bracket Regex - */ + if (_running === self.concurrency || self.paused) { + if (queueHead) { + current.next = queueHead + queueHead = current + } else { + queueHead = current + queueTail = current + self.saturated() + } + } else { + _running++ + worker.call(context, current.value, current.worked) + } + } -const POSIX_REGEX_SOURCE = { - alnum: 'a-zA-Z0-9', - alpha: 'a-zA-Z', - ascii: '\\x00-\\x7F', - blank: ' \\t', - cntrl: '\\x00-\\x1F\\x7F', - digit: '0-9', - graph: '\\x21-\\x7E', - lower: 'a-z', - print: '\\x20-\\x7E ', - punct: '\\-!"#$%&\'()\\*+,./:;<=>?@[\\]^_`{|}~', - space: ' \\t\\r\\n\\v\\f', - upper: 'A-Z', - word: 'A-Za-z0-9_', - xdigit: 'A-Fa-f0-9' -}; + function release (holder) { + if (holder) { + cache.release(holder) + } + var next = queueHead + if (next) { + if (!self.paused) { + if (queueTail === queueHead) { + queueTail = null + } + queueHead = next.next + next.next = null + worker.call(context, next.value, next.worked) + if (queueTail === null) { + self.empty() + } + } else { + _running-- + } + } else if (--_running === 0) { + self.drain() + } + } -module.exports = { - MAX_LENGTH: 1024 * 64, - POSIX_REGEX_SOURCE, + function kill () { + queueHead = null + queueTail = null + self.drain = noop + } - // regular expressions - REGEX_BACKSLASH: /\\(?![*+?^${}(|)[\]])/g, - REGEX_NON_SPECIAL_CHARS: /^[^@![\].,$*+?^{}()|\\/]+/, - REGEX_SPECIAL_CHARS: /[-*+?.^${}(|)[\]]/, - REGEX_SPECIAL_CHARS_BACKREF: /(\\?)((\W)(\3*))/g, - REGEX_SPECIAL_CHARS_GLOBAL: /([-*+?.^${}(|)[\]])/g, - REGEX_REMOVE_BACKSLASH: /(?:\[.*?[^\\]\]|\\(?=.))/g, + function killAndDrain () { + queueHead = null + queueTail = null + self.drain() + self.drain = noop + } +} - // Replace globs with equivalent patterns to reduce parsing time. - REPLACEMENTS: { - '***': '*', - '**/**': '**', - '**/**/**': '**' - }, +function noop () {} - // Digits - CHAR_0: 48, /* 0 */ - CHAR_9: 57, /* 9 */ +function Task () { + this.value = null + this.callback = noop + this.next = null + this.release = noop + this.context = null - // Alphabet chars. - CHAR_UPPERCASE_A: 65, /* A */ - CHAR_LOWERCASE_A: 97, /* a */ - CHAR_UPPERCASE_Z: 90, /* Z */ - CHAR_LOWERCASE_Z: 122, /* z */ + var self = this - CHAR_LEFT_PARENTHESES: 40, /* ( */ - CHAR_RIGHT_PARENTHESES: 41, /* ) */ + this.worked = function worked (err, result) { + var callback = self.callback + self.value = null + self.callback = noop + callback.call(self.context, err, result) + self.release(self) + } +} - CHAR_ASTERISK: 42, /* * */ +module.exports = fastqueue - // Non-alphabetic chars. - CHAR_AMPERSAND: 38, /* & */ - CHAR_AT: 64, /* @ */ - CHAR_BACKWARD_SLASH: 92, /* \ */ - CHAR_CARRIAGE_RETURN: 13, /* \r */ - CHAR_CIRCUMFLEX_ACCENT: 94, /* ^ */ - CHAR_COLON: 58, /* : */ - CHAR_COMMA: 44, /* , */ - CHAR_DOT: 46, /* . */ - CHAR_DOUBLE_QUOTE: 34, /* " */ - CHAR_EQUAL: 61, /* = */ - CHAR_EXCLAMATION_MARK: 33, /* ! */ - CHAR_FORM_FEED: 12, /* \f */ - CHAR_FORWARD_SLASH: 47, /* / */ - CHAR_GRAVE_ACCENT: 96, /* ` */ - CHAR_HASH: 35, /* # */ - CHAR_HYPHEN_MINUS: 45, /* - */ - CHAR_LEFT_ANGLE_BRACKET: 60, /* < */ - CHAR_LEFT_CURLY_BRACE: 123, /* { */ - CHAR_LEFT_SQUARE_BRACKET: 91, /* [ */ - CHAR_LINE_FEED: 10, /* \n */ - CHAR_NO_BREAK_SPACE: 160, /* \u00A0 */ - CHAR_PERCENT: 37, /* % */ - CHAR_PLUS: 43, /* + */ - CHAR_QUESTION_MARK: 63, /* ? */ - CHAR_RIGHT_ANGLE_BRACKET: 62, /* > */ - CHAR_RIGHT_CURLY_BRACE: 125, /* } */ - CHAR_RIGHT_SQUARE_BRACKET: 93, /* ] */ - CHAR_SEMICOLON: 59, /* ; */ - CHAR_SINGLE_QUOTE: 39, /* ' */ - CHAR_SPACE: 32, /* */ - CHAR_TAB: 9, /* \t */ - CHAR_UNDERSCORE: 95, /* _ */ - CHAR_VERTICAL_LINE: 124, /* | */ - CHAR_ZERO_WIDTH_NOBREAK_SPACE: 65279, /* \uFEFF */ - SEP: path.sep, +/***/ }), +/* 335 */ +/***/ (function(module, exports, __webpack_require__) { - /** - * Create EXTGLOB_CHARS - */ +"use strict"; - extglobChars(chars) { - return { - '!': { type: 'negate', open: '(?:(?!(?:', close: `))${chars.STAR})` }, - '?': { type: 'qmark', open: '(?:', close: ')?' }, - '+': { type: 'plus', open: '(?:', close: ')+' }, - '*': { type: 'star', open: '(?:', close: ')*' }, - '@': { type: 'at', open: '(?:', close: ')' } - }; - }, - /** - * Create GLOB_CHARS - */ +function reusify (Constructor) { + var head = new Constructor() + var tail = head - globChars(win32) { - return win32 === true ? WINDOWS_CHARS : POSIX_CHARS; - } -}; - - -/***/ }), -/* 319 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -const constants = __webpack_require__(318); -const utils = __webpack_require__(317); - -/** - * Constants - */ + function get () { + var current = head -const { - MAX_LENGTH, - POSIX_REGEX_SOURCE, - REGEX_NON_SPECIAL_CHARS, - REGEX_SPECIAL_CHARS_BACKREF, - REPLACEMENTS -} = constants; + if (current.next) { + head = current.next + } else { + head = new Constructor() + tail = head + } -/** - * Helpers - */ + current.next = null -const expandRange = (args, options) => { - if (typeof options.expandRange === 'function') { - return options.expandRange(...args, options); + return current } - args.sort(); - const value = `[${args.join('-')}]`; + function release (obj) { + tail.next = obj + tail = obj + } - try { - /* eslint-disable-next-line no-new */ - new RegExp(value); - } catch (ex) { - return args.map(v => utils.escapeRegex(v)).join('..'); + return { + get: get, + release: release } +} - return value; -}; +module.exports = reusify -/** - * Create the message for a syntax error - */ -const syntaxError = (type, char) => { - return `Missing ${type}: "${char}" - use "\\\\${char}" to match literal characters`; -}; +/***/ }), +/* 336 */ +/***/ (function(module, exports, __webpack_require__) { -/** - * Parse the given input string. - * @param {String} input - * @param {Object} options - * @return {Object} - */ +"use strict"; + +Object.defineProperty(exports, "__esModule", { value: true }); +function isFatalError(settings, error) { + if (settings.errorFilter === null) { + return true; + } + return !settings.errorFilter(error); +} +exports.isFatalError = isFatalError; +function isAppliedFilter(filter, value) { + return filter === null || filter(value); +} +exports.isAppliedFilter = isAppliedFilter; +function replacePathSegmentSeparator(filepath, separator) { + return filepath.split(/[\\/]/).join(separator); +} +exports.replacePathSegmentSeparator = replacePathSegmentSeparator; +function joinPathSegments(a, b, separator) { + if (a === '') { + return b; + } + return a + separator + b; +} +exports.joinPathSegments = joinPathSegments; -const parse = (input, options) => { - if (typeof input !== 'string') { - throw new TypeError('Expected a string'); - } - input = REPLACEMENTS[input] || input; +/***/ }), +/* 337 */ +/***/ (function(module, exports, __webpack_require__) { - const opts = { ...options }; - const max = typeof opts.maxLength === 'number' ? Math.min(MAX_LENGTH, opts.maxLength) : MAX_LENGTH; +"use strict"; + +Object.defineProperty(exports, "__esModule", { value: true }); +const common = __webpack_require__(336); +class Reader { + constructor(_root, _settings) { + this._root = _root; + this._settings = _settings; + this._root = common.replacePathSegmentSeparator(_root, _settings.pathSegmentSeparator); + } +} +exports.default = Reader; - let len = input.length; - if (len > max) { - throw new SyntaxError(`Input length: ${len}, exceeds maximum allowed length: ${max}`); - } - const bos = { type: 'bos', value: '', output: opts.prepend || '' }; - const tokens = [bos]; +/***/ }), +/* 338 */ +/***/ (function(module, exports, __webpack_require__) { - const capture = opts.capture ? '' : '?:'; - const win32 = utils.isWindows(options); +"use strict"; + +Object.defineProperty(exports, "__esModule", { value: true }); +const stream_1 = __webpack_require__(138); +const async_1 = __webpack_require__(324); +class StreamProvider { + constructor(_root, _settings) { + this._root = _root; + this._settings = _settings; + this._reader = new async_1.default(this._root, this._settings); + this._stream = new stream_1.Readable({ + objectMode: true, + read: () => { }, + destroy: this._reader.destroy.bind(this._reader) + }); + } + read() { + this._reader.onError((error) => { + this._stream.emit('error', error); + }); + this._reader.onEntry((entry) => { + this._stream.push(entry); + }); + this._reader.onEnd(() => { + this._stream.push(null); + }); + this._reader.read(); + return this._stream; + } +} +exports.default = StreamProvider; - // create constants based on platform, for windows or posix - const PLATFORM_CHARS = constants.globChars(win32); - const EXTGLOB_CHARS = constants.extglobChars(PLATFORM_CHARS); - const { - DOT_LITERAL, - PLUS_LITERAL, - SLASH_LITERAL, - ONE_CHAR, - DOTS_SLASH, - NO_DOT, - NO_DOT_SLASH, - NO_DOTS_SLASH, - QMARK, - QMARK_NO_DOT, - STAR, - START_ANCHOR - } = PLATFORM_CHARS; +/***/ }), +/* 339 */ +/***/ (function(module, exports, __webpack_require__) { - const globstar = (opts) => { - return `(${capture}(?:(?!${START_ANCHOR}${opts.dot ? DOTS_SLASH : DOT_LITERAL}).)*?)`; - }; +"use strict"; + +Object.defineProperty(exports, "__esModule", { value: true }); +const sync_1 = __webpack_require__(340); +class SyncProvider { + constructor(_root, _settings) { + this._root = _root; + this._settings = _settings; + this._reader = new sync_1.default(this._root, this._settings); + } + read() { + return this._reader.read(); + } +} +exports.default = SyncProvider; - const nodot = opts.dot ? '' : NO_DOT; - const qmarkNoDot = opts.dot ? QMARK : QMARK_NO_DOT; - let star = opts.bash === true ? globstar(opts) : STAR; - if (opts.capture) { - star = `(${star})`; - } +/***/ }), +/* 340 */ +/***/ (function(module, exports, __webpack_require__) { - // minimatch options support - if (typeof opts.noext === 'boolean') { - opts.noextglob = opts.noext; - } +"use strict"; + +Object.defineProperty(exports, "__esModule", { value: true }); +const fsScandir = __webpack_require__(325); +const common = __webpack_require__(336); +const reader_1 = __webpack_require__(337); +class SyncReader extends reader_1.default { + constructor() { + super(...arguments); + this._scandir = fsScandir.scandirSync; + this._storage = new Set(); + this._queue = new Set(); + } + read() { + this._pushToQueue(this._root, this._settings.basePath); + this._handleQueue(); + return [...this._storage]; + } + _pushToQueue(directory, base) { + this._queue.add({ directory, base }); + } + _handleQueue() { + for (const item of this._queue.values()) { + this._handleDirectory(item.directory, item.base); + } + } + _handleDirectory(directory, base) { + try { + const entries = this._scandir(directory, this._settings.fsScandirSettings); + for (const entry of entries) { + this._handleEntry(entry, base); + } + } + catch (error) { + this._handleError(error); + } + } + _handleError(error) { + if (!common.isFatalError(this._settings, error)) { + return; + } + throw error; + } + _handleEntry(entry, base) { + const fullpath = entry.path; + if (base !== undefined) { + entry.path = common.joinPathSegments(base, entry.name, this._settings.pathSegmentSeparator); + } + if (common.isAppliedFilter(this._settings.entryFilter, entry)) { + this._pushToStorage(entry); + } + if (entry.dirent.isDirectory() && common.isAppliedFilter(this._settings.deepFilter, entry)) { + this._pushToQueue(fullpath, entry.path); + } + } + _pushToStorage(entry) { + this._storage.add(entry); + } +} +exports.default = SyncReader; - const state = { - input, - index: -1, - start: 0, - dot: opts.dot === true, - consumed: '', - output: '', - prefix: '', - backtrack: false, - negated: false, - brackets: 0, - braces: 0, - parens: 0, - quotes: 0, - globstar: false, - tokens - }; - input = utils.removePrefix(input, state); - len = input.length; +/***/ }), +/* 341 */ +/***/ (function(module, exports, __webpack_require__) { - const extglobs = []; - const braces = []; - const stack = []; - let prev = bos; - let value; +"use strict"; + +Object.defineProperty(exports, "__esModule", { value: true }); +const path = __webpack_require__(4); +const fsScandir = __webpack_require__(325); +class Settings { + constructor(_options = {}) { + this._options = _options; + this.basePath = this._getValue(this._options.basePath, undefined); + this.concurrency = this._getValue(this._options.concurrency, Infinity); + this.deepFilter = this._getValue(this._options.deepFilter, null); + this.entryFilter = this._getValue(this._options.entryFilter, null); + this.errorFilter = this._getValue(this._options.errorFilter, null); + this.pathSegmentSeparator = this._getValue(this._options.pathSegmentSeparator, path.sep); + this.fsScandirSettings = new fsScandir.Settings({ + followSymbolicLinks: this._options.followSymbolicLinks, + fs: this._options.fs, + pathSegmentSeparator: this._options.pathSegmentSeparator, + stats: this._options.stats, + throwErrorOnBrokenSymbolicLink: this._options.throwErrorOnBrokenSymbolicLink + }); + } + _getValue(option, value) { + return option === undefined ? value : option; + } +} +exports.default = Settings; - /** - * Tokenizing helpers - */ - const eos = () => state.index === len - 1; - const peek = state.peek = (n = 1) => input[state.index + n]; - const advance = state.advance = () => input[++state.index]; - const remaining = () => input.slice(state.index + 1); - const consume = (value = '', num = 0) => { - state.consumed += value; - state.index += num; - }; - const append = token => { - state.output += token.output != null ? token.output : token.value; - consume(token.value); - }; +/***/ }), +/* 342 */ +/***/ (function(module, exports, __webpack_require__) { - const negate = () => { - let count = 1; +"use strict"; + +Object.defineProperty(exports, "__esModule", { value: true }); +const path = __webpack_require__(4); +const fsStat = __webpack_require__(317); +const utils = __webpack_require__(287); +class Reader { + constructor(_settings) { + this._settings = _settings; + this._fsStatSettings = new fsStat.Settings({ + followSymbolicLink: this._settings.followSymbolicLinks, + fs: this._settings.fs, + throwErrorOnBrokenSymbolicLink: this._settings.followSymbolicLinks + }); + } + _getFullEntryPath(filepath) { + return path.resolve(this._settings.cwd, filepath); + } + _makeEntry(stats, pattern) { + const entry = { + name: pattern, + path: pattern, + dirent: utils.fs.createDirentFromStats(pattern, stats) + }; + if (this._settings.stats) { + entry.stats = stats; + } + return entry; + } + _isFatalError(error) { + return !utils.errno.isEnoentCodeError(error) && !this._settings.suppressErrors; + } +} +exports.default = Reader; - while (peek() === '!' && (peek(2) !== '(' || peek(3) === '?')) { - advance(); - state.start++; - count++; - } - if (count % 2 === 0) { - return false; - } +/***/ }), +/* 343 */ +/***/ (function(module, exports, __webpack_require__) { - state.negated = true; - state.start++; - return true; - }; +"use strict"; + +Object.defineProperty(exports, "__esModule", { value: true }); +const path = __webpack_require__(4); +const deep_1 = __webpack_require__(344); +const entry_1 = __webpack_require__(347); +const error_1 = __webpack_require__(348); +const entry_2 = __webpack_require__(349); +class Provider { + constructor(_settings) { + this._settings = _settings; + this.errorFilter = new error_1.default(this._settings); + this.entryFilter = new entry_1.default(this._settings, this._getMicromatchOptions()); + this.deepFilter = new deep_1.default(this._settings, this._getMicromatchOptions()); + this.entryTransformer = new entry_2.default(this._settings); + } + _getRootDirectory(task) { + return path.resolve(this._settings.cwd, task.base); + } + _getReaderOptions(task) { + const basePath = task.base === '.' ? '' : task.base; + return { + basePath, + pathSegmentSeparator: '/', + concurrency: this._settings.concurrency, + deepFilter: this.deepFilter.getFilter(basePath, task.positive, task.negative), + entryFilter: this.entryFilter.getFilter(task.positive, task.negative), + errorFilter: this.errorFilter.getFilter(), + followSymbolicLinks: this._settings.followSymbolicLinks, + fs: this._settings.fs, + stats: this._settings.stats, + throwErrorOnBrokenSymbolicLink: this._settings.throwErrorOnBrokenSymbolicLink, + transform: this.entryTransformer.getTransformer() + }; + } + _getMicromatchOptions() { + return { + dot: this._settings.dot, + matchBase: this._settings.baseNameMatch, + nobrace: !this._settings.braceExpansion, + nocase: !this._settings.caseSensitiveMatch, + noext: !this._settings.extglob, + noglobstar: !this._settings.globstar, + posix: true, + strictSlashes: false + }; + } +} +exports.default = Provider; - const increment = type => { - state[type]++; - stack.push(type); - }; - const decrement = type => { - state[type]--; - stack.pop(); - }; +/***/ }), +/* 344 */ +/***/ (function(module, exports, __webpack_require__) { - /** - * Push tokens onto the tokens array. This helper speeds up - * tokenizing by 1) helping us avoid backtracking as much as possible, - * and 2) helping us avoid creating extra tokens when consecutive - * characters are plain text. This improves performance and simplifies - * lookbehinds. - */ +"use strict"; + +Object.defineProperty(exports, "__esModule", { value: true }); +const utils = __webpack_require__(287); +const partial_1 = __webpack_require__(345); +class DeepFilter { + constructor(_settings, _micromatchOptions) { + this._settings = _settings; + this._micromatchOptions = _micromatchOptions; + } + getFilter(basePath, positive, negative) { + const matcher = this._getMatcher(positive); + const negativeRe = this._getNegativePatternsRe(negative); + return (entry) => this._filter(basePath, entry, matcher, negativeRe); + } + _getMatcher(patterns) { + return new partial_1.default(patterns, this._settings, this._micromatchOptions); + } + _getNegativePatternsRe(patterns) { + const affectDepthOfReadingPatterns = patterns.filter(utils.pattern.isAffectDepthOfReadingPattern); + return utils.pattern.convertPatternsToRe(affectDepthOfReadingPatterns, this._micromatchOptions); + } + _filter(basePath, entry, matcher, negativeRe) { + const depth = this._getEntryLevel(basePath, entry.path); + if (this._isSkippedByDeep(depth)) { + return false; + } + if (this._isSkippedSymbolicLink(entry)) { + return false; + } + const filepath = utils.path.removeLeadingDotSegment(entry.path); + if (this._isSkippedByPositivePatterns(filepath, matcher)) { + return false; + } + return this._isSkippedByNegativePatterns(filepath, negativeRe); + } + _isSkippedByDeep(entryDepth) { + return entryDepth >= this._settings.deep; + } + _isSkippedSymbolicLink(entry) { + return !this._settings.followSymbolicLinks && entry.dirent.isSymbolicLink(); + } + _getEntryLevel(basePath, entryPath) { + const basePathDepth = basePath.split('/').length; + const entryPathDepth = entryPath.split('/').length; + return entryPathDepth - (basePath === '' ? 0 : basePathDepth); + } + _isSkippedByPositivePatterns(entryPath, matcher) { + return !this._settings.baseNameMatch && !matcher.match(entryPath); + } + _isSkippedByNegativePatterns(entryPath, negativeRe) { + return !utils.pattern.matchAny(entryPath, negativeRe); + } +} +exports.default = DeepFilter; - const push = tok => { - if (prev.type === 'globstar') { - const isBrace = state.braces > 0 && (tok.type === 'comma' || tok.type === 'brace'); - const isExtglob = tok.extglob === true || (extglobs.length && (tok.type === 'pipe' || tok.type === 'paren')); - if (tok.type !== 'slash' && tok.type !== 'paren' && !isBrace && !isExtglob) { - state.output = state.output.slice(0, -prev.output.length); - prev.type = 'star'; - prev.value = '*'; - prev.output = star; - state.output += prev.output; - } - } +/***/ }), +/* 345 */ +/***/ (function(module, exports, __webpack_require__) { - if (extglobs.length && tok.type !== 'paren' && !EXTGLOB_CHARS[tok.value]) { - extglobs[extglobs.length - 1].inner += tok.value; - } +"use strict"; + +Object.defineProperty(exports, "__esModule", { value: true }); +const matcher_1 = __webpack_require__(346); +class PartialMatcher extends matcher_1.default { + match(filepath) { + const parts = filepath.split('/'); + const levels = parts.length; + const patterns = this._storage.filter((info) => !info.complete || info.segments.length > levels); + for (const pattern of patterns) { + const section = pattern.sections[0]; + /** + * In this case, the pattern has a globstar and we must read all directories unconditionally, + * but only if the level has reached the end of the first group. + * + * fixtures/{a,b}/** + * ^ true/false ^ always true + */ + if (!pattern.complete && levels > section.length) { + return true; + } + const match = parts.every((part, index) => { + const segment = pattern.segments[index]; + if (segment.dynamic && segment.patternRe.test(part)) { + return true; + } + if (!segment.dynamic && segment.pattern === part) { + return true; + } + return false; + }); + if (match) { + return true; + } + } + return false; + } +} +exports.default = PartialMatcher; - if (tok.value || tok.output) append(tok); - if (prev && prev.type === 'text' && tok.type === 'text') { - prev.value += tok.value; - prev.output = (prev.output || '') + tok.value; - return; - } - tok.prev = prev; - tokens.push(tok); - prev = tok; - }; +/***/ }), +/* 346 */ +/***/ (function(module, exports, __webpack_require__) { - const extglobOpen = (type, value) => { - const token = { ...EXTGLOB_CHARS[value], conditions: 1, inner: '' }; +"use strict"; + +Object.defineProperty(exports, "__esModule", { value: true }); +const utils = __webpack_require__(287); +class Matcher { + constructor(_patterns, _settings, _micromatchOptions) { + this._patterns = _patterns; + this._settings = _settings; + this._micromatchOptions = _micromatchOptions; + this._storage = []; + this._fillStorage(); + } + _fillStorage() { + /** + * The original pattern may include `{,*,**,a/*}`, which will lead to problems with matching (unresolved level). + * So, before expand patterns with brace expansion into separated patterns. + */ + const patterns = utils.pattern.expandPatternsWithBraceExpansion(this._patterns); + for (const pattern of patterns) { + const segments = this._getPatternSegments(pattern); + const sections = this._splitSegmentsIntoSections(segments); + this._storage.push({ + complete: sections.length <= 1, + pattern, + segments, + sections + }); + } + } + _getPatternSegments(pattern) { + const parts = utils.pattern.getPatternParts(pattern, this._micromatchOptions); + return parts.map((part) => { + const dynamic = utils.pattern.isDynamicPattern(part, this._settings); + if (!dynamic) { + return { + dynamic: false, + pattern: part + }; + } + return { + dynamic: true, + pattern: part, + patternRe: utils.pattern.makeRe(part, this._micromatchOptions) + }; + }); + } + _splitSegmentsIntoSections(segments) { + return utils.array.splitWhen(segments, (segment) => segment.dynamic && utils.pattern.hasGlobStar(segment.pattern)); + } +} +exports.default = Matcher; - token.prev = prev; - token.parens = state.parens; - token.output = state.output; - const output = (opts.capture ? '(' : '') + token.open; - increment('parens'); - push({ type, value, output: state.output ? '' : ONE_CHAR }); - push({ type: 'paren', extglob: true, value: advance(), output }); - extglobs.push(token); - }; +/***/ }), +/* 347 */ +/***/ (function(module, exports, __webpack_require__) { - const extglobClose = token => { - let output = token.close + (opts.capture ? ')' : ''); +"use strict"; + +Object.defineProperty(exports, "__esModule", { value: true }); +const utils = __webpack_require__(287); +class EntryFilter { + constructor(_settings, _micromatchOptions) { + this._settings = _settings; + this._micromatchOptions = _micromatchOptions; + this.index = new Map(); + } + getFilter(positive, negative) { + const positiveRe = utils.pattern.convertPatternsToRe(positive, this._micromatchOptions); + const negativeRe = utils.pattern.convertPatternsToRe(negative, this._micromatchOptions); + return (entry) => this._filter(entry, positiveRe, negativeRe); + } + _filter(entry, positiveRe, negativeRe) { + if (this._settings.unique) { + if (this._isDuplicateEntry(entry)) { + return false; + } + this._createIndexRecord(entry); + } + if (this._onlyFileFilter(entry) || this._onlyDirectoryFilter(entry)) { + return false; + } + if (this._isSkippedByAbsoluteNegativePatterns(entry, negativeRe)) { + return false; + } + const filepath = this._settings.baseNameMatch ? entry.name : entry.path; + return this._isMatchToPatterns(filepath, positiveRe) && !this._isMatchToPatterns(entry.path, negativeRe); + } + _isDuplicateEntry(entry) { + return this.index.has(entry.path); + } + _createIndexRecord(entry) { + this.index.set(entry.path, undefined); + } + _onlyFileFilter(entry) { + return this._settings.onlyFiles && !entry.dirent.isFile(); + } + _onlyDirectoryFilter(entry) { + return this._settings.onlyDirectories && !entry.dirent.isDirectory(); + } + _isSkippedByAbsoluteNegativePatterns(entry, negativeRe) { + if (!this._settings.absolute) { + return false; + } + const fullpath = utils.path.makeAbsolute(this._settings.cwd, entry.path); + return this._isMatchToPatterns(fullpath, negativeRe); + } + _isMatchToPatterns(entryPath, patternsRe) { + const filepath = utils.path.removeLeadingDotSegment(entryPath); + return utils.pattern.matchAny(filepath, patternsRe); + } +} +exports.default = EntryFilter; - if (token.type === 'negate') { - let extglobStar = star; - if (token.inner && token.inner.length > 1 && token.inner.includes('/')) { - extglobStar = globstar(opts); - } +/***/ }), +/* 348 */ +/***/ (function(module, exports, __webpack_require__) { - if (extglobStar !== star || eos() || /^\)+$/.test(remaining())) { - output = token.close = `)$))${extglobStar}`; - } +"use strict"; + +Object.defineProperty(exports, "__esModule", { value: true }); +const utils = __webpack_require__(287); +class ErrorFilter { + constructor(_settings) { + this._settings = _settings; + } + getFilter() { + return (error) => this._isNonFatalError(error); + } + _isNonFatalError(error) { + return utils.errno.isEnoentCodeError(error) || this._settings.suppressErrors; + } +} +exports.default = ErrorFilter; - if (token.prev.type === 'bos' && eos()) { - state.negatedExtglob = true; - } - } - push({ type: 'paren', extglob: true, value, output }); - decrement('parens'); - }; +/***/ }), +/* 349 */ +/***/ (function(module, exports, __webpack_require__) { - /** - * Fast paths - */ +"use strict"; + +Object.defineProperty(exports, "__esModule", { value: true }); +const utils = __webpack_require__(287); +class EntryTransformer { + constructor(_settings) { + this._settings = _settings; + } + getTransformer() { + return (entry) => this._transform(entry); + } + _transform(entry) { + let filepath = entry.path; + if (this._settings.absolute) { + filepath = utils.path.makeAbsolute(this._settings.cwd, filepath); + filepath = utils.path.unixify(filepath); + } + if (this._settings.markDirectories && entry.dirent.isDirectory()) { + filepath += '/'; + } + if (!this._settings.objectMode) { + return filepath; + } + return Object.assign(Object.assign({}, entry), { path: filepath }); + } +} +exports.default = EntryTransformer; - if (opts.fastpaths !== false && !/(^[*!]|[/()[\]{}"])/.test(input)) { - let backslashes = false; - let output = input.replace(REGEX_SPECIAL_CHARS_BACKREF, (m, esc, chars, first, rest, index) => { - if (first === '\\') { - backslashes = true; - return m; - } +/***/ }), +/* 350 */ +/***/ (function(module, exports, __webpack_require__) { - if (first === '?') { - if (esc) { - return esc + first + (rest ? QMARK.repeat(rest.length) : ''); - } - if (index === 0) { - return qmarkNoDot + (rest ? QMARK.repeat(rest.length) : ''); - } - return QMARK.repeat(chars.length); - } +"use strict"; + +Object.defineProperty(exports, "__esModule", { value: true }); +const stream_1 = __webpack_require__(138); +const stream_2 = __webpack_require__(316); +const provider_1 = __webpack_require__(343); +class ProviderStream extends provider_1.default { + constructor() { + super(...arguments); + this._reader = new stream_2.default(this._settings); + } + read(task) { + const root = this._getRootDirectory(task); + const options = this._getReaderOptions(task); + const source = this.api(root, task, options); + const destination = new stream_1.Readable({ objectMode: true, read: () => { } }); + source + .once('error', (error) => destination.emit('error', error)) + .on('data', (entry) => destination.emit('data', options.transform(entry))) + .once('end', () => destination.emit('end')); + destination + .once('close', () => source.destroy()); + return destination; + } + api(root, task, options) { + if (task.dynamic) { + return this._reader.dynamic(root, options); + } + return this._reader.static(task.patterns, options); + } +} +exports.default = ProviderStream; - if (first === '.') { - return DOT_LITERAL.repeat(chars.length); - } - if (first === '*') { - if (esc) { - return esc + first + (rest ? star : ''); - } - return star; - } - return esc ? m : `\\${m}`; - }); +/***/ }), +/* 351 */ +/***/ (function(module, exports, __webpack_require__) { - if (backslashes === true) { - if (opts.unescape === true) { - output = output.replace(/\\/g, ''); - } else { - output = output.replace(/\\+/g, m => { - return m.length % 2 === 0 ? '\\\\' : (m ? '\\' : ''); - }); - } - } +"use strict"; + +Object.defineProperty(exports, "__esModule", { value: true }); +const sync_1 = __webpack_require__(352); +const provider_1 = __webpack_require__(343); +class ProviderSync extends provider_1.default { + constructor() { + super(...arguments); + this._reader = new sync_1.default(this._settings); + } + read(task) { + const root = this._getRootDirectory(task); + const options = this._getReaderOptions(task); + const entries = this.api(root, task, options); + return entries.map(options.transform); + } + api(root, task, options) { + if (task.dynamic) { + return this._reader.dynamic(root, options); + } + return this._reader.static(task.patterns, options); + } +} +exports.default = ProviderSync; - if (output === input && opts.contains === true) { - state.output = input; - return state; - } - state.output = utils.wrapOutput(output, state, options); - return state; - } +/***/ }), +/* 352 */ +/***/ (function(module, exports, __webpack_require__) { - /** - * Tokenize input until we reach end-of-string - */ +"use strict"; + +Object.defineProperty(exports, "__esModule", { value: true }); +const fsStat = __webpack_require__(317); +const fsWalk = __webpack_require__(322); +const reader_1 = __webpack_require__(342); +class ReaderSync extends reader_1.default { + constructor() { + super(...arguments); + this._walkSync = fsWalk.walkSync; + this._statSync = fsStat.statSync; + } + dynamic(root, options) { + return this._walkSync(root, options); + } + static(patterns, options) { + const entries = []; + for (const pattern of patterns) { + const filepath = this._getFullEntryPath(pattern); + const entry = this._getEntry(filepath, pattern, options); + if (entry === null || !options.entryFilter(entry)) { + continue; + } + entries.push(entry); + } + return entries; + } + _getEntry(filepath, pattern, options) { + try { + const stats = this._getStat(filepath); + return this._makeEntry(stats, pattern); + } + catch (error) { + if (options.errorFilter(error)) { + return null; + } + throw error; + } + } + _getStat(filepath) { + return this._statSync(filepath, this._fsStatSettings); + } +} +exports.default = ReaderSync; - while (!eos()) { - value = advance(); - if (value === '\u0000') { - continue; - } +/***/ }), +/* 353 */ +/***/ (function(module, exports, __webpack_require__) { - /** - * Escaped characters - */ +"use strict"; + +Object.defineProperty(exports, "__esModule", { value: true }); +const fs = __webpack_require__(134); +const os = __webpack_require__(121); +const CPU_COUNT = os.cpus().length; +exports.DEFAULT_FILE_SYSTEM_ADAPTER = { + lstat: fs.lstat, + lstatSync: fs.lstatSync, + stat: fs.stat, + statSync: fs.statSync, + readdir: fs.readdir, + readdirSync: fs.readdirSync +}; +class Settings { + constructor(_options = {}) { + this._options = _options; + this.absolute = this._getValue(this._options.absolute, false); + this.baseNameMatch = this._getValue(this._options.baseNameMatch, false); + this.braceExpansion = this._getValue(this._options.braceExpansion, true); + this.caseSensitiveMatch = this._getValue(this._options.caseSensitiveMatch, true); + this.concurrency = this._getValue(this._options.concurrency, CPU_COUNT); + this.cwd = this._getValue(this._options.cwd, process.cwd()); + this.deep = this._getValue(this._options.deep, Infinity); + this.dot = this._getValue(this._options.dot, false); + this.extglob = this._getValue(this._options.extglob, true); + this.followSymbolicLinks = this._getValue(this._options.followSymbolicLinks, true); + this.fs = this._getFileSystemMethods(this._options.fs); + this.globstar = this._getValue(this._options.globstar, true); + this.ignore = this._getValue(this._options.ignore, []); + this.markDirectories = this._getValue(this._options.markDirectories, false); + this.objectMode = this._getValue(this._options.objectMode, false); + this.onlyDirectories = this._getValue(this._options.onlyDirectories, false); + this.onlyFiles = this._getValue(this._options.onlyFiles, true); + this.stats = this._getValue(this._options.stats, false); + this.suppressErrors = this._getValue(this._options.suppressErrors, false); + this.throwErrorOnBrokenSymbolicLink = this._getValue(this._options.throwErrorOnBrokenSymbolicLink, false); + this.unique = this._getValue(this._options.unique, true); + if (this.onlyDirectories) { + this.onlyFiles = false; + } + if (this.stats) { + this.objectMode = true; + } + } + _getValue(option, value) { + return option === undefined ? value : option; + } + _getFileSystemMethods(methods = {}) { + return Object.assign(Object.assign({}, exports.DEFAULT_FILE_SYSTEM_ADAPTER), methods); + } +} +exports.default = Settings; - if (value === '\\') { - const next = peek(); - if (next === '/' && opts.bash !== true) { - continue; - } +/***/ }), +/* 354 */ +/***/ (function(module, exports, __webpack_require__) { - if (next === '.' || next === ';') { - continue; - } +"use strict"; - if (!next) { - value += '\\'; - push({ type: 'text', value }); - continue; - } +const path = __webpack_require__(4); +const pathType = __webpack_require__(355); - // collapse slashes to reduce potential for exploits - const match = /^\\+/.exec(remaining()); - let slashes = 0; +const getExtensions = extensions => extensions.length > 1 ? `{${extensions.join(',')}}` : extensions[0]; - if (match && match[0].length > 2) { - slashes = match[0].length; - state.index += slashes; - if (slashes % 2 !== 0) { - value += '\\'; - } - } +const getPath = (filepath, cwd) => { + const pth = filepath[0] === '!' ? filepath.slice(1) : filepath; + return path.isAbsolute(pth) ? pth : path.join(cwd, pth); +}; - if (opts.unescape === true) { - value = advance() || ''; - } else { - value += advance() || ''; - } +const addExtensions = (file, extensions) => { + if (path.extname(file)) { + return `**/${file}`; + } - if (state.brackets === 0) { - push({ type: 'text', value }); - continue; - } - } + return `**/${file}.${getExtensions(extensions)}`; +}; - /** - * If we're inside a regex character class, continue - * until we reach the closing bracket. - */ +const getGlob = (directory, options) => { + if (options.files && !Array.isArray(options.files)) { + throw new TypeError(`Expected \`files\` to be of type \`Array\` but received type \`${typeof options.files}\``); + } - if (state.brackets > 0 && (value !== ']' || prev.value === '[' || prev.value === '[^')) { - if (opts.posix !== false && value === ':') { - const inner = prev.value.slice(1); - if (inner.includes('[')) { - prev.posix = true; + if (options.extensions && !Array.isArray(options.extensions)) { + throw new TypeError(`Expected \`extensions\` to be of type \`Array\` but received type \`${typeof options.extensions}\``); + } - if (inner.includes(':')) { - const idx = prev.value.lastIndexOf('['); - const pre = prev.value.slice(0, idx); - const rest = prev.value.slice(idx + 2); - const posix = POSIX_REGEX_SOURCE[rest]; - if (posix) { - prev.value = pre + posix; - state.backtrack = true; - advance(); + if (options.files && options.extensions) { + return options.files.map(x => path.posix.join(directory, addExtensions(x, options.extensions))); + } - if (!bos.output && tokens.indexOf(prev) === 1) { - bos.output = ONE_CHAR; - } - continue; - } - } - } - } + if (options.files) { + return options.files.map(x => path.posix.join(directory, `**/${x}`)); + } - if ((value === '[' && peek() !== ':') || (value === '-' && peek() === ']')) { - value = `\\${value}`; - } + if (options.extensions) { + return [path.posix.join(directory, `**/*.${getExtensions(options.extensions)}`)]; + } - if (value === ']' && (prev.value === '[' || prev.value === '[^')) { - value = `\\${value}`; - } + return [path.posix.join(directory, '**')]; +}; - if (opts.posix === true && value === '!' && prev.value === '[') { - value = '^'; - } +module.exports = async (input, options) => { + options = { + cwd: process.cwd(), + ...options + }; - prev.value += value; - append({ value }); - continue; - } + if (typeof options.cwd !== 'string') { + throw new TypeError(`Expected \`cwd\` to be of type \`string\` but received type \`${typeof options.cwd}\``); + } - /** - * If we're inside a quoted string, continue - * until we reach the closing double quote. - */ + const globs = await Promise.all([].concat(input).map(async x => { + const isDirectory = await pathType.isDirectory(getPath(x, options.cwd)); + return isDirectory ? getGlob(x, options) : x; + })); - if (state.quotes === 1 && value !== '"') { - value = utils.escapeRegex(value); - prev.value += value; - append({ value }); - continue; - } + return [].concat.apply([], globs); // eslint-disable-line prefer-spread +}; - /** - * Double quotes - */ +module.exports.sync = (input, options) => { + options = { + cwd: process.cwd(), + ...options + }; - if (value === '"') { - state.quotes = state.quotes === 1 ? 0 : 1; - if (opts.keepQuotes === true) { - push({ type: 'text', value }); - } - continue; - } + if (typeof options.cwd !== 'string') { + throw new TypeError(`Expected \`cwd\` to be of type \`string\` but received type \`${typeof options.cwd}\``); + } - /** - * Parentheses - */ + const globs = [].concat(input).map(x => pathType.isDirectorySync(getPath(x, options.cwd)) ? getGlob(x, options) : x); - if (value === '(') { - increment('parens'); - push({ type: 'paren', value }); - continue; - } + return [].concat.apply([], globs); // eslint-disable-line prefer-spread +}; - if (value === ')') { - if (state.parens === 0 && opts.strictBrackets === true) { - throw new SyntaxError(syntaxError('opening', '(')); - } - const extglob = extglobs[extglobs.length - 1]; - if (extglob && state.parens === extglob.parens + 1) { - extglobClose(extglobs.pop()); - continue; - } +/***/ }), +/* 355 */ +/***/ (function(module, exports, __webpack_require__) { - push({ type: 'paren', value, output: state.parens ? ')' : '\\)' }); - decrement('parens'); - continue; - } +"use strict"; - /** - * Square brackets - */ +const {promisify} = __webpack_require__(112); +const fs = __webpack_require__(134); - if (value === '[') { - if (opts.nobracket === true || !remaining().includes(']')) { - if (opts.nobracket !== true && opts.strictBrackets === true) { - throw new SyntaxError(syntaxError('closing', ']')); - } +async function isType(fsStatType, statsMethodName, filePath) { + if (typeof filePath !== 'string') { + throw new TypeError(`Expected a string, got ${typeof filePath}`); + } - value = `\\${value}`; - } else { - increment('brackets'); - } + try { + const stats = await promisify(fs[fsStatType])(filePath); + return stats[statsMethodName](); + } catch (error) { + if (error.code === 'ENOENT') { + return false; + } - push({ type: 'bracket', value }); - continue; - } + throw error; + } +} - if (value === ']') { - if (opts.nobracket === true || (prev && prev.type === 'bracket' && prev.value.length === 1)) { - push({ type: 'text', value, output: `\\${value}` }); - continue; - } +function isTypeSync(fsStatType, statsMethodName, filePath) { + if (typeof filePath !== 'string') { + throw new TypeError(`Expected a string, got ${typeof filePath}`); + } - if (state.brackets === 0) { - if (opts.strictBrackets === true) { - throw new SyntaxError(syntaxError('opening', '[')); - } + try { + return fs[fsStatType](filePath)[statsMethodName](); + } catch (error) { + if (error.code === 'ENOENT') { + return false; + } - push({ type: 'text', value, output: `\\${value}` }); - continue; - } + throw error; + } +} - decrement('brackets'); +exports.isFile = isType.bind(null, 'stat', 'isFile'); +exports.isDirectory = isType.bind(null, 'stat', 'isDirectory'); +exports.isSymlink = isType.bind(null, 'lstat', 'isSymbolicLink'); +exports.isFileSync = isTypeSync.bind(null, 'statSync', 'isFile'); +exports.isDirectorySync = isTypeSync.bind(null, 'statSync', 'isDirectory'); +exports.isSymlinkSync = isTypeSync.bind(null, 'lstatSync', 'isSymbolicLink'); - const prevValue = prev.value.slice(1); - if (prev.posix !== true && prevValue[0] === '^' && !prevValue.includes('/')) { - value = `/${value}`; - } - prev.value += value; - append({ value }); +/***/ }), +/* 356 */ +/***/ (function(module, exports, __webpack_require__) { - // when literal brackets are explicitly disabled - // assume we should match with a regex character class - if (opts.literalBrackets === false || utils.hasRegexChars(prevValue)) { - continue; - } +"use strict"; - const escaped = utils.escapeRegex(prev.value); - state.output = state.output.slice(0, -prev.value.length); +const {promisify} = __webpack_require__(112); +const fs = __webpack_require__(134); +const path = __webpack_require__(4); +const fastGlob = __webpack_require__(285); +const gitIgnore = __webpack_require__(357); +const slash = __webpack_require__(358); - // when literal brackets are explicitly enabled - // assume we should escape the brackets to match literal characters - if (opts.literalBrackets === true) { - state.output += escaped; - prev.value = escaped; - continue; - } +const DEFAULT_IGNORE = [ + '**/node_modules/**', + '**/flow-typed/**', + '**/coverage/**', + '**/.git' +]; - // when the user specifies nothing, try to match both - prev.value = `(${capture}${escaped}|${prev.value})`; - state.output += prev.value; - continue; - } +const readFileP = promisify(fs.readFile); - /** - * Braces - */ +const mapGitIgnorePatternTo = base => ignore => { + if (ignore.startsWith('!')) { + return '!' + path.posix.join(base, ignore.slice(1)); + } - if (value === '{' && opts.nobrace !== true) { - increment('braces'); + return path.posix.join(base, ignore); +}; - const open = { - type: 'brace', - value, - output: '(', - outputIndex: state.output.length, - tokensIndex: state.tokens.length - }; +const parseGitIgnore = (content, options) => { + const base = slash(path.relative(options.cwd, path.dirname(options.fileName))); - braces.push(open); - push(open); - continue; - } + return content + .split(/\r?\n/) + .filter(Boolean) + .filter(line => !line.startsWith('#')) + .map(mapGitIgnorePatternTo(base)); +}; - if (value === '}') { - const brace = braces[braces.length - 1]; +const reduceIgnore = files => { + return files.reduce((ignores, file) => { + ignores.add(parseGitIgnore(file.content, { + cwd: file.cwd, + fileName: file.filePath + })); + return ignores; + }, gitIgnore()); +}; - if (opts.nobrace === true || !brace) { - push({ type: 'text', value, output: value }); - continue; - } +const ensureAbsolutePathForCwd = (cwd, p) => { + if (path.isAbsolute(p)) { + if (p.startsWith(cwd)) { + return p; + } - let output = ')'; + throw new Error(`Path ${p} is not in cwd ${cwd}`); + } - if (brace.dots === true) { - const arr = tokens.slice(); - const range = []; + return path.join(cwd, p); +}; - for (let i = arr.length - 1; i >= 0; i--) { - tokens.pop(); - if (arr[i].type === 'brace') { - break; - } - if (arr[i].type !== 'dots') { - range.unshift(arr[i].value); - } - } +const getIsIgnoredPredecate = (ignores, cwd) => { + return p => ignores.ignores(slash(path.relative(cwd, ensureAbsolutePathForCwd(cwd, p)))); +}; - output = expandRange(range, opts); - state.backtrack = true; - } +const getFile = async (file, cwd) => { + const filePath = path.join(cwd, file); + const content = await readFileP(filePath, 'utf8'); - if (brace.comma !== true && brace.dots !== true) { - const out = state.output.slice(0, brace.outputIndex); - const toks = state.tokens.slice(brace.tokensIndex); - brace.value = brace.output = '\\{'; - value = output = '\\}'; - state.output = out; - for (const t of toks) { - state.output += (t.output || t.value); - } - } + return { + cwd, + filePath, + content + }; +}; - push({ type: 'brace', value, output }); - decrement('braces'); - braces.pop(); - continue; - } +const getFileSync = (file, cwd) => { + const filePath = path.join(cwd, file); + const content = fs.readFileSync(filePath, 'utf8'); - /** - * Pipes - */ + return { + cwd, + filePath, + content + }; +}; - if (value === '|') { - if (extglobs.length > 0) { - extglobs[extglobs.length - 1].conditions++; - } - push({ type: 'text', value }); - continue; - } +const normalizeOptions = ({ + ignore = [], + cwd = slash(process.cwd()) +} = {}) => { + return {ignore, cwd}; +}; - /** - * Commas - */ +module.exports = async options => { + options = normalizeOptions(options); - if (value === ',') { - let output = value; + const paths = await fastGlob('**/.gitignore', { + ignore: DEFAULT_IGNORE.concat(options.ignore), + cwd: options.cwd + }); - const brace = braces[braces.length - 1]; - if (brace && stack[stack.length - 1] === 'braces') { - brace.comma = true; - output = '|'; - } + const files = await Promise.all(paths.map(file => getFile(file, options.cwd))); + const ignores = reduceIgnore(files); - push({ type: 'comma', value, output }); - continue; - } + return getIsIgnoredPredecate(ignores, options.cwd); +}; - /** - * Slashes - */ +module.exports.sync = options => { + options = normalizeOptions(options); - if (value === '/') { - // if the beginning of the glob is "./", advance the start - // to the current index, and don't add the "./" characters - // to the state. This greatly simplifies lookbehinds when - // checking for BOS characters like "!" and "." (not "./") - if (prev.type === 'dot' && state.index === state.start + 1) { - state.start = state.index + 1; - state.consumed = ''; - state.output = ''; - tokens.pop(); - prev = bos; // reset "prev" to the first token - continue; - } + const paths = fastGlob.sync('**/.gitignore', { + ignore: DEFAULT_IGNORE.concat(options.ignore), + cwd: options.cwd + }); - push({ type: 'slash', value, output: SLASH_LITERAL }); - continue; - } + const files = paths.map(file => getFileSync(file, options.cwd)); + const ignores = reduceIgnore(files); - /** - * Dots - */ + return getIsIgnoredPredecate(ignores, options.cwd); +}; - if (value === '.') { - if (state.braces > 0 && prev.type === 'dot') { - if (prev.value === '.') prev.output = DOT_LITERAL; - const brace = braces[braces.length - 1]; - prev.type = 'dots'; - prev.output += value; - prev.value += value; - brace.dots = true; - continue; - } - if ((state.braces + state.parens) === 0 && prev.type !== 'bos' && prev.type !== 'slash') { - push({ type: 'text', value, output: DOT_LITERAL }); - continue; - } +/***/ }), +/* 357 */ +/***/ (function(module, exports) { - push({ type: 'dot', value, output: DOT_LITERAL }); - continue; - } +// A simple implementation of make-array +function makeArray (subject) { + return Array.isArray(subject) + ? subject + : [subject] +} - /** - * Question marks - */ +const EMPTY = '' +const SPACE = ' ' +const ESCAPE = '\\' +const REGEX_TEST_BLANK_LINE = /^\s+$/ +const REGEX_REPLACE_LEADING_EXCAPED_EXCLAMATION = /^\\!/ +const REGEX_REPLACE_LEADING_EXCAPED_HASH = /^\\#/ +const REGEX_SPLITALL_CRLF = /\r?\n/g +// /foo, +// ./foo, +// ../foo, +// . +// .. +const REGEX_TEST_INVALID_PATH = /^\.*\/|^\.+$/ - if (value === '?') { - const isGroup = prev && prev.value === '('; - if (!isGroup && opts.noextglob !== true && peek() === '(' && peek(2) !== '?') { - extglobOpen('qmark', value); - continue; - } +const SLASH = '/' +const KEY_IGNORE = typeof Symbol !== 'undefined' + ? Symbol.for('node-ignore') + /* istanbul ignore next */ + : 'node-ignore' - if (prev && prev.type === 'paren') { - const next = peek(); - let output = value; +const define = (object, key, value) => + Object.defineProperty(object, key, {value}) - if (next === '<' && !utils.supportsLookbehinds()) { - throw new Error('Node.js v10 or higher is required for regex lookbehinds'); - } +const REGEX_REGEXP_RANGE = /([0-z])-([0-z])/g - if ((prev.value === '(' && !/[!=<:]/.test(next)) || (next === '<' && !/<([!=]|\w+>)/.test(remaining()))) { - output = `\\${value}`; - } +// Sanitize the range of a regular expression +// The cases are complicated, see test cases for details +const sanitizeRange = range => range.replace( + REGEX_REGEXP_RANGE, + (match, from, to) => from.charCodeAt(0) <= to.charCodeAt(0) + ? match + // Invalid range (out of order) which is ok for gitignore rules but + // fatal for JavaScript regular expression, so eliminate it. + : EMPTY +) - push({ type: 'text', value, output }); - continue; - } +// See fixtures #59 +const cleanRangeBackSlash = slashes => { + const {length} = slashes + return slashes.slice(0, length - length % 2) +} - if (opts.dot !== true && (prev.type === 'slash' || prev.type === 'bos')) { - push({ type: 'qmark', value, output: QMARK_NO_DOT }); - continue; - } +// > If the pattern ends with a slash, +// > it is removed for the purpose of the following description, +// > but it would only find a match with a directory. +// > In other words, foo/ will match a directory foo and paths underneath it, +// > but will not match a regular file or a symbolic link foo +// > (this is consistent with the way how pathspec works in general in Git). +// '`foo/`' will not match regular file '`foo`' or symbolic link '`foo`' +// -> ignore-rules will not deal with it, because it costs extra `fs.stat` call +// you could use option `mark: true` with `glob` - push({ type: 'qmark', value, output: QMARK }); - continue; - } +// '`foo/`' should not continue with the '`..`' +const REPLACERS = [ - /** - * Exclamation - */ + // > Trailing spaces are ignored unless they are quoted with backslash ("\") + [ + // (a\ ) -> (a ) + // (a ) -> (a) + // (a \ ) -> (a ) + /\\?\s+$/, + match => match.indexOf('\\') === 0 + ? SPACE + : EMPTY + ], - if (value === '!') { - if (opts.noextglob !== true && peek() === '(') { - if (peek(2) !== '?' || !/[!=<:]/.test(peek(3))) { - extglobOpen('negate', value); - continue; - } - } - - if (opts.nonegate !== true && state.index === 0) { - negate(); - continue; - } - } - - /** - * Plus - */ + // replace (\ ) with ' ' + [ + /\\\s/g, + () => SPACE + ], - if (value === '+') { - if (opts.noextglob !== true && peek() === '(' && peek(2) !== '?') { - extglobOpen('plus', value); - continue; - } + // Escape metacharacters + // which is written down by users but means special for regular expressions. - if ((prev && prev.value === '(') || opts.regex === false) { - push({ type: 'plus', value, output: PLUS_LITERAL }); - continue; - } + // > There are 12 characters with special meanings: + // > - the backslash \, + // > - the caret ^, + // > - the dollar sign $, + // > - the period or dot ., + // > - the vertical bar or pipe symbol |, + // > - the question mark ?, + // > - the asterisk or star *, + // > - the plus sign +, + // > - the opening parenthesis (, + // > - the closing parenthesis ), + // > - and the opening square bracket [, + // > - the opening curly brace {, + // > These special characters are often called "metacharacters". + [ + /[\\$.|*+(){^]/g, + match => `\\${match}` + ], - if ((prev && (prev.type === 'bracket' || prev.type === 'paren' || prev.type === 'brace')) || state.parens > 0) { - push({ type: 'plus', value }); - continue; - } + [ + // > a question mark (?) matches a single character + /(?!\\)\?/g, + () => '[^/]' + ], - push({ type: 'plus', value: PLUS_LITERAL }); - continue; - } + // leading slash + [ - /** - * Plain text - */ + // > A leading slash matches the beginning of the pathname. + // > For example, "/*.c" matches "cat-file.c" but not "mozilla-sha1/sha1.c". + // A leading slash matches the beginning of the pathname + /^\//, + () => '^' + ], - if (value === '@') { - if (opts.noextglob !== true && peek() === '(' && peek(2) !== '?') { - push({ type: 'at', extglob: true, value, output: '' }); - continue; - } + // replace special metacharacter slash after the leading slash + [ + /\//g, + () => '\\/' + ], - push({ type: 'text', value }); - continue; - } + [ + // > A leading "**" followed by a slash means match in all directories. + // > For example, "**/foo" matches file or directory "foo" anywhere, + // > the same as pattern "foo". + // > "**/foo/bar" matches file or directory "bar" anywhere that is directly + // > under directory "foo". + // Notice that the '*'s have been replaced as '\\*' + /^\^*\\\*\\\*\\\//, - /** - * Plain text - */ + // '**/foo' <-> 'foo' + () => '^(?:.*\\/)?' + ], - if (value !== '*') { - if (value === '$' || value === '^') { - value = `\\${value}`; - } + // starting + [ + // there will be no leading '/' + // (which has been replaced by section "leading slash") + // If starts with '**', adding a '^' to the regular expression also works + /^(?=[^^])/, + function startingReplacer () { + // If has a slash `/` at the beginning or middle + return !/\/(?!$)/.test(this) + // > Prior to 2.22.1 + // > If the pattern does not contain a slash /, + // > Git treats it as a shell glob pattern + // Actually, if there is only a trailing slash, + // git also treats it as a shell glob pattern - const match = REGEX_NON_SPECIAL_CHARS.exec(remaining()); - if (match) { - value += match[0]; - state.index += match[0].length; - } + // After 2.22.1 (compatible but clearer) + // > If there is a separator at the beginning or middle (or both) + // > of the pattern, then the pattern is relative to the directory + // > level of the particular .gitignore file itself. + // > Otherwise the pattern may also match at any level below + // > the .gitignore level. + ? '(?:^|\\/)' - push({ type: 'text', value }); - continue; + // > Otherwise, Git treats the pattern as a shell glob suitable for + // > consumption by fnmatch(3) + : '^' } + ], - /** - * Stars - */ + // two globstars + [ + // Use lookahead assertions so that we could match more than one `'/**'` + /\\\/\\\*\\\*(?=\\\/|$)/g, - if (prev && (prev.type === 'globstar' || prev.star === true)) { - prev.type = 'star'; - prev.star = true; - prev.value += value; - prev.output = star; - state.backtrack = true; - state.globstar = true; - consume(value); - continue; - } + // Zero, one or several directories + // should not use '*', or it will be replaced by the next replacer - let rest = remaining(); - if (opts.noextglob !== true && /^\([^?]/.test(rest)) { - extglobOpen('star', value); - continue; - } + // Check if it is not the last `'/**'` + (_, index, str) => index + 6 < str.length - if (prev.type === 'star') { - if (opts.noglobstar === true) { - consume(value); - continue; - } + // case: /**/ + // > A slash followed by two consecutive asterisks then a slash matches + // > zero or more directories. + // > For example, "a/**/b" matches "a/b", "a/x/b", "a/x/y/b" and so on. + // '/**/' + ? '(?:\\/[^\\/]+)*' - const prior = prev.prev; - const before = prior.prev; - const isStart = prior.type === 'slash' || prior.type === 'bos'; - const afterStar = before && (before.type === 'star' || before.type === 'globstar'); + // case: /** + // > A trailing `"/**"` matches everything inside. - if (opts.bash === true && (!isStart || (rest[0] && rest[0] !== '/'))) { - push({ type: 'star', value, output: '' }); - continue; - } + // #21: everything inside but it should not include the current folder + : '\\/.+' + ], - const isBrace = state.braces > 0 && (prior.type === 'comma' || prior.type === 'brace'); - const isExtglob = extglobs.length && (prior.type === 'pipe' || prior.type === 'paren'); - if (!isStart && prior.type !== 'paren' && !isBrace && !isExtglob) { - push({ type: 'star', value, output: '' }); - continue; - } + // intermediate wildcards + [ + // Never replace escaped '*' + // ignore rule '\*' will match the path '*' - // strip consecutive `/**/` - while (rest.slice(0, 3) === '/**') { - const after = input[state.index + 4]; - if (after && after !== '/') { - break; - } - rest = rest.slice(3); - consume('/**', 3); - } + // 'abc.*/' -> go + // 'abc.*' -> skip this rule + /(^|[^\\]+)\\\*(?=.+)/g, - if (prior.type === 'bos' && eos()) { - prev.type = 'globstar'; - prev.value += value; - prev.output = globstar(opts); - state.output = prev.output; - state.globstar = true; - consume(value); - continue; - } + // '*.js' matches '.js' + // '*.js' doesn't match 'abc' + (_, p1) => `${p1}[^\\/]*` + ], - if (prior.type === 'slash' && prior.prev.type !== 'bos' && !afterStar && eos()) { - state.output = state.output.slice(0, -(prior.output + prev.output).length); - prior.output = `(?:${prior.output}`; + [ + // unescape, revert step 3 except for back slash + // For example, if a user escape a '\\*', + // after step 3, the result will be '\\\\\\*' + /\\\\\\(?=[$.|*+(){^])/g, + () => ESCAPE + ], - prev.type = 'globstar'; - prev.output = globstar(opts) + (opts.strictSlashes ? ')' : '|$)'); - prev.value += value; - state.globstar = true; - state.output += prior.output + prev.output; - consume(value); - continue; - } + [ + // '\\\\' -> '\\' + /\\\\/g, + () => ESCAPE + ], - if (prior.type === 'slash' && prior.prev.type !== 'bos' && rest[0] === '/') { - const end = rest[1] !== void 0 ? '|$' : ''; + [ + // > The range notation, e.g. [a-zA-Z], + // > can be used to match one of the characters in a range. - state.output = state.output.slice(0, -(prior.output + prev.output).length); - prior.output = `(?:${prior.output}`; + // `\` is escaped by step 3 + /(\\)?\[([^\]/]*?)(\\*)($|\])/g, + (match, leadEscape, range, endEscape, close) => leadEscape === ESCAPE + // '\\[bar]' -> '\\\\[bar\\]' + ? `\\[${range}${cleanRangeBackSlash(endEscape)}${close}` + : close === ']' + ? endEscape.length % 2 === 0 + // A normal case, and it is a range notation + // '[bar]' + // '[bar\\\\]' + ? `[${sanitizeRange(range)}${endEscape}]` + // Invalid range notaton + // '[bar\\]' -> '[bar\\\\]' + : '[]' + : '[]' + ], - prev.type = 'globstar'; - prev.output = `${globstar(opts)}${SLASH_LITERAL}|${SLASH_LITERAL}${end})`; - prev.value += value; + // ending + [ + // 'js' will not match 'js.' + // 'ab' will not match 'abc' + /(?:[^*])$/, - state.output += prior.output + prev.output; - state.globstar = true; + // WTF! + // https://git-scm.com/docs/gitignore + // changes in [2.22.1](https://git-scm.com/docs/gitignore/2.22.1) + // which re-fixes #24, #38 - consume(value + advance()); + // > If there is a separator at the end of the pattern then the pattern + // > will only match directories, otherwise the pattern can match both + // > files and directories. - push({ type: 'slash', value: '/', output: '' }); - continue; - } + // 'js*' will not match 'a.js' + // 'js/' will not match 'a.js' + // 'js' will match 'a.js' and 'a.js/' + match => /\/$/.test(match) + // foo/ will not match 'foo' + ? `${match}$` + // foo matches 'foo' and 'foo/' + : `${match}(?=$|\\/$)` + ], - if (prior.type === 'bos' && rest[0] === '/') { - prev.type = 'globstar'; - prev.value += value; - prev.output = `(?:^|${SLASH_LITERAL}|${globstar(opts)}${SLASH_LITERAL})`; - state.output = prev.output; - state.globstar = true; - consume(value + advance()); - push({ type: 'slash', value: '/', output: '' }); - continue; - } + // trailing wildcard + [ + /(\^|\\\/)?\\\*$/, + (_, p1) => { + const prefix = p1 + // '\^': + // '/*' does not match EMPTY + // '/*' does not match everything - // remove single star from output - state.output = state.output.slice(0, -prev.output.length); + // '\\\/': + // 'abc/*' does not match 'abc/' + ? `${p1}[^/]+` - // reset previous token to globstar - prev.type = 'globstar'; - prev.output = globstar(opts); - prev.value += value; + // 'a*' matches 'a' + // 'a*' matches 'aa' + : '[^/]*' - // reset output with globstar - state.output += prev.output; - state.globstar = true; - consume(value); - continue; + return `${prefix}(?=$|\\/$)` } + ], +] - const token = { type: 'star', value, output: star }; +// A simple cache, because an ignore rule only has only one certain meaning +const regexCache = Object.create(null) - if (opts.bash === true) { - token.output = '.*?'; - if (prev.type === 'bos' || prev.type === 'slash') { - token.output = nodot + token.output; - } - push(token); - continue; - } +// @param {pattern} +const makeRegex = (pattern, negative, ignorecase) => { + const r = regexCache[pattern] + if (r) { + return r + } - if (prev && (prev.type === 'bracket' || prev.type === 'paren') && opts.regex === true) { - token.output = value; - push(token); - continue; - } + // const replacers = negative + // ? NEGATIVE_REPLACERS + // : POSITIVE_REPLACERS - if (state.index === state.start || prev.type === 'slash' || prev.type === 'dot') { - if (prev.type === 'dot') { - state.output += NO_DOT_SLASH; - prev.output += NO_DOT_SLASH; + const source = REPLACERS.reduce( + (prev, current) => prev.replace(current[0], current[1].bind(pattern)), + pattern + ) - } else if (opts.dot === true) { - state.output += NO_DOTS_SLASH; - prev.output += NO_DOTS_SLASH; + return regexCache[pattern] = ignorecase + ? new RegExp(source, 'i') + : new RegExp(source) +} - } else { - state.output += nodot; - prev.output += nodot; - } +const isString = subject => typeof subject === 'string' - if (peek() !== '*') { - state.output += ONE_CHAR; - prev.output += ONE_CHAR; - } - } +// > A blank line matches no files, so it can serve as a separator for readability. +const checkPattern = pattern => pattern + && isString(pattern) + && !REGEX_TEST_BLANK_LINE.test(pattern) - push(token); - } + // > A line starting with # serves as a comment. + && pattern.indexOf('#') !== 0 - while (state.brackets > 0) { - if (opts.strictBrackets === true) throw new SyntaxError(syntaxError('closing', ']')); - state.output = utils.escapeLast(state.output, '['); - decrement('brackets'); - } +const splitPattern = pattern => pattern.split(REGEX_SPLITALL_CRLF) - while (state.parens > 0) { - if (opts.strictBrackets === true) throw new SyntaxError(syntaxError('closing', ')')); - state.output = utils.escapeLast(state.output, '('); - decrement('parens'); +class IgnoreRule { + constructor ( + origin, + pattern, + negative, + regex + ) { + this.origin = origin + this.pattern = pattern + this.negative = negative + this.regex = regex } +} - while (state.braces > 0) { - if (opts.strictBrackets === true) throw new SyntaxError(syntaxError('closing', '}')); - state.output = utils.escapeLast(state.output, '{'); - decrement('braces'); - } +const createRule = (pattern, ignorecase) => { + const origin = pattern + let negative = false - if (opts.strictSlashes !== true && (prev.type === 'star' || prev.type === 'bracket')) { - push({ type: 'maybe_slash', value: '', output: `${SLASH_LITERAL}?` }); + // > An optional prefix "!" which negates the pattern; + if (pattern.indexOf('!') === 0) { + negative = true + pattern = pattern.substr(1) } - // rebuild the output if we had to backtrack at any point - if (state.backtrack === true) { - state.output = ''; + pattern = pattern + // > Put a backslash ("\") in front of the first "!" for patterns that + // > begin with a literal "!", for example, `"\!important!.txt"`. + .replace(REGEX_REPLACE_LEADING_EXCAPED_EXCLAMATION, '!') + // > Put a backslash ("\") in front of the first hash for patterns that + // > begin with a hash. + .replace(REGEX_REPLACE_LEADING_EXCAPED_HASH, '#') - for (const token of state.tokens) { - state.output += token.output != null ? token.output : token.value; + const regex = makeRegex(pattern, negative, ignorecase) - if (token.suffix) { - state.output += token.suffix; - } - } - } + return new IgnoreRule( + origin, + pattern, + negative, + regex + ) +} - return state; -}; +const throwError = (message, Ctor) => { + throw new Ctor(message) +} -/** - * Fast paths for creating regular expressions for common glob patterns. - * This can significantly speed up processing and has very little downside - * impact when none of the fast paths match. - */ +const checkPath = (path, originalPath, doThrow) => { + if (!isString(path)) { + return doThrow( + `path must be a string, but got \`${originalPath}\``, + TypeError + ) + } -parse.fastpaths = (input, options) => { - const opts = { ...options }; - const max = typeof opts.maxLength === 'number' ? Math.min(MAX_LENGTH, opts.maxLength) : MAX_LENGTH; - const len = input.length; - if (len > max) { - throw new SyntaxError(`Input length: ${len}, exceeds maximum allowed length: ${max}`); + // We don't know if we should ignore EMPTY, so throw + if (!path) { + return doThrow(`path must not be empty`, TypeError) } - input = REPLACEMENTS[input] || input; - const win32 = utils.isWindows(options); + // Check if it is a relative path + if (checkPath.isNotRelative(path)) { + const r = '`path.relative()`d' + return doThrow( + `path should be a ${r} string, but got "${originalPath}"`, + RangeError + ) + } - // create constants based on platform, for windows or posix - const { - DOT_LITERAL, - SLASH_LITERAL, - ONE_CHAR, - DOTS_SLASH, - NO_DOT, - NO_DOTS, - NO_DOTS_SLASH, - STAR, - START_ANCHOR - } = constants.globChars(win32); + return true +} - const nodot = opts.dot ? NO_DOTS : NO_DOT; - const slashDot = opts.dot ? NO_DOTS_SLASH : NO_DOT; - const capture = opts.capture ? '' : '?:'; - const state = { negated: false, prefix: '' }; - let star = opts.bash === true ? '.*?' : STAR; +const isNotRelative = path => REGEX_TEST_INVALID_PATH.test(path) - if (opts.capture) { - star = `(${star})`; - } +checkPath.isNotRelative = isNotRelative +checkPath.convert = p => p - const globstar = (opts) => { - if (opts.noglobstar === true) return star; - return `(${capture}(?:(?!${START_ANCHOR}${opts.dot ? DOTS_SLASH : DOT_LITERAL}).)*?)`; - }; +class Ignore { + constructor ({ + ignorecase = true + } = {}) { + this._rules = [] + this._ignorecase = ignorecase + define(this, KEY_IGNORE, true) + this._initCache() + } - const create = str => { - switch (str) { - case '*': - return `${nodot}${ONE_CHAR}${star}`; + _initCache () { + this._ignoreCache = Object.create(null) + this._testCache = Object.create(null) + } - case '.*': - return `${DOT_LITERAL}${ONE_CHAR}${star}`; + _addPattern (pattern) { + // #32 + if (pattern && pattern[KEY_IGNORE]) { + this._rules = this._rules.concat(pattern._rules) + this._added = true + return + } - case '*.*': - return `${nodot}${star}${DOT_LITERAL}${ONE_CHAR}${star}`; + if (checkPattern(pattern)) { + const rule = createRule(pattern, this._ignorecase) + this._added = true + this._rules.push(rule) + } + } - case '*/*': - return `${nodot}${star}${SLASH_LITERAL}${ONE_CHAR}${slashDot}${star}`; + // @param {Array | string | Ignore} pattern + add (pattern) { + this._added = false - case '**': - return nodot + globstar(opts); + makeArray( + isString(pattern) + ? splitPattern(pattern) + : pattern + ).forEach(this._addPattern, this) - case '**/*': - return `(?:${nodot}${globstar(opts)}${SLASH_LITERAL})?${slashDot}${ONE_CHAR}${star}`; + // Some rules have just added to the ignore, + // making the behavior changed. + if (this._added) { + this._initCache() + } - case '**/*.*': - return `(?:${nodot}${globstar(opts)}${SLASH_LITERAL})?${slashDot}${star}${DOT_LITERAL}${ONE_CHAR}${star}`; + return this + } - case '**/.*': - return `(?:${nodot}${globstar(opts)}${SLASH_LITERAL})?${DOT_LITERAL}${ONE_CHAR}${star}`; + // legacy + addPattern (pattern) { + return this.add(pattern) + } - default: { - const match = /^(.*?)\.(\w+)$/.exec(str); - if (!match) return; + // | ignored : unignored + // negative | 0:0 | 0:1 | 1:0 | 1:1 + // -------- | ------- | ------- | ------- | -------- + // 0 | TEST | TEST | SKIP | X + // 1 | TESTIF | SKIP | TEST | X - const source = create(match[1]); - if (!source) return; + // - SKIP: always skip + // - TEST: always test + // - TESTIF: only test if checkUnignored + // - X: that never happen - return source + DOT_LITERAL + match[2]; + // @param {boolean} whether should check if the path is unignored, + // setting `checkUnignored` to `false` could reduce additional + // path matching. + + // @returns {TestResult} true if a file is ignored + _testOne (path, checkUnignored) { + let ignored = false + let unignored = false + + this._rules.forEach(rule => { + const {negative} = rule + if ( + unignored === negative && ignored !== unignored + || negative && !ignored && !unignored && !checkUnignored + ) { + return } + + const matched = rule.regex.test(path) + + if (matched) { + ignored = !negative + unignored = negative + } + }) + + return { + ignored, + unignored } - }; + } - const output = utils.removePrefix(input, state); - let source = create(output); + // @returns {TestResult} + _test (originalPath, cache, checkUnignored, slices) { + const path = originalPath + // Supports nullable path + && checkPath.convert(originalPath) - if (source && opts.strictSlashes !== true) { - source += `${SLASH_LITERAL}?`; + checkPath(path, originalPath, throwError) + + return this._t(path, cache, checkUnignored, slices) } - return source; -}; + _t (path, cache, checkUnignored, slices) { + if (path in cache) { + return cache[path] + } -module.exports = parse; + if (!slices) { + // path/to/a.js + // ['path', 'to', 'a.js'] + slices = path.split(SLASH) + } + slices.pop() -/***/ }), -/* 320 */ -/***/ (function(module, exports, __webpack_require__) { + // If the path has no parent directory, just test it + if (!slices.length) { + return cache[path] = this._testOne(path, checkUnignored) + } -"use strict"; - -Object.defineProperty(exports, "__esModule", { value: true }); -const merge2 = __webpack_require__(291); -function merge(streams) { - const mergedStream = merge2(streams); - streams.forEach((stream) => { - stream.once('error', (error) => mergedStream.emit('error', error)); - }); - mergedStream.once('close', () => propagateCloseEventToSources(streams)); - mergedStream.once('end', () => propagateCloseEventToSources(streams)); - return mergedStream; -} -exports.merge = merge; -function propagateCloseEventToSources(streams) { - streams.forEach((stream) => stream.emit('close')); -} + const parent = this._t( + slices.join(SLASH) + SLASH, + cache, + checkUnignored, + slices + ) + // If the path contains a parent directory, check the parent first + return cache[path] = parent.ignored + // > It is not possible to re-include a file if a parent directory of + // > that file is excluded. + ? parent + : this._testOne(path, checkUnignored) + } -/***/ }), -/* 321 */ -/***/ (function(module, exports, __webpack_require__) { + ignores (path) { + return this._test(path, this._ignoreCache, false).ignored + } -"use strict"; - -Object.defineProperty(exports, "__esModule", { value: true }); -function isString(input) { - return typeof input === 'string'; -} -exports.isString = isString; -function isEmpty(input) { - return input === ''; -} -exports.isEmpty = isEmpty; + createFilter () { + return path => !this.ignores(path) + } + filter (paths) { + return makeArray(paths).filter(this.createFilter()) + } -/***/ }), -/* 322 */ -/***/ (function(module, exports, __webpack_require__) { + // @returns {TestResult} + test (path) { + return this._test(path, this._testCache, true) + } +} -"use strict"; - -Object.defineProperty(exports, "__esModule", { value: true }); -const stream_1 = __webpack_require__(323); -const provider_1 = __webpack_require__(350); -class ProviderAsync extends provider_1.default { - constructor() { - super(...arguments); - this._reader = new stream_1.default(this._settings); - } - read(task) { - const root = this._getRootDirectory(task); - const options = this._getReaderOptions(task); - const entries = []; - return new Promise((resolve, reject) => { - const stream = this.api(root, task, options); - stream.once('error', reject); - stream.on('data', (entry) => entries.push(options.transform(entry))); - stream.once('end', () => resolve(entries)); - }); - } - api(root, task, options) { - if (task.dynamic) { - return this._reader.dynamic(root, options); - } - return this._reader.static(task.patterns, options); - } -} -exports.default = ProviderAsync; +const factory = options => new Ignore(options) +const returnFalse = () => false -/***/ }), -/* 323 */ -/***/ (function(module, exports, __webpack_require__) { +const isPathValid = path => + checkPath(path && checkPath.convert(path), path, returnFalse) -"use strict"; - -Object.defineProperty(exports, "__esModule", { value: true }); -const stream_1 = __webpack_require__(137); -const fsStat = __webpack_require__(324); -const fsWalk = __webpack_require__(329); -const reader_1 = __webpack_require__(349); -class ReaderStream extends reader_1.default { - constructor() { - super(...arguments); - this._walkStream = fsWalk.walkStream; - this._stat = fsStat.stat; - } - dynamic(root, options) { - return this._walkStream(root, options); - } - static(patterns, options) { - const filepaths = patterns.map(this._getFullEntryPath, this); - const stream = new stream_1.PassThrough({ objectMode: true }); - stream._write = (index, _enc, done) => { - return this._getEntry(filepaths[index], patterns[index], options) - .then((entry) => { - if (entry !== null && options.entryFilter(entry)) { - stream.push(entry); - } - if (index === filepaths.length - 1) { - stream.end(); - } - done(); - }) - .catch(done); - }; - for (let i = 0; i < filepaths.length; i++) { - stream.write(i); - } - return stream; - } - _getEntry(filepath, pattern, options) { - return this._getStat(filepath) - .then((stats) => this._makeEntry(stats, pattern)) - .catch((error) => { - if (options.errorFilter(error)) { - return null; - } - throw error; - }); - } - _getStat(filepath) { - return new Promise((resolve, reject) => { - this._stat(filepath, this._fsStatSettings, (error, stats) => { - return error === null ? resolve(stats) : reject(error); - }); - }); - } -} -exports.default = ReaderStream; +factory.isPathValid = isPathValid +// Fixes typescript +factory.default = factory -/***/ }), -/* 324 */ -/***/ (function(module, exports, __webpack_require__) { +module.exports = factory -"use strict"; - -Object.defineProperty(exports, "__esModule", { value: true }); -const async = __webpack_require__(325); -const sync = __webpack_require__(326); -const settings_1 = __webpack_require__(327); -exports.Settings = settings_1.default; -function stat(path, optionsOrSettingsOrCallback, callback) { - if (typeof optionsOrSettingsOrCallback === 'function') { - return async.read(path, getSettings(), optionsOrSettingsOrCallback); - } - async.read(path, getSettings(optionsOrSettingsOrCallback), callback); -} -exports.stat = stat; -function statSync(path, optionsOrSettings) { - const settings = getSettings(optionsOrSettings); - return sync.read(path, settings); -} -exports.statSync = statSync; -function getSettings(settingsOrOptions = {}) { - if (settingsOrOptions instanceof settings_1.default) { - return settingsOrOptions; - } - return new settings_1.default(settingsOrOptions); -} +// Windows +// -------------------------------------------------------------- +/* istanbul ignore if */ +if ( + // Detect `process` so that it can run in browsers. + typeof process !== 'undefined' + && ( + process.env && process.env.IGNORE_TEST_WIN32 + || process.platform === 'win32' + ) +) { + /* eslint no-control-regex: "off" */ + const makePosix = str => /^\\\\\?\\/.test(str) + || /["<>|\u0000-\u001F]+/u.test(str) + ? str + : str.replace(/\\/g, '/') + + checkPath.convert = makePosix + + // 'C:\\foo' <- 'C:\\foo' has been converted to 'C:/' + // 'd:\\foo' + const REGIX_IS_WINDOWS_PATH_ABSOLUTE = /^[a-z]:\//i + checkPath.isNotRelative = path => + REGIX_IS_WINDOWS_PATH_ABSOLUTE.test(path) + || isNotRelative(path) +} /***/ }), -/* 325 */ +/* 358 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; - -Object.defineProperty(exports, "__esModule", { value: true }); -function read(path, settings, callback) { - settings.fs.lstat(path, (lstatError, lstat) => { - if (lstatError !== null) { - return callFailureCallback(callback, lstatError); - } - if (!lstat.isSymbolicLink() || !settings.followSymbolicLink) { - return callSuccessCallback(callback, lstat); - } - settings.fs.stat(path, (statError, stat) => { - if (statError !== null) { - if (settings.throwErrorOnBrokenSymbolicLink) { - return callFailureCallback(callback, statError); - } - return callSuccessCallback(callback, lstat); - } - if (settings.markSymbolicLink) { - stat.isSymbolicLink = () => true; - } - callSuccessCallback(callback, stat); - }); - }); -} -exports.read = read; -function callFailureCallback(callback, error) { - callback(error); -} -function callSuccessCallback(callback, result) { - callback(null, result); -} +module.exports = path => { + const isExtendedLengthPath = /^\\\\\?\\/.test(path); + const hasNonAscii = /[^\u0000-\u0080]+/.test(path); // eslint-disable-line no-control-regex -/***/ }), -/* 326 */ -/***/ (function(module, exports, __webpack_require__) { + if (isExtendedLengthPath || hasNonAscii) { + return path; + } -"use strict"; - -Object.defineProperty(exports, "__esModule", { value: true }); -function read(path, settings) { - const lstat = settings.fs.lstatSync(path); - if (!lstat.isSymbolicLink() || !settings.followSymbolicLink) { - return lstat; - } - try { - const stat = settings.fs.statSync(path); - if (settings.markSymbolicLink) { - stat.isSymbolicLink = () => true; - } - return stat; - } - catch (error) { - if (!settings.throwErrorOnBrokenSymbolicLink) { - return lstat; - } - throw error; - } -} -exports.read = read; + return path.replace(/\\/g, '/'); +}; /***/ }), -/* 327 */ +/* 359 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; - -Object.defineProperty(exports, "__esModule", { value: true }); -const fs = __webpack_require__(328); -class Settings { - constructor(_options = {}) { - this._options = _options; - this.followSymbolicLink = this._getValue(this._options.followSymbolicLink, true); - this.fs = fs.createFileSystemAdapter(this._options.fs); - this.markSymbolicLink = this._getValue(this._options.markSymbolicLink, false); - this.throwErrorOnBrokenSymbolicLink = this._getValue(this._options.throwErrorOnBrokenSymbolicLink, true); - } - _getValue(option, value) { - return option === undefined ? value : option; - } -} -exports.default = Settings; + +const {Transform} = __webpack_require__(138); + +class ObjectTransform extends Transform { + constructor() { + super({ + objectMode: true + }); + } +} + +class FilterStream extends ObjectTransform { + constructor(filter) { + super(); + this._filter = filter; + } + + _transform(data, encoding, callback) { + if (this._filter(data)) { + this.push(data); + } + + callback(); + } +} + +class UniqueStream extends ObjectTransform { + constructor() { + super(); + this._pushed = new Set(); + } + + _transform(data, encoding, callback) { + if (!this._pushed.has(data)) { + this.push(data); + this._pushed.add(data); + } + + callback(); + } +} + +module.exports = { + FilterStream, + UniqueStream +}; /***/ }), -/* 328 */ +/* 360 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; - -Object.defineProperty(exports, "__esModule", { value: true }); -const fs = __webpack_require__(133); -exports.FILE_SYSTEM_ADAPTER = { - lstat: fs.lstat, - stat: fs.stat, - lstatSync: fs.lstatSync, - statSync: fs.statSync -}; -function createFileSystemAdapter(fsMethods) { - if (fsMethods === undefined) { - return exports.FILE_SYSTEM_ADAPTER; - } - return Object.assign(Object.assign({}, exports.FILE_SYSTEM_ADAPTER), fsMethods); -} -exports.createFileSystemAdapter = createFileSystemAdapter; + +const path = __webpack_require__(4); + +module.exports = path_ => { + let cwd = process.cwd(); + + path_ = path.resolve(path_); + + if (process.platform === 'win32') { + cwd = cwd.toLowerCase(); + path_ = path_.toLowerCase(); + } + + return path_ === cwd; +}; /***/ }), -/* 329 */ +/* 361 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; - -Object.defineProperty(exports, "__esModule", { value: true }); -const async_1 = __webpack_require__(330); -const stream_1 = __webpack_require__(345); -const sync_1 = __webpack_require__(346); -const settings_1 = __webpack_require__(348); -exports.Settings = settings_1.default; -function walk(directory, optionsOrSettingsOrCallback, callback) { - if (typeof optionsOrSettingsOrCallback === 'function') { - return new async_1.default(directory, getSettings()).read(optionsOrSettingsOrCallback); - } - new async_1.default(directory, getSettings(optionsOrSettingsOrCallback)).read(callback); -} -exports.walk = walk; -function walkSync(directory, optionsOrSettings) { - const settings = getSettings(optionsOrSettings); - const provider = new sync_1.default(directory, settings); - return provider.read(); -} -exports.walkSync = walkSync; -function walkStream(directory, optionsOrSettings) { - const settings = getSettings(optionsOrSettings); - const provider = new stream_1.default(directory, settings); - return provider.read(); -} -exports.walkStream = walkStream; -function getSettings(settingsOrOptions = {}) { - if (settingsOrOptions instanceof settings_1.default) { - return settingsOrOptions; - } - return new settings_1.default(settingsOrOptions); -} +const path = __webpack_require__(4); -/***/ }), -/* 330 */ -/***/ (function(module, exports, __webpack_require__) { +module.exports = (childPath, parentPath) => { + childPath = path.resolve(childPath); + parentPath = path.resolve(parentPath); -"use strict"; - -Object.defineProperty(exports, "__esModule", { value: true }); -const async_1 = __webpack_require__(331); -class AsyncProvider { - constructor(_root, _settings) { - this._root = _root; - this._settings = _settings; - this._reader = new async_1.default(this._root, this._settings); - this._storage = new Set(); - } - read(callback) { - this._reader.onError((error) => { - callFailureCallback(callback, error); - }); - this._reader.onEntry((entry) => { - this._storage.add(entry); - }); - this._reader.onEnd(() => { - callSuccessCallback(callback, [...this._storage]); - }); - this._reader.read(); - } -} -exports.default = AsyncProvider; -function callFailureCallback(callback, error) { - callback(error); -} -function callSuccessCallback(callback, entries) { - callback(null, entries); -} + if (process.platform === 'win32') { + childPath = childPath.toLowerCase(); + parentPath = parentPath.toLowerCase(); + } + if (childPath === parentPath) { + return false; + } -/***/ }), -/* 331 */ -/***/ (function(module, exports, __webpack_require__) { + childPath += path.sep; + parentPath += path.sep; -"use strict"; - -Object.defineProperty(exports, "__esModule", { value: true }); -const events_1 = __webpack_require__(155); -const fsScandir = __webpack_require__(332); -const fastq = __webpack_require__(341); -const common = __webpack_require__(343); -const reader_1 = __webpack_require__(344); -class AsyncReader extends reader_1.default { - constructor(_root, _settings) { - super(_root, _settings); - this._settings = _settings; - this._scandir = fsScandir.scandir; - this._emitter = new events_1.EventEmitter(); - this._queue = fastq(this._worker.bind(this), this._settings.concurrency); - this._isFatalError = false; - this._isDestroyed = false; - this._queue.drain = () => { - if (!this._isFatalError) { - this._emitter.emit('end'); - } - }; - } - read() { - this._isFatalError = false; - this._isDestroyed = false; - setImmediate(() => { - this._pushToQueue(this._root, this._settings.basePath); - }); - return this._emitter; - } - destroy() { - if (this._isDestroyed) { - throw new Error('The reader is already destroyed'); - } - this._isDestroyed = true; - this._queue.killAndDrain(); - } - onEntry(callback) { - this._emitter.on('entry', callback); - } - onError(callback) { - this._emitter.once('error', callback); - } - onEnd(callback) { - this._emitter.once('end', callback); - } - _pushToQueue(directory, base) { - const queueItem = { directory, base }; - this._queue.push(queueItem, (error) => { - if (error !== null) { - this._handleError(error); - } - }); - } - _worker(item, done) { - this._scandir(item.directory, this._settings.fsScandirSettings, (error, entries) => { - if (error !== null) { - return done(error, undefined); - } - for (const entry of entries) { - this._handleEntry(entry, item.base); - } - done(null, undefined); - }); - } - _handleError(error) { - if (!common.isFatalError(this._settings, error)) { - return; - } - this._isFatalError = true; - this._isDestroyed = true; - this._emitter.emit('error', error); - } - _handleEntry(entry, base) { - if (this._isDestroyed || this._isFatalError) { - return; - } - const fullpath = entry.path; - if (base !== undefined) { - entry.path = common.joinPathSegments(base, entry.name, this._settings.pathSegmentSeparator); - } - if (common.isAppliedFilter(this._settings.entryFilter, entry)) { - this._emitEntry(entry); - } - if (entry.dirent.isDirectory() && common.isAppliedFilter(this._settings.deepFilter, entry)) { - this._pushToQueue(fullpath, entry.path); - } - } - _emitEntry(entry) { - this._emitter.emit('entry', entry); - } -} -exports.default = AsyncReader; + return childPath.startsWith(parentPath); +}; /***/ }), -/* 332 */ +/* 362 */ /***/ (function(module, exports, __webpack_require__) { -"use strict"; - -Object.defineProperty(exports, "__esModule", { value: true }); -const async = __webpack_require__(333); -const sync = __webpack_require__(338); -const settings_1 = __webpack_require__(339); -exports.Settings = settings_1.default; -function scandir(path, optionsOrSettingsOrCallback, callback) { - if (typeof optionsOrSettingsOrCallback === 'function') { - return async.read(path, getSettings(), optionsOrSettingsOrCallback); - } - async.read(path, getSettings(optionsOrSettingsOrCallback), callback); -} -exports.scandir = scandir; -function scandirSync(path, optionsOrSettings) { - const settings = getSettings(optionsOrSettings); - return sync.read(path, settings); -} -exports.scandirSync = scandirSync; -function getSettings(settingsOrOptions = {}) { - if (settingsOrOptions instanceof settings_1.default) { - return settingsOrOptions; - } - return new settings_1.default(settingsOrOptions); -} +const assert = __webpack_require__(140) +const path = __webpack_require__(4) +const fs = __webpack_require__(134) +let glob = undefined +try { + glob = __webpack_require__(147) +} catch (_err) { + // treat glob as optional. +} +const defaultGlobOpts = { + nosort: true, + silent: true +} -/***/ }), -/* 333 */ -/***/ (function(module, exports, __webpack_require__) { +// for EMFILE handling +let timeout = 0 -"use strict"; - -Object.defineProperty(exports, "__esModule", { value: true }); -const fsStat = __webpack_require__(324); -const rpl = __webpack_require__(334); -const constants_1 = __webpack_require__(335); -const utils = __webpack_require__(336); -function read(directory, settings, callback) { - if (!settings.stats && constants_1.IS_SUPPORT_READDIR_WITH_FILE_TYPES) { - return readdirWithFileTypes(directory, settings, callback); - } - return readdir(directory, settings, callback); -} -exports.read = read; -function readdirWithFileTypes(directory, settings, callback) { - settings.fs.readdir(directory, { withFileTypes: true }, (readdirError, dirents) => { - if (readdirError !== null) { - return callFailureCallback(callback, readdirError); - } - const entries = dirents.map((dirent) => ({ - dirent, - name: dirent.name, - path: `${directory}${settings.pathSegmentSeparator}${dirent.name}` - })); - if (!settings.followSymbolicLinks) { - return callSuccessCallback(callback, entries); - } - const tasks = entries.map((entry) => makeRplTaskEntry(entry, settings)); - rpl(tasks, (rplError, rplEntries) => { - if (rplError !== null) { - return callFailureCallback(callback, rplError); - } - callSuccessCallback(callback, rplEntries); - }); - }); -} -exports.readdirWithFileTypes = readdirWithFileTypes; -function makeRplTaskEntry(entry, settings) { - return (done) => { - if (!entry.dirent.isSymbolicLink()) { - return done(null, entry); - } - settings.fs.stat(entry.path, (statError, stats) => { - if (statError !== null) { - if (settings.throwErrorOnBrokenSymbolicLink) { - return done(statError); - } - return done(null, entry); - } - entry.dirent = utils.fs.createDirentFromStats(entry.name, stats); - return done(null, entry); - }); - }; -} -function readdir(directory, settings, callback) { - settings.fs.readdir(directory, (readdirError, names) => { - if (readdirError !== null) { - return callFailureCallback(callback, readdirError); - } - const filepaths = names.map((name) => `${directory}${settings.pathSegmentSeparator}${name}`); - const tasks = filepaths.map((filepath) => { - return (done) => fsStat.stat(filepath, settings.fsStatSettings, done); - }); - rpl(tasks, (rplError, results) => { - if (rplError !== null) { - return callFailureCallback(callback, rplError); - } - const entries = []; - names.forEach((name, index) => { - const stats = results[index]; - const entry = { - name, - path: filepaths[index], - dirent: utils.fs.createDirentFromStats(name, stats) - }; - if (settings.stats) { - entry.stats = stats; - } - entries.push(entry); - }); - callSuccessCallback(callback, entries); - }); - }); -} -exports.readdir = readdir; -function callFailureCallback(callback, error) { - callback(error); -} -function callSuccessCallback(callback, result) { - callback(null, result); -} +const isWindows = (process.platform === "win32") +const defaults = options => { + const methods = [ + 'unlink', + 'chmod', + 'stat', + 'lstat', + 'rmdir', + 'readdir' + ] + methods.forEach(m => { + options[m] = options[m] || fs[m] + m = m + 'Sync' + options[m] = options[m] || fs[m] + }) -/***/ }), -/* 334 */ -/***/ (function(module, exports) { + options.maxBusyTries = options.maxBusyTries || 3 + options.emfileWait = options.emfileWait || 1000 + if (options.glob === false) { + options.disableGlob = true + } + if (options.disableGlob !== true && glob === undefined) { + throw Error('glob dependency not found, set `options.disableGlob = true` if intentional') + } + options.disableGlob = options.disableGlob || false + options.glob = options.glob || defaultGlobOpts +} -module.exports = runParallel +const rimraf = (p, options, cb) => { + if (typeof options === 'function') { + cb = options + options = {} + } -function runParallel (tasks, cb) { - var results, pending, keys - var isSync = true + assert(p, 'rimraf: missing path') + assert.equal(typeof p, 'string', 'rimraf: path should be a string') + assert.equal(typeof cb, 'function', 'rimraf: callback function required') + assert(options, 'rimraf: invalid options argument provided') + assert.equal(typeof options, 'object', 'rimraf: options should be object') - if (Array.isArray(tasks)) { - results = [] - pending = tasks.length - } else { - keys = Object.keys(tasks) - results = {} - pending = keys.length - } + defaults(options) - function done (err) { - function end () { - if (cb) cb(err, results) - cb = null - } - if (isSync) process.nextTick(end) - else end() - } + let busyTries = 0 + let errState = null + let n = 0 - function each (i, err, result) { - results[i] = result - if (--pending === 0 || err) { - done(err) - } + const next = (er) => { + errState = errState || er + if (--n === 0) + cb(errState) } - if (!pending) { - // empty - done(null) - } else if (keys) { - // object - keys.forEach(function (key) { - tasks[key](function (err, result) { each(key, err, result) }) - }) - } else { - // array - tasks.forEach(function (task, i) { - task(function (err, result) { each(i, err, result) }) - }) - } + const afterGlob = (er, results) => { + if (er) + return cb(er) - isSync = false -} + n = results.length + if (n === 0) + return cb() + results.forEach(p => { + const CB = (er) => { + if (er) { + if ((er.code === "EBUSY" || er.code === "ENOTEMPTY" || er.code === "EPERM") && + busyTries < options.maxBusyTries) { + busyTries ++ + // try again, with the same exact callback as this one. + return setTimeout(() => rimraf_(p, options, CB), busyTries * 100) + } -/***/ }), -/* 335 */ -/***/ (function(module, exports, __webpack_require__) { + // this one won't happen if graceful-fs is used. + if (er.code === "EMFILE" && timeout < options.emfileWait) { + return setTimeout(() => rimraf_(p, options, CB), timeout ++) + } -"use strict"; - -Object.defineProperty(exports, "__esModule", { value: true }); -const NODE_PROCESS_VERSION_PARTS = process.versions.node.split('.'); -const MAJOR_VERSION = parseInt(NODE_PROCESS_VERSION_PARTS[0], 10); -const MINOR_VERSION = parseInt(NODE_PROCESS_VERSION_PARTS[1], 10); -const SUPPORTED_MAJOR_VERSION = 10; -const SUPPORTED_MINOR_VERSION = 10; -const IS_MATCHED_BY_MAJOR = MAJOR_VERSION > SUPPORTED_MAJOR_VERSION; -const IS_MATCHED_BY_MAJOR_AND_MINOR = MAJOR_VERSION === SUPPORTED_MAJOR_VERSION && MINOR_VERSION >= SUPPORTED_MINOR_VERSION; -/** - * IS `true` for Node.js 10.10 and greater. - */ -exports.IS_SUPPORT_READDIR_WITH_FILE_TYPES = IS_MATCHED_BY_MAJOR || IS_MATCHED_BY_MAJOR_AND_MINOR; + // already gone + if (er.code === "ENOENT") er = null + } + timeout = 0 + next(er) + } + rimraf_(p, options, CB) + }) + } -/***/ }), -/* 336 */ -/***/ (function(module, exports, __webpack_require__) { + if (options.disableGlob || !glob.hasMagic(p)) + return afterGlob(null, [p]) -"use strict"; - -Object.defineProperty(exports, "__esModule", { value: true }); -const fs = __webpack_require__(337); -exports.fs = fs; + options.lstat(p, (er, stat) => { + if (!er) + return afterGlob(null, [p]) + glob(p, options.glob, afterGlob) + }) -/***/ }), -/* 337 */ -/***/ (function(module, exports, __webpack_require__) { +} -"use strict"; - -Object.defineProperty(exports, "__esModule", { value: true }); -class DirentFromStats { - constructor(name, stats) { - this.name = name; - this.isBlockDevice = stats.isBlockDevice.bind(stats); - this.isCharacterDevice = stats.isCharacterDevice.bind(stats); - this.isDirectory = stats.isDirectory.bind(stats); - this.isFIFO = stats.isFIFO.bind(stats); - this.isFile = stats.isFile.bind(stats); - this.isSocket = stats.isSocket.bind(stats); - this.isSymbolicLink = stats.isSymbolicLink.bind(stats); - } -} -function createDirentFromStats(name, stats) { - return new DirentFromStats(name, stats); -} -exports.createDirentFromStats = createDirentFromStats; +// Two possible strategies. +// 1. Assume it's a file. unlink it, then do the dir stuff on EPERM or EISDIR +// 2. Assume it's a directory. readdir, then do the file stuff on ENOTDIR +// +// Both result in an extra syscall when you guess wrong. However, there +// are likely far more normal files in the world than directories. This +// is based on the assumption that a the average number of files per +// directory is >= 1. +// +// If anyone ever complains about this, then I guess the strategy could +// be made configurable somehow. But until then, YAGNI. +const rimraf_ = (p, options, cb) => { + assert(p) + assert(options) + assert(typeof cb === 'function') + // sunos lets the root user unlink directories, which is... weird. + // so we have to lstat here and make sure it's not a dir. + options.lstat(p, (er, st) => { + if (er && er.code === "ENOENT") + return cb(null) -/***/ }), -/* 338 */ -/***/ (function(module, exports, __webpack_require__) { + // Windows can EPERM on stat. Life is suffering. + if (er && er.code === "EPERM" && isWindows) + fixWinEPERM(p, options, er, cb) -"use strict"; - -Object.defineProperty(exports, "__esModule", { value: true }); -const fsStat = __webpack_require__(324); -const constants_1 = __webpack_require__(335); -const utils = __webpack_require__(336); -function read(directory, settings) { - if (!settings.stats && constants_1.IS_SUPPORT_READDIR_WITH_FILE_TYPES) { - return readdirWithFileTypes(directory, settings); - } - return readdir(directory, settings); -} -exports.read = read; -function readdirWithFileTypes(directory, settings) { - const dirents = settings.fs.readdirSync(directory, { withFileTypes: true }); - return dirents.map((dirent) => { - const entry = { - dirent, - name: dirent.name, - path: `${directory}${settings.pathSegmentSeparator}${dirent.name}` - }; - if (entry.dirent.isSymbolicLink() && settings.followSymbolicLinks) { - try { - const stats = settings.fs.statSync(entry.path); - entry.dirent = utils.fs.createDirentFromStats(entry.name, stats); - } - catch (error) { - if (settings.throwErrorOnBrokenSymbolicLink) { - throw error; - } - } - } - return entry; - }); -} -exports.readdirWithFileTypes = readdirWithFileTypes; -function readdir(directory, settings) { - const names = settings.fs.readdirSync(directory); - return names.map((name) => { - const entryPath = `${directory}${settings.pathSegmentSeparator}${name}`; - const stats = fsStat.statSync(entryPath, settings.fsStatSettings); - const entry = { - name, - path: entryPath, - dirent: utils.fs.createDirentFromStats(name, stats) - }; - if (settings.stats) { - entry.stats = stats; - } - return entry; - }); -} -exports.readdir = readdir; - - -/***/ }), -/* 339 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - -Object.defineProperty(exports, "__esModule", { value: true }); -const path = __webpack_require__(4); -const fsStat = __webpack_require__(324); -const fs = __webpack_require__(340); -class Settings { - constructor(_options = {}) { - this._options = _options; - this.followSymbolicLinks = this._getValue(this._options.followSymbolicLinks, false); - this.fs = fs.createFileSystemAdapter(this._options.fs); - this.pathSegmentSeparator = this._getValue(this._options.pathSegmentSeparator, path.sep); - this.stats = this._getValue(this._options.stats, false); - this.throwErrorOnBrokenSymbolicLink = this._getValue(this._options.throwErrorOnBrokenSymbolicLink, true); - this.fsStatSettings = new fsStat.Settings({ - followSymbolicLink: this.followSymbolicLinks, - fs: this.fs, - throwErrorOnBrokenSymbolicLink: this.throwErrorOnBrokenSymbolicLink - }); - } - _getValue(option, value) { - return option === undefined ? value : option; - } -} -exports.default = Settings; - - -/***/ }), -/* 340 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - -Object.defineProperty(exports, "__esModule", { value: true }); -const fs = __webpack_require__(133); -exports.FILE_SYSTEM_ADAPTER = { - lstat: fs.lstat, - stat: fs.stat, - lstatSync: fs.lstatSync, - statSync: fs.statSync, - readdir: fs.readdir, - readdirSync: fs.readdirSync -}; -function createFileSystemAdapter(fsMethods) { - if (fsMethods === undefined) { - return exports.FILE_SYSTEM_ADAPTER; - } - return Object.assign(Object.assign({}, exports.FILE_SYSTEM_ADAPTER), fsMethods); -} -exports.createFileSystemAdapter = createFileSystemAdapter; + if (st && st.isDirectory()) + return rmdir(p, options, er, cb) + options.unlink(p, er => { + if (er) { + if (er.code === "ENOENT") + return cb(null) + if (er.code === "EPERM") + return (isWindows) + ? fixWinEPERM(p, options, er, cb) + : rmdir(p, options, er, cb) + if (er.code === "EISDIR") + return rmdir(p, options, er, cb) + } + return cb(er) + }) + }) +} -/***/ }), -/* 341 */ -/***/ (function(module, exports, __webpack_require__) { +const fixWinEPERM = (p, options, er, cb) => { + assert(p) + assert(options) + assert(typeof cb === 'function') -"use strict"; + options.chmod(p, 0o666, er2 => { + if (er2) + cb(er2.code === "ENOENT" ? null : er) + else + options.stat(p, (er3, stats) => { + if (er3) + cb(er3.code === "ENOENT" ? null : er) + else if (stats.isDirectory()) + rmdir(p, options, er, cb) + else + options.unlink(p, cb) + }) + }) +} +const fixWinEPERMSync = (p, options, er) => { + assert(p) + assert(options) -var reusify = __webpack_require__(342) + try { + options.chmodSync(p, 0o666) + } catch (er2) { + if (er2.code === "ENOENT") + return + else + throw er + } -function fastqueue (context, worker, concurrency) { - if (typeof context === 'function') { - concurrency = worker - worker = context - context = null + let stats + try { + stats = options.statSync(p) + } catch (er3) { + if (er3.code === "ENOENT") + return + else + throw er } - var cache = reusify(Task) - var queueHead = null - var queueTail = null - var _running = 0 + if (stats.isDirectory()) + rmdirSync(p, options, er) + else + options.unlinkSync(p) +} - var self = { - push: push, - drain: noop, - saturated: noop, - pause: pause, - paused: false, - concurrency: concurrency, - running: running, - resume: resume, - idle: idle, - length: length, - unshift: unshift, - empty: noop, - kill: kill, - killAndDrain: killAndDrain - } +const rmdir = (p, options, originalEr, cb) => { + assert(p) + assert(options) + assert(typeof cb === 'function') - return self + // try to rmdir first, and only readdir on ENOTEMPTY or EEXIST (SunOS) + // if we guessed wrong, and it's not a directory, then + // raise the original error. + options.rmdir(p, er => { + if (er && (er.code === "ENOTEMPTY" || er.code === "EEXIST" || er.code === "EPERM")) + rmkids(p, options, cb) + else if (er && er.code === "ENOTDIR") + cb(originalEr) + else + cb(er) + }) +} - function running () { - return _running - } +const rmkids = (p, options, cb) => { + assert(p) + assert(options) + assert(typeof cb === 'function') - function pause () { - self.paused = true - } + options.readdir(p, (er, files) => { + if (er) + return cb(er) + let n = files.length + if (n === 0) + return options.rmdir(p, cb) + let errState + files.forEach(f => { + rimraf(path.join(p, f), options, er => { + if (errState) + return + if (er) + return cb(errState = er) + if (--n === 0) + options.rmdir(p, cb) + }) + }) + }) +} - function length () { - var current = queueHead - var counter = 0 +// this looks simpler, and is strictly *faster*, but will +// tie up the JavaScript thread and fail on excessively +// deep directory trees. +const rimrafSync = (p, options) => { + options = options || {} + defaults(options) - while (current) { - current = current.next - counter++ - } + assert(p, 'rimraf: missing path') + assert.equal(typeof p, 'string', 'rimraf: path should be a string') + assert(options, 'rimraf: missing options') + assert.equal(typeof options, 'object', 'rimraf: options should be object') - return counter - } + let results - function resume () { - if (!self.paused) return - self.paused = false - for (var i = 0; i < self.concurrency; i++) { - _running++ - release() + if (options.disableGlob || !glob.hasMagic(p)) { + results = [p] + } else { + try { + options.lstatSync(p) + results = [p] + } catch (er) { + results = glob.sync(p, options.glob) } } - function idle () { - return _running === 0 && self.length() === 0 - } + if (!results.length) + return - function push (value, done) { - var current = cache.get() + for (let i = 0; i < results.length; i++) { + const p = results[i] - current.context = context - current.release = release - current.value = value - current.callback = done || noop + let st + try { + st = options.lstatSync(p) + } catch (er) { + if (er.code === "ENOENT") + return - if (_running === self.concurrency || self.paused) { - if (queueTail) { - queueTail.next = current - queueTail = current - } else { - queueHead = current - queueTail = current - self.saturated() - } - } else { - _running++ - worker.call(context, current.value, current.worked) + // Windows can EPERM on stat. Life is suffering. + if (er.code === "EPERM" && isWindows) + fixWinEPERMSync(p, options, er) } - } - - function unshift (value, done) { - var current = cache.get() - - current.context = context - current.release = release - current.value = value - current.callback = done || noop - if (_running === self.concurrency || self.paused) { - if (queueHead) { - current.next = queueHead - queueHead = current - } else { - queueHead = current - queueTail = current - self.saturated() - } - } else { - _running++ - worker.call(context, current.value, current.worked) - } - } + try { + // sunos lets the root user unlink directories, which is... weird. + if (st && st.isDirectory()) + rmdirSync(p, options, null) + else + options.unlinkSync(p) + } catch (er) { + if (er.code === "ENOENT") + return + if (er.code === "EPERM") + return isWindows ? fixWinEPERMSync(p, options, er) : rmdirSync(p, options, er) + if (er.code !== "EISDIR") + throw er - function release (holder) { - if (holder) { - cache.release(holder) - } - var next = queueHead - if (next) { - if (!self.paused) { - if (queueTail === queueHead) { - queueTail = null - } - queueHead = next.next - next.next = null - worker.call(context, next.value, next.worked) - if (queueTail === null) { - self.empty() - } - } else { - _running-- - } - } else if (--_running === 0) { - self.drain() + rmdirSync(p, options, er) } } +} - function kill () { - queueHead = null - queueTail = null - self.drain = noop - } +const rmdirSync = (p, options, originalEr) => { + assert(p) + assert(options) - function killAndDrain () { - queueHead = null - queueTail = null - self.drain() - self.drain = noop + try { + options.rmdirSync(p) + } catch (er) { + if (er.code === "ENOENT") + return + if (er.code === "ENOTDIR") + throw originalEr + if (er.code === "ENOTEMPTY" || er.code === "EEXIST" || er.code === "EPERM") + rmkidsSync(p, options) } } -function noop () {} - -function Task () { - this.value = null - this.callback = noop - this.next = null - this.release = noop - this.context = null - - var self = this +const rmkidsSync = (p, options) => { + assert(p) + assert(options) + options.readdirSync(p).forEach(f => rimrafSync(path.join(p, f), options)) - this.worked = function worked (err, result) { - var callback = self.callback - self.value = null - self.callback = noop - callback.call(self.context, err, result) - self.release(self) - } + // We only end up here once we got ENOTEMPTY at least once, and + // at this point, we are guaranteed to have removed all the kids. + // So, we know that it won't be ENOENT or ENOTDIR or anything else. + // try really hard to delete stuff on windows, because it has a + // PROFOUNDLY annoying habit of not closing handles promptly when + // files are deleted, resulting in spurious ENOTEMPTY errors. + const retries = isWindows ? 100 : 1 + let i = 0 + do { + let threw = true + try { + const ret = options.rmdirSync(p, options) + threw = false + return ret + } finally { + if (++i < retries && threw) + continue + } + } while (true) } -module.exports = fastqueue +module.exports = rimraf +rimraf.sync = rimrafSync /***/ }), -/* 342 */ +/* 363 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; +const AggregateError = __webpack_require__(364); -function reusify (Constructor) { - var head = new Constructor() - var tail = head +module.exports = async ( + iterable, + mapper, + { + concurrency = Infinity, + stopOnError = true + } = {} +) => { + return new Promise((resolve, reject) => { + if (typeof mapper !== 'function') { + throw new TypeError('Mapper function is required'); + } - function get () { - var current = head + if (!(typeof concurrency === 'number' && concurrency >= 1)) { + throw new TypeError(`Expected \`concurrency\` to be a number from 1 and up, got \`${concurrency}\` (${typeof concurrency})`); + } - if (current.next) { - head = current.next - } else { - head = new Constructor() - tail = head - } + const ret = []; + const errors = []; + const iterator = iterable[Symbol.iterator](); + let isRejected = false; + let isIterableDone = false; + let resolvingCount = 0; + let currentIndex = 0; - current.next = null + const next = () => { + if (isRejected) { + return; + } - return current - } + const nextItem = iterator.next(); + const i = currentIndex; + currentIndex++; - function release (obj) { - tail.next = obj - tail = obj - } + if (nextItem.done) { + isIterableDone = true; - return { - get: get, - release: release - } -} + if (resolvingCount === 0) { + if (!stopOnError && errors.length !== 0) { + reject(new AggregateError(errors)); + } else { + resolve(ret); + } + } -module.exports = reusify + return; + } + + resolvingCount++; + + (async () => { + try { + const element = await nextItem.value; + ret[i] = await mapper(element, i); + resolvingCount--; + next(); + } catch (error) { + if (stopOnError) { + isRejected = true; + reject(error); + } else { + errors.push(error); + resolvingCount--; + next(); + } + } + })(); + }; + + for (let i = 0; i < concurrency; i++) { + next(); + + if (isIterableDone) { + break; + } + } + }); +}; /***/ }), -/* 343 */ +/* 364 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; - -Object.defineProperty(exports, "__esModule", { value: true }); -function isFatalError(settings, error) { - if (settings.errorFilter === null) { - return true; - } - return !settings.errorFilter(error); -} -exports.isFatalError = isFatalError; -function isAppliedFilter(filter, value) { - return filter === null || filter(value); -} -exports.isAppliedFilter = isAppliedFilter; -function replacePathSegmentSeparator(filepath, separator) { - return filepath.split(/[\\/]/).join(separator); -} -exports.replacePathSegmentSeparator = replacePathSegmentSeparator; -function joinPathSegments(a, b, separator) { - if (a === '') { - return b; - } - return a + separator + b; -} -exports.joinPathSegments = joinPathSegments; +const indentString = __webpack_require__(365); +const cleanStack = __webpack_require__(366); -/***/ }), -/* 344 */ -/***/ (function(module, exports, __webpack_require__) { +const cleanInternalStack = stack => stack.replace(/\s+at .*aggregate-error\/index.js:\d+:\d+\)?/g, ''); -"use strict"; - -Object.defineProperty(exports, "__esModule", { value: true }); -const common = __webpack_require__(343); -class Reader { - constructor(_root, _settings) { - this._root = _root; - this._settings = _settings; - this._root = common.replacePathSegmentSeparator(_root, _settings.pathSegmentSeparator); - } -} -exports.default = Reader; +class AggregateError extends Error { + constructor(errors) { + if (!Array.isArray(errors)) { + throw new TypeError(`Expected input to be an Array, got ${typeof errors}`); + } + errors = [...errors].map(error => { + if (error instanceof Error) { + return error; + } -/***/ }), -/* 345 */ -/***/ (function(module, exports, __webpack_require__) { + if (error !== null && typeof error === 'object') { + // Handle plain error objects with message property and/or possibly other metadata + return Object.assign(new Error(error.message), error); + } -"use strict"; - -Object.defineProperty(exports, "__esModule", { value: true }); -const stream_1 = __webpack_require__(137); -const async_1 = __webpack_require__(331); -class StreamProvider { - constructor(_root, _settings) { - this._root = _root; - this._settings = _settings; - this._reader = new async_1.default(this._root, this._settings); - this._stream = new stream_1.Readable({ - objectMode: true, - read: () => { }, - destroy: this._reader.destroy.bind(this._reader) - }); - } - read() { - this._reader.onError((error) => { - this._stream.emit('error', error); - }); - this._reader.onEntry((entry) => { - this._stream.push(entry); - }); - this._reader.onEnd(() => { - this._stream.push(null); - }); - this._reader.read(); - return this._stream; - } -} -exports.default = StreamProvider; + return new Error(error); + }); + let message = errors + .map(error => { + // The `stack` property is not standardized, so we can't assume it exists + return typeof error.stack === 'string' ? cleanInternalStack(cleanStack(error.stack)) : String(error); + }) + .join('\n'); + message = '\n' + indentString(message, 4); + super(message); -/***/ }), -/* 346 */ -/***/ (function(module, exports, __webpack_require__) { + this.name = 'AggregateError'; -"use strict"; - -Object.defineProperty(exports, "__esModule", { value: true }); -const sync_1 = __webpack_require__(347); -class SyncProvider { - constructor(_root, _settings) { - this._root = _root; - this._settings = _settings; - this._reader = new sync_1.default(this._root, this._settings); - } - read() { - return this._reader.read(); - } -} -exports.default = SyncProvider; + Object.defineProperty(this, '_errors', {value: errors}); + } + + * [Symbol.iterator]() { + for (const error of this._errors) { + yield error; + } + } +} + +module.exports = AggregateError; /***/ }), -/* 347 */ +/* 365 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; - -Object.defineProperty(exports, "__esModule", { value: true }); -const fsScandir = __webpack_require__(332); -const common = __webpack_require__(343); -const reader_1 = __webpack_require__(344); -class SyncReader extends reader_1.default { - constructor() { - super(...arguments); - this._scandir = fsScandir.scandirSync; - this._storage = new Set(); - this._queue = new Set(); - } - read() { - this._pushToQueue(this._root, this._settings.basePath); - this._handleQueue(); - return [...this._storage]; - } - _pushToQueue(directory, base) { - this._queue.add({ directory, base }); - } - _handleQueue() { - for (const item of this._queue.values()) { - this._handleDirectory(item.directory, item.base); - } - } - _handleDirectory(directory, base) { - try { - const entries = this._scandir(directory, this._settings.fsScandirSettings); - for (const entry of entries) { - this._handleEntry(entry, base); - } - } - catch (error) { - this._handleError(error); - } - } - _handleError(error) { - if (!common.isFatalError(this._settings, error)) { - return; - } - throw error; - } - _handleEntry(entry, base) { - const fullpath = entry.path; - if (base !== undefined) { - entry.path = common.joinPathSegments(base, entry.name, this._settings.pathSegmentSeparator); - } - if (common.isAppliedFilter(this._settings.entryFilter, entry)) { - this._pushToStorage(entry); - } - if (entry.dirent.isDirectory() && common.isAppliedFilter(this._settings.deepFilter, entry)) { - this._pushToQueue(fullpath, entry.path); - } - } - _pushToStorage(entry) { - this._storage.add(entry); - } -} -exports.default = SyncReader; -/***/ }), -/* 348 */ -/***/ (function(module, exports, __webpack_require__) { +module.exports = (string, count = 1, options) => { + options = { + indent: ' ', + includeEmptyLines: false, + ...options + }; -"use strict"; - -Object.defineProperty(exports, "__esModule", { value: true }); -const path = __webpack_require__(4); -const fsScandir = __webpack_require__(332); -class Settings { - constructor(_options = {}) { - this._options = _options; - this.basePath = this._getValue(this._options.basePath, undefined); - this.concurrency = this._getValue(this._options.concurrency, Infinity); - this.deepFilter = this._getValue(this._options.deepFilter, null); - this.entryFilter = this._getValue(this._options.entryFilter, null); - this.errorFilter = this._getValue(this._options.errorFilter, null); - this.pathSegmentSeparator = this._getValue(this._options.pathSegmentSeparator, path.sep); - this.fsScandirSettings = new fsScandir.Settings({ - followSymbolicLinks: this._options.followSymbolicLinks, - fs: this._options.fs, - pathSegmentSeparator: this._options.pathSegmentSeparator, - stats: this._options.stats, - throwErrorOnBrokenSymbolicLink: this._options.throwErrorOnBrokenSymbolicLink - }); - } - _getValue(option, value) { - return option === undefined ? value : option; - } -} -exports.default = Settings; + if (typeof string !== 'string') { + throw new TypeError( + `Expected \`input\` to be a \`string\`, got \`${typeof string}\`` + ); + } + if (typeof count !== 'number') { + throw new TypeError( + `Expected \`count\` to be a \`number\`, got \`${typeof count}\`` + ); + } -/***/ }), -/* 349 */ -/***/ (function(module, exports, __webpack_require__) { + if (typeof options.indent !== 'string') { + throw new TypeError( + `Expected \`options.indent\` to be a \`string\`, got \`${typeof options.indent}\`` + ); + } -"use strict"; - -Object.defineProperty(exports, "__esModule", { value: true }); -const path = __webpack_require__(4); -const fsStat = __webpack_require__(324); -const utils = __webpack_require__(294); -class Reader { - constructor(_settings) { - this._settings = _settings; - this._fsStatSettings = new fsStat.Settings({ - followSymbolicLink: this._settings.followSymbolicLinks, - fs: this._settings.fs, - throwErrorOnBrokenSymbolicLink: this._settings.followSymbolicLinks - }); - } - _getFullEntryPath(filepath) { - return path.resolve(this._settings.cwd, filepath); - } - _makeEntry(stats, pattern) { - const entry = { - name: pattern, - path: pattern, - dirent: utils.fs.createDirentFromStats(pattern, stats) - }; - if (this._settings.stats) { - entry.stats = stats; - } - return entry; - } - _isFatalError(error) { - return !utils.errno.isEnoentCodeError(error) && !this._settings.suppressErrors; - } -} -exports.default = Reader; + if (count === 0) { + return string; + } + + const regex = options.includeEmptyLines ? /^/gm : /^(?!\s*$)/gm; + + return string.replace(regex, options.indent.repeat(count)); +}; /***/ }), -/* 350 */ +/* 366 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; - -Object.defineProperty(exports, "__esModule", { value: true }); -const path = __webpack_require__(4); -const deep_1 = __webpack_require__(351); -const entry_1 = __webpack_require__(354); -const error_1 = __webpack_require__(355); -const entry_2 = __webpack_require__(356); -class Provider { - constructor(_settings) { - this._settings = _settings; - this.errorFilter = new error_1.default(this._settings); - this.entryFilter = new entry_1.default(this._settings, this._getMicromatchOptions()); - this.deepFilter = new deep_1.default(this._settings, this._getMicromatchOptions()); - this.entryTransformer = new entry_2.default(this._settings); - } - _getRootDirectory(task) { - return path.resolve(this._settings.cwd, task.base); - } - _getReaderOptions(task) { - const basePath = task.base === '.' ? '' : task.base; - return { - basePath, - pathSegmentSeparator: '/', - concurrency: this._settings.concurrency, - deepFilter: this.deepFilter.getFilter(basePath, task.positive, task.negative), - entryFilter: this.entryFilter.getFilter(task.positive, task.negative), - errorFilter: this.errorFilter.getFilter(), - followSymbolicLinks: this._settings.followSymbolicLinks, - fs: this._settings.fs, - stats: this._settings.stats, - throwErrorOnBrokenSymbolicLink: this._settings.throwErrorOnBrokenSymbolicLink, - transform: this.entryTransformer.getTransformer() - }; - } - _getMicromatchOptions() { - return { - dot: this._settings.dot, - matchBase: this._settings.baseNameMatch, - nobrace: !this._settings.braceExpansion, - nocase: !this._settings.caseSensitiveMatch, - noext: !this._settings.extglob, - noglobstar: !this._settings.globstar, - posix: true, - strictSlashes: false - }; - } -} -exports.default = Provider; +const os = __webpack_require__(121); -/***/ }), -/* 351 */ -/***/ (function(module, exports, __webpack_require__) { +const extractPathRegex = /\s+at.*(?:\(|\s)(.*)\)?/; +const pathRegex = /^(?:(?:(?:node|(?:internal\/[\w/]*|.*node_modules\/(?:babel-polyfill|pirates)\/.*)?\w+)\.js:\d+:\d+)|native)/; +const homeDir = typeof os.homedir === 'undefined' ? '' : os.homedir(); -"use strict"; - -Object.defineProperty(exports, "__esModule", { value: true }); -const utils = __webpack_require__(294); -const partial_1 = __webpack_require__(352); -class DeepFilter { - constructor(_settings, _micromatchOptions) { - this._settings = _settings; - this._micromatchOptions = _micromatchOptions; - } - getFilter(basePath, positive, negative) { - const matcher = this._getMatcher(positive); - const negativeRe = this._getNegativePatternsRe(negative); - return (entry) => this._filter(basePath, entry, matcher, negativeRe); - } - _getMatcher(patterns) { - return new partial_1.default(patterns, this._settings, this._micromatchOptions); - } - _getNegativePatternsRe(patterns) { - const affectDepthOfReadingPatterns = patterns.filter(utils.pattern.isAffectDepthOfReadingPattern); - return utils.pattern.convertPatternsToRe(affectDepthOfReadingPatterns, this._micromatchOptions); - } - _filter(basePath, entry, matcher, negativeRe) { - const depth = this._getEntryLevel(basePath, entry.path); - if (this._isSkippedByDeep(depth)) { - return false; - } - if (this._isSkippedSymbolicLink(entry)) { - return false; - } - const filepath = utils.path.removeLeadingDotSegment(entry.path); - if (this._isSkippedByPositivePatterns(filepath, matcher)) { - return false; - } - return this._isSkippedByNegativePatterns(filepath, negativeRe); - } - _isSkippedByDeep(entryDepth) { - return entryDepth >= this._settings.deep; - } - _isSkippedSymbolicLink(entry) { - return !this._settings.followSymbolicLinks && entry.dirent.isSymbolicLink(); - } - _getEntryLevel(basePath, entryPath) { - const basePathDepth = basePath.split('/').length; - const entryPathDepth = entryPath.split('/').length; - return entryPathDepth - (basePath === '' ? 0 : basePathDepth); - } - _isSkippedByPositivePatterns(entryPath, matcher) { - return !this._settings.baseNameMatch && !matcher.match(entryPath); - } - _isSkippedByNegativePatterns(entryPath, negativeRe) { - return !utils.pattern.matchAny(entryPath, negativeRe); - } -} -exports.default = DeepFilter; +module.exports = (stack, options) => { + options = Object.assign({pretty: false}, options); + return stack.replace(/\\/g, '/') + .split('\n') + .filter(line => { + const pathMatches = line.match(extractPathRegex); + if (pathMatches === null || !pathMatches[1]) { + return true; + } -/***/ }), -/* 352 */ -/***/ (function(module, exports, __webpack_require__) { + const match = pathMatches[1]; -"use strict"; - -Object.defineProperty(exports, "__esModule", { value: true }); -const matcher_1 = __webpack_require__(353); -class PartialMatcher extends matcher_1.default { - match(filepath) { - const parts = filepath.split('/'); - const levels = parts.length; - const patterns = this._storage.filter((info) => !info.complete || info.segments.length > levels); - for (const pattern of patterns) { - const section = pattern.sections[0]; - /** - * In this case, the pattern has a globstar and we must read all directories unconditionally, - * but only if the level has reached the end of the first group. - * - * fixtures/{a,b}/** - * ^ true/false ^ always true - */ - if (!pattern.complete && levels > section.length) { - return true; - } - const match = parts.every((part, index) => { - const segment = pattern.segments[index]; - if (segment.dynamic && segment.patternRe.test(part)) { - return true; - } - if (!segment.dynamic && segment.pattern === part) { - return true; - } - return false; - }); - if (match) { - return true; - } - } - return false; - } -} -exports.default = PartialMatcher; + // Electron + if ( + match.includes('.app/Contents/Resources/electron.asar') || + match.includes('.app/Contents/Resources/default_app.asar') + ) { + return false; + } + + return !pathRegex.test(match); + }) + .filter(line => line.trim() !== '') + .map(line => { + if (options.pretty) { + return line.replace(extractPathRegex, (m, p1) => m.replace(p1, p1.replace(homeDir, '~'))); + } + + return line; + }) + .join('\n'); +}; /***/ }), -/* 353 */ +/* 367 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; - -Object.defineProperty(exports, "__esModule", { value: true }); -const utils = __webpack_require__(294); -class Matcher { - constructor(_patterns, _settings, _micromatchOptions) { - this._patterns = _patterns; - this._settings = _settings; - this._micromatchOptions = _micromatchOptions; - this._storage = []; - this._fillStorage(); - } - _fillStorage() { - /** - * The original pattern may include `{,*,**,a/*}`, which will lead to problems with matching (unresolved level). - * So, before expand patterns with brace expansion into separated patterns. - */ - const patterns = utils.pattern.expandPatternsWithBraceExpansion(this._patterns); - for (const pattern of patterns) { - const segments = this._getPatternSegments(pattern); - const sections = this._splitSegmentsIntoSections(segments); - this._storage.push({ - complete: sections.length <= 1, - pattern, - segments, - sections - }); - } - } - _getPatternSegments(pattern) { - const parts = utils.pattern.getPatternParts(pattern, this._micromatchOptions); - return parts.map((part) => { - const dynamic = utils.pattern.isDynamicPattern(part, this._settings); - if (!dynamic) { - return { - dynamic: false, - pattern: part - }; - } - return { - dynamic: true, - pattern: part, - patternRe: utils.pattern.makeRe(part, this._micromatchOptions) - }; - }); - } - _splitSegmentsIntoSections(segments) { - return utils.array.splitWhen(segments, (segment) => segment.dynamic && utils.pattern.hasGlobStar(segment.pattern)); - } -} -exports.default = Matcher; +const readline = __webpack_require__(368); +const chalk = __webpack_require__(369); +const cliCursor = __webpack_require__(376); +const cliSpinners = __webpack_require__(380); +const logSymbols = __webpack_require__(382); +const stripAnsi = __webpack_require__(391); +const wcwidth = __webpack_require__(393); +const isInteractive = __webpack_require__(397); +const MuteStream = __webpack_require__(398); -/***/ }), -/* 354 */ -/***/ (function(module, exports, __webpack_require__) { +const TEXT = Symbol('text'); +const PREFIX_TEXT = Symbol('prefixText'); -"use strict"; - -Object.defineProperty(exports, "__esModule", { value: true }); -const utils = __webpack_require__(294); -class EntryFilter { - constructor(_settings, _micromatchOptions) { - this._settings = _settings; - this._micromatchOptions = _micromatchOptions; - this.index = new Map(); - } - getFilter(positive, negative) { - const positiveRe = utils.pattern.convertPatternsToRe(positive, this._micromatchOptions); - const negativeRe = utils.pattern.convertPatternsToRe(negative, this._micromatchOptions); - return (entry) => this._filter(entry, positiveRe, negativeRe); - } - _filter(entry, positiveRe, negativeRe) { - if (this._settings.unique) { - if (this._isDuplicateEntry(entry)) { - return false; - } - this._createIndexRecord(entry); - } - if (this._onlyFileFilter(entry) || this._onlyDirectoryFilter(entry)) { - return false; - } - if (this._isSkippedByAbsoluteNegativePatterns(entry, negativeRe)) { - return false; - } - const filepath = this._settings.baseNameMatch ? entry.name : entry.path; - return this._isMatchToPatterns(filepath, positiveRe) && !this._isMatchToPatterns(entry.path, negativeRe); - } - _isDuplicateEntry(entry) { - return this.index.has(entry.path); - } - _createIndexRecord(entry) { - this.index.set(entry.path, undefined); - } - _onlyFileFilter(entry) { - return this._settings.onlyFiles && !entry.dirent.isFile(); - } - _onlyDirectoryFilter(entry) { - return this._settings.onlyDirectories && !entry.dirent.isDirectory(); - } - _isSkippedByAbsoluteNegativePatterns(entry, negativeRe) { - if (!this._settings.absolute) { - return false; - } - const fullpath = utils.path.makeAbsolute(this._settings.cwd, entry.path); - return this._isMatchToPatterns(fullpath, negativeRe); - } - _isMatchToPatterns(entryPath, patternsRe) { - const filepath = utils.path.removeLeadingDotSegment(entryPath); - return utils.pattern.matchAny(filepath, patternsRe); - } -} -exports.default = EntryFilter; +const ASCII_ETX_CODE = 0x03; // Ctrl+C emits this code +class StdinDiscarder { + constructor() { + this.requests = 0; + + this.mutedStream = new MuteStream(); + this.mutedStream.pipe(process.stdout); + this.mutedStream.mute(); + + const self = this; + this.ourEmit = function (event, data, ...args) { + const {stdin} = process; + if (self.requests > 0 || stdin.emit === self.ourEmit) { + if (event === 'keypress') { // Fixes readline behavior + return; + } -/***/ }), -/* 355 */ -/***/ (function(module, exports, __webpack_require__) { + if (event === 'data' && data.includes(ASCII_ETX_CODE)) { + process.emit('SIGINT'); + } -"use strict"; - -Object.defineProperty(exports, "__esModule", { value: true }); -const utils = __webpack_require__(294); -class ErrorFilter { - constructor(_settings) { - this._settings = _settings; - } - getFilter() { - return (error) => this._isNonFatalError(error); - } - _isNonFatalError(error) { - return utils.errno.isEnoentCodeError(error) || this._settings.suppressErrors; - } -} -exports.default = ErrorFilter; + Reflect.apply(self.oldEmit, this, [event, data, ...args]); + } else { + Reflect.apply(process.stdin.emit, this, [event, data, ...args]); + } + }; + } + start() { + this.requests++; -/***/ }), -/* 356 */ -/***/ (function(module, exports, __webpack_require__) { + if (this.requests === 1) { + this.realStart(); + } + } -"use strict"; - -Object.defineProperty(exports, "__esModule", { value: true }); -const utils = __webpack_require__(294); -class EntryTransformer { - constructor(_settings) { - this._settings = _settings; - } - getTransformer() { - return (entry) => this._transform(entry); - } - _transform(entry) { - let filepath = entry.path; - if (this._settings.absolute) { - filepath = utils.path.makeAbsolute(this._settings.cwd, filepath); - filepath = utils.path.unixify(filepath); - } - if (this._settings.markDirectories && entry.dirent.isDirectory()) { - filepath += '/'; - } - if (!this._settings.objectMode) { - return filepath; - } - return Object.assign(Object.assign({}, entry), { path: filepath }); - } -} -exports.default = EntryTransformer; + stop() { + if (this.requests <= 0) { + throw new Error('`stop` called more times than `start`'); + } + this.requests--; -/***/ }), -/* 357 */ -/***/ (function(module, exports, __webpack_require__) { + if (this.requests === 0) { + this.realStop(); + } + } -"use strict"; - -Object.defineProperty(exports, "__esModule", { value: true }); -const stream_1 = __webpack_require__(137); -const stream_2 = __webpack_require__(323); -const provider_1 = __webpack_require__(350); -class ProviderStream extends provider_1.default { - constructor() { - super(...arguments); - this._reader = new stream_2.default(this._settings); - } - read(task) { - const root = this._getRootDirectory(task); - const options = this._getReaderOptions(task); - const source = this.api(root, task, options); - const destination = new stream_1.Readable({ objectMode: true, read: () => { } }); - source - .once('error', (error) => destination.emit('error', error)) - .on('data', (entry) => destination.emit('data', options.transform(entry))) - .once('end', () => destination.emit('end')); - destination - .once('close', () => source.destroy()); - return destination; - } - api(root, task, options) { - if (task.dynamic) { - return this._reader.dynamic(root, options); - } - return this._reader.static(task.patterns, options); - } -} -exports.default = ProviderStream; + realStart() { + // No known way to make it work reliably on Windows + if (process.platform === 'win32') { + return; + } + this.rl = readline.createInterface({ + input: process.stdin, + output: this.mutedStream + }); -/***/ }), -/* 358 */ -/***/ (function(module, exports, __webpack_require__) { + this.rl.on('SIGINT', () => { + if (process.listenerCount('SIGINT') === 0) { + process.emit('SIGINT'); + } else { + this.rl.close(); + process.kill(process.pid, 'SIGINT'); + } + }); + } -"use strict"; - -Object.defineProperty(exports, "__esModule", { value: true }); -const sync_1 = __webpack_require__(359); -const provider_1 = __webpack_require__(350); -class ProviderSync extends provider_1.default { - constructor() { - super(...arguments); - this._reader = new sync_1.default(this._settings); - } - read(task) { - const root = this._getRootDirectory(task); - const options = this._getReaderOptions(task); - const entries = this.api(root, task, options); - return entries.map(options.transform); - } - api(root, task, options) { - if (task.dynamic) { - return this._reader.dynamic(root, options); - } - return this._reader.static(task.patterns, options); - } -} -exports.default = ProviderSync; + realStop() { + if (process.platform === 'win32') { + return; + } + this.rl.close(); + this.rl = undefined; + } +} -/***/ }), -/* 359 */ -/***/ (function(module, exports, __webpack_require__) { +let stdinDiscarder; -"use strict"; - -Object.defineProperty(exports, "__esModule", { value: true }); -const fsStat = __webpack_require__(324); -const fsWalk = __webpack_require__(329); -const reader_1 = __webpack_require__(349); -class ReaderSync extends reader_1.default { - constructor() { - super(...arguments); - this._walkSync = fsWalk.walkSync; - this._statSync = fsStat.statSync; - } - dynamic(root, options) { - return this._walkSync(root, options); - } - static(patterns, options) { - const entries = []; - for (const pattern of patterns) { - const filepath = this._getFullEntryPath(pattern); - const entry = this._getEntry(filepath, pattern, options); - if (entry === null || !options.entryFilter(entry)) { - continue; - } - entries.push(entry); - } - return entries; - } - _getEntry(filepath, pattern, options) { - try { - const stats = this._getStat(filepath); - return this._makeEntry(stats, pattern); - } - catch (error) { - if (options.errorFilter(error)) { - return null; - } - throw error; - } - } - _getStat(filepath) { - return this._statSync(filepath, this._fsStatSettings); - } -} -exports.default = ReaderSync; +class Ora { + constructor(options) { + if (!stdinDiscarder) { + stdinDiscarder = new StdinDiscarder(); + } + if (typeof options === 'string') { + options = { + text: options + }; + } -/***/ }), -/* 360 */ -/***/ (function(module, exports, __webpack_require__) { + this.options = { + text: '', + color: 'cyan', + stream: process.stderr, + discardStdin: true, + ...options + }; -"use strict"; - -Object.defineProperty(exports, "__esModule", { value: true }); -const fs = __webpack_require__(133); -const os = __webpack_require__(120); -const CPU_COUNT = os.cpus().length; -exports.DEFAULT_FILE_SYSTEM_ADAPTER = { - lstat: fs.lstat, - lstatSync: fs.lstatSync, - stat: fs.stat, - statSync: fs.statSync, - readdir: fs.readdir, - readdirSync: fs.readdirSync -}; -class Settings { - constructor(_options = {}) { - this._options = _options; - this.absolute = this._getValue(this._options.absolute, false); - this.baseNameMatch = this._getValue(this._options.baseNameMatch, false); - this.braceExpansion = this._getValue(this._options.braceExpansion, true); - this.caseSensitiveMatch = this._getValue(this._options.caseSensitiveMatch, true); - this.concurrency = this._getValue(this._options.concurrency, CPU_COUNT); - this.cwd = this._getValue(this._options.cwd, process.cwd()); - this.deep = this._getValue(this._options.deep, Infinity); - this.dot = this._getValue(this._options.dot, false); - this.extglob = this._getValue(this._options.extglob, true); - this.followSymbolicLinks = this._getValue(this._options.followSymbolicLinks, true); - this.fs = this._getFileSystemMethods(this._options.fs); - this.globstar = this._getValue(this._options.globstar, true); - this.ignore = this._getValue(this._options.ignore, []); - this.markDirectories = this._getValue(this._options.markDirectories, false); - this.objectMode = this._getValue(this._options.objectMode, false); - this.onlyDirectories = this._getValue(this._options.onlyDirectories, false); - this.onlyFiles = this._getValue(this._options.onlyFiles, true); - this.stats = this._getValue(this._options.stats, false); - this.suppressErrors = this._getValue(this._options.suppressErrors, false); - this.throwErrorOnBrokenSymbolicLink = this._getValue(this._options.throwErrorOnBrokenSymbolicLink, false); - this.unique = this._getValue(this._options.unique, true); - if (this.onlyDirectories) { - this.onlyFiles = false; - } - if (this.stats) { - this.objectMode = true; - } - } - _getValue(option, value) { - return option === undefined ? value : option; - } - _getFileSystemMethods(methods = {}) { - return Object.assign(Object.assign({}, exports.DEFAULT_FILE_SYSTEM_ADAPTER), methods); - } -} -exports.default = Settings; + this.spinner = this.options.spinner; + this.color = this.options.color; + this.hideCursor = this.options.hideCursor !== false; + this.interval = this.options.interval || this.spinner.interval || 100; + this.stream = this.options.stream; + this.id = undefined; + this.isEnabled = typeof this.options.isEnabled === 'boolean' ? this.options.isEnabled : isInteractive({stream: this.stream}); -/***/ }), -/* 361 */ -/***/ (function(module, exports, __webpack_require__) { + // Set *after* `this.stream` + this.text = this.options.text; + this.prefixText = this.options.prefixText; + this.linesToClear = 0; + this.indent = this.options.indent; + this.discardStdin = this.options.discardStdin; + this.isDiscardingStdin = false; + } -"use strict"; + get indent() { + return this._indent; + } -const path = __webpack_require__(4); -const pathType = __webpack_require__(362); + set indent(indent = 0) { + if (!(indent >= 0 && Number.isInteger(indent))) { + throw new Error('The `indent` option must be an integer from 0 and up'); + } -const getExtensions = extensions => extensions.length > 1 ? `{${extensions.join(',')}}` : extensions[0]; + this._indent = indent; + } -const getPath = (filepath, cwd) => { - const pth = filepath[0] === '!' ? filepath.slice(1) : filepath; - return path.isAbsolute(pth) ? pth : path.join(cwd, pth); -}; + _updateInterval(interval) { + if (interval !== undefined) { + this.interval = interval; + } + } -const addExtensions = (file, extensions) => { - if (path.extname(file)) { - return `**/${file}`; + get spinner() { + return this._spinner; } - return `**/${file}.${getExtensions(extensions)}`; -}; + set spinner(spinner) { + this.frameIndex = 0; -const getGlob = (directory, options) => { - if (options.files && !Array.isArray(options.files)) { - throw new TypeError(`Expected \`files\` to be of type \`Array\` but received type \`${typeof options.files}\``); - } + if (typeof spinner === 'object') { + if (spinner.frames === undefined) { + throw new Error('The given spinner must have a `frames` property'); + } - if (options.extensions && !Array.isArray(options.extensions)) { - throw new TypeError(`Expected \`extensions\` to be of type \`Array\` but received type \`${typeof options.extensions}\``); + this._spinner = spinner; + } else if (process.platform === 'win32') { + this._spinner = cliSpinners.line; + } else if (spinner === undefined) { + // Set default spinner + this._spinner = cliSpinners.dots; + } else if (cliSpinners[spinner]) { + this._spinner = cliSpinners[spinner]; + } else { + throw new Error(`There is no built-in spinner named '${spinner}'. See https://github.com/sindresorhus/cli-spinners/blob/master/spinners.json for a full list.`); + } + + this._updateInterval(this._spinner.interval); } - if (options.files && options.extensions) { - return options.files.map(x => path.posix.join(directory, addExtensions(x, options.extensions))); + get text() { + return this[TEXT]; } - if (options.files) { - return options.files.map(x => path.posix.join(directory, `**/${x}`)); + get prefixText() { + return this[PREFIX_TEXT]; } - if (options.extensions) { - return [path.posix.join(directory, `**/*.${getExtensions(options.extensions)}`)]; + get isSpinning() { + return this.id !== undefined; } - return [path.posix.join(directory, '**')]; -}; + updateLineCount() { + const columns = this.stream.columns || 80; + const fullPrefixText = (typeof this[PREFIX_TEXT] === 'string') ? this[PREFIX_TEXT] + '-' : ''; + this.lineCount = stripAnsi(fullPrefixText + '--' + this[TEXT]).split('\n').reduce((count, line) => { + return count + Math.max(1, Math.ceil(wcwidth(line) / columns)); + }, 0); + } -module.exports = async (input, options) => { - options = { - cwd: process.cwd(), - ...options - }; + set text(value) { + this[TEXT] = value; + this.updateLineCount(); + } - if (typeof options.cwd !== 'string') { - throw new TypeError(`Expected \`cwd\` to be of type \`string\` but received type \`${typeof options.cwd}\``); + set prefixText(value) { + this[PREFIX_TEXT] = value; + this.updateLineCount(); } - const globs = await Promise.all([].concat(input).map(async x => { - const isDirectory = await pathType.isDirectory(getPath(x, options.cwd)); - return isDirectory ? getGlob(x, options) : x; - })); + frame() { + const {frames} = this.spinner; + let frame = frames[this.frameIndex]; - return [].concat.apply([], globs); // eslint-disable-line prefer-spread -}; + if (this.color) { + frame = chalk[this.color](frame); + } -module.exports.sync = (input, options) => { - options = { - cwd: process.cwd(), - ...options - }; + this.frameIndex = ++this.frameIndex % frames.length; + const fullPrefixText = (typeof this.prefixText === 'string' && this.prefixText !== '') ? this.prefixText + ' ' : ''; + const fullText = typeof this.text === 'string' ? ' ' + this.text : ''; - if (typeof options.cwd !== 'string') { - throw new TypeError(`Expected \`cwd\` to be of type \`string\` but received type \`${typeof options.cwd}\``); + return fullPrefixText + frame + fullText; } - const globs = [].concat(input).map(x => pathType.isDirectorySync(getPath(x, options.cwd)) ? getGlob(x, options) : x); + clear() { + if (!this.isEnabled || !this.stream.isTTY) { + return this; + } - return [].concat.apply([], globs); // eslint-disable-line prefer-spread -}; + for (let i = 0; i < this.linesToClear; i++) { + if (i > 0) { + this.stream.moveCursor(0, -1); + } + this.stream.clearLine(); + this.stream.cursorTo(this.indent); + } -/***/ }), -/* 362 */ -/***/ (function(module, exports, __webpack_require__) { + this.linesToClear = 0; -"use strict"; + return this; + } -const {promisify} = __webpack_require__(111); -const fs = __webpack_require__(133); + render() { + this.clear(); + this.stream.write(this.frame()); + this.linesToClear = this.lineCount; -async function isType(fsStatType, statsMethodName, filePath) { - if (typeof filePath !== 'string') { - throw new TypeError(`Expected a string, got ${typeof filePath}`); + return this; } - try { - const stats = await promisify(fs[fsStatType])(filePath); - return stats[statsMethodName](); - } catch (error) { - if (error.code === 'ENOENT') { - return false; + start(text) { + if (text) { + this.text = text; } - throw error; - } -} + if (!this.isEnabled) { + if (this.text) { + this.stream.write(`- ${this.text}\n`); + } -function isTypeSync(fsStatType, statsMethodName, filePath) { - if (typeof filePath !== 'string') { - throw new TypeError(`Expected a string, got ${typeof filePath}`); - } + return this; + } - try { - return fs[fsStatType](filePath)[statsMethodName](); - } catch (error) { - if (error.code === 'ENOENT') { - return false; + if (this.isSpinning) { + return this; } - throw error; - } -} + if (this.hideCursor) { + cliCursor.hide(this.stream); + } -exports.isFile = isType.bind(null, 'stat', 'isFile'); -exports.isDirectory = isType.bind(null, 'stat', 'isDirectory'); -exports.isSymlink = isType.bind(null, 'lstat', 'isSymbolicLink'); -exports.isFileSync = isTypeSync.bind(null, 'statSync', 'isFile'); -exports.isDirectorySync = isTypeSync.bind(null, 'statSync', 'isDirectory'); -exports.isSymlinkSync = isTypeSync.bind(null, 'lstatSync', 'isSymbolicLink'); + if (this.discardStdin && process.stdin.isTTY) { + this.isDiscardingStdin = true; + stdinDiscarder.start(); + } + this.render(); + this.id = setInterval(this.render.bind(this), this.interval); -/***/ }), -/* 363 */ -/***/ (function(module, exports, __webpack_require__) { + return this; + } -"use strict"; + stop() { + if (!this.isEnabled) { + return this; + } -const {promisify} = __webpack_require__(111); -const fs = __webpack_require__(133); -const path = __webpack_require__(4); -const fastGlob = __webpack_require__(292); -const gitIgnore = __webpack_require__(364); -const slash = __webpack_require__(365); + clearInterval(this.id); + this.id = undefined; + this.frameIndex = 0; + this.clear(); + if (this.hideCursor) { + cliCursor.show(this.stream); + } -const DEFAULT_IGNORE = [ - '**/node_modules/**', - '**/flow-typed/**', - '**/coverage/**', - '**/.git' -]; + if (this.discardStdin && process.stdin.isTTY && this.isDiscardingStdin) { + stdinDiscarder.stop(); + this.isDiscardingStdin = false; + } -const readFileP = promisify(fs.readFile); + return this; + } -const mapGitIgnorePatternTo = base => ignore => { - if (ignore.startsWith('!')) { - return '!' + path.posix.join(base, ignore.slice(1)); + succeed(text) { + return this.stopAndPersist({symbol: logSymbols.success, text}); } - return path.posix.join(base, ignore); -}; + fail(text) { + return this.stopAndPersist({symbol: logSymbols.error, text}); + } -const parseGitIgnore = (content, options) => { - const base = slash(path.relative(options.cwd, path.dirname(options.fileName))); + warn(text) { + return this.stopAndPersist({symbol: logSymbols.warning, text}); + } - return content - .split(/\r?\n/) - .filter(Boolean) - .filter(line => !line.startsWith('#')) - .map(mapGitIgnorePatternTo(base)); -}; + info(text) { + return this.stopAndPersist({symbol: logSymbols.info, text}); + } -const reduceIgnore = files => { - return files.reduce((ignores, file) => { - ignores.add(parseGitIgnore(file.content, { - cwd: file.cwd, - fileName: file.filePath - })); - return ignores; - }, gitIgnore()); -}; + stopAndPersist(options = {}) { + const prefixText = options.prefixText || this.prefixText; + const fullPrefixText = (typeof prefixText === 'string' && prefixText !== '') ? prefixText + ' ' : ''; + const text = options.text || this.text; + const fullText = (typeof text === 'string') ? ' ' + text : ''; -const ensureAbsolutePathForCwd = (cwd, p) => { - if (path.isAbsolute(p)) { - if (p.startsWith(cwd)) { - return p; - } + this.stop(); + this.stream.write(`${fullPrefixText}${options.symbol || ' '}${fullText}\n`); - throw new Error(`Path ${p} is not in cwd ${cwd}`); + return this; } +} - return path.join(cwd, p); +const oraFactory = function (options) { + return new Ora(options); }; -const getIsIgnoredPredecate = (ignores, cwd) => { - return p => ignores.ignores(slash(path.relative(cwd, ensureAbsolutePathForCwd(cwd, p)))); -}; +module.exports = oraFactory; -const getFile = async (file, cwd) => { - const filePath = path.join(cwd, file); - const content = await readFileP(filePath, 'utf8'); +module.exports.promise = (action, options) => { + // eslint-disable-next-line promise/prefer-await-to-then + if (typeof action.then !== 'function') { + throw new TypeError('Parameter `action` must be a Promise'); + } - return { - cwd, - filePath, - content - }; -}; + const spinner = new Ora(options); + spinner.start(); -const getFileSync = (file, cwd) => { - const filePath = path.join(cwd, file); - const content = fs.readFileSync(filePath, 'utf8'); + (async () => { + try { + await action; + spinner.succeed(); + } catch (_) { + spinner.fail(); + } + })(); - return { - cwd, - filePath, - content - }; + return spinner; }; -const normalizeOptions = ({ - ignore = [], - cwd = slash(process.cwd()) -} = {}) => { - return {ignore, cwd}; -}; -module.exports = async options => { - options = normalizeOptions(options); +/***/ }), +/* 368 */ +/***/ (function(module, exports) { - const paths = await fastGlob('**/.gitignore', { - ignore: DEFAULT_IGNORE.concat(options.ignore), - cwd: options.cwd - }); +module.exports = require("readline"); - const files = await Promise.all(paths.map(file => getFile(file, options.cwd))); - const ignores = reduceIgnore(files); +/***/ }), +/* 369 */ +/***/ (function(module, exports, __webpack_require__) { - return getIsIgnoredPredecate(ignores, options.cwd); -}; +"use strict"; -module.exports.sync = options => { - options = normalizeOptions(options); +const ansiStyles = __webpack_require__(370); +const {stdout: stdoutColor, stderr: stderrColor} = __webpack_require__(120); +const { + stringReplaceAll, + stringEncaseCRLFWithFirstIndex +} = __webpack_require__(374); - const paths = fastGlob.sync('**/.gitignore', { - ignore: DEFAULT_IGNORE.concat(options.ignore), - cwd: options.cwd - }); +// `supportsColor.level` → `ansiStyles.color[name]` mapping +const levelMapping = [ + 'ansi', + 'ansi', + 'ansi256', + 'ansi16m' +]; - const files = paths.map(file => getFileSync(file, options.cwd)); - const ignores = reduceIgnore(files); +const styles = Object.create(null); - return getIsIgnoredPredecate(ignores, options.cwd); +const applyOptions = (object, options = {}) => { + if (options.level > 3 || options.level < 0) { + throw new Error('The `level` option should be an integer from 0 to 3'); + } + + // Detect level if not set manually + const colorLevel = stdoutColor ? stdoutColor.level : 0; + object.level = options.level === undefined ? colorLevel : options.level; }; +class ChalkClass { + constructor(options) { + return chalkFactory(options); + } +} -/***/ }), -/* 364 */ -/***/ (function(module, exports) { +const chalkFactory = options => { + const chalk = {}; + applyOptions(chalk, options); -// A simple implementation of make-array -function makeArray (subject) { - return Array.isArray(subject) - ? subject - : [subject] -} + chalk.template = (...arguments_) => chalkTag(chalk.template, ...arguments_); -const EMPTY = '' -const SPACE = ' ' -const ESCAPE = '\\' -const REGEX_TEST_BLANK_LINE = /^\s+$/ -const REGEX_REPLACE_LEADING_EXCAPED_EXCLAMATION = /^\\!/ -const REGEX_REPLACE_LEADING_EXCAPED_HASH = /^\\#/ -const REGEX_SPLITALL_CRLF = /\r?\n/g -// /foo, -// ./foo, -// ../foo, -// . -// .. -const REGEX_TEST_INVALID_PATH = /^\.*\/|^\.+$/ + Object.setPrototypeOf(chalk, Chalk.prototype); + Object.setPrototypeOf(chalk.template, chalk); -const SLASH = '/' -const KEY_IGNORE = typeof Symbol !== 'undefined' - ? Symbol.for('node-ignore') - /* istanbul ignore next */ - : 'node-ignore' + chalk.template.constructor = () => { + throw new Error('`chalk.constructor()` is deprecated. Use `new chalk.Instance()` instead.'); + }; -const define = (object, key, value) => - Object.defineProperty(object, key, {value}) + chalk.template.Instance = ChalkClass; -const REGEX_REGEXP_RANGE = /([0-z])-([0-z])/g + return chalk.template; +}; -// Sanitize the range of a regular expression -// The cases are complicated, see test cases for details -const sanitizeRange = range => range.replace( - REGEX_REGEXP_RANGE, - (match, from, to) => from.charCodeAt(0) <= to.charCodeAt(0) - ? match - // Invalid range (out of order) which is ok for gitignore rules but - // fatal for JavaScript regular expression, so eliminate it. - : EMPTY -) +function Chalk(options) { + return chalkFactory(options); +} -// See fixtures #59 -const cleanRangeBackSlash = slashes => { - const {length} = slashes - return slashes.slice(0, length - length % 2) +for (const [styleName, style] of Object.entries(ansiStyles)) { + styles[styleName] = { + get() { + const builder = createBuilder(this, createStyler(style.open, style.close, this._styler), this._isEmpty); + Object.defineProperty(this, styleName, {value: builder}); + return builder; + } + }; } -// > If the pattern ends with a slash, -// > it is removed for the purpose of the following description, -// > but it would only find a match with a directory. -// > In other words, foo/ will match a directory foo and paths underneath it, -// > but will not match a regular file or a symbolic link foo -// > (this is consistent with the way how pathspec works in general in Git). -// '`foo/`' will not match regular file '`foo`' or symbolic link '`foo`' -// -> ignore-rules will not deal with it, because it costs extra `fs.stat` call -// you could use option `mark: true` with `glob` +styles.visible = { + get() { + const builder = createBuilder(this, this._styler, true); + Object.defineProperty(this, 'visible', {value: builder}); + return builder; + } +}; -// '`foo/`' should not continue with the '`..`' -const REPLACERS = [ +const usedModels = ['rgb', 'hex', 'keyword', 'hsl', 'hsv', 'hwb', 'ansi', 'ansi256']; - // > Trailing spaces are ignored unless they are quoted with backslash ("\") - [ - // (a\ ) -> (a ) - // (a ) -> (a) - // (a \ ) -> (a ) - /\\?\s+$/, - match => match.indexOf('\\') === 0 - ? SPACE - : EMPTY - ], +for (const model of usedModels) { + styles[model] = { + get() { + const {level} = this; + return function (...arguments_) { + const styler = createStyler(ansiStyles.color[levelMapping[level]][model](...arguments_), ansiStyles.color.close, this._styler); + return createBuilder(this, styler, this._isEmpty); + }; + } + }; +} - // replace (\ ) with ' ' - [ - /\\\s/g, - () => SPACE - ], +for (const model of usedModels) { + const bgModel = 'bg' + model[0].toUpperCase() + model.slice(1); + styles[bgModel] = { + get() { + const {level} = this; + return function (...arguments_) { + const styler = createStyler(ansiStyles.bgColor[levelMapping[level]][model](...arguments_), ansiStyles.bgColor.close, this._styler); + return createBuilder(this, styler, this._isEmpty); + }; + } + }; +} - // Escape metacharacters - // which is written down by users but means special for regular expressions. +const proto = Object.defineProperties(() => {}, { + ...styles, + level: { + enumerable: true, + get() { + return this._generator.level; + }, + set(level) { + this._generator.level = level; + } + } +}); - // > There are 12 characters with special meanings: - // > - the backslash \, - // > - the caret ^, - // > - the dollar sign $, - // > - the period or dot ., - // > - the vertical bar or pipe symbol |, - // > - the question mark ?, - // > - the asterisk or star *, - // > - the plus sign +, - // > - the opening parenthesis (, - // > - the closing parenthesis ), - // > - and the opening square bracket [, - // > - the opening curly brace {, - // > These special characters are often called "metacharacters". - [ - /[\\$.|*+(){^]/g, - match => `\\${match}` - ], +const createStyler = (open, close, parent) => { + let openAll; + let closeAll; + if (parent === undefined) { + openAll = open; + closeAll = close; + } else { + openAll = parent.openAll + open; + closeAll = close + parent.closeAll; + } - [ - // > a question mark (?) matches a single character - /(?!\\)\?/g, - () => '[^/]' - ], + return { + open, + close, + openAll, + closeAll, + parent + }; +}; - // leading slash - [ +const createBuilder = (self, _styler, _isEmpty) => { + const builder = (...arguments_) => { + // Single argument is hot path, implicit coercion is faster than anything + // eslint-disable-next-line no-implicit-coercion + return applyStyle(builder, (arguments_.length === 1) ? ('' + arguments_[0]) : arguments_.join(' ')); + }; - // > A leading slash matches the beginning of the pathname. - // > For example, "/*.c" matches "cat-file.c" but not "mozilla-sha1/sha1.c". - // A leading slash matches the beginning of the pathname - /^\//, - () => '^' - ], + // `__proto__` is used because we must return a function, but there is + // no way to create a function with a different prototype + builder.__proto__ = proto; // eslint-disable-line no-proto - // replace special metacharacter slash after the leading slash - [ - /\//g, - () => '\\/' - ], + builder._generator = self; + builder._styler = _styler; + builder._isEmpty = _isEmpty; - [ - // > A leading "**" followed by a slash means match in all directories. - // > For example, "**/foo" matches file or directory "foo" anywhere, - // > the same as pattern "foo". - // > "**/foo/bar" matches file or directory "bar" anywhere that is directly - // > under directory "foo". - // Notice that the '*'s have been replaced as '\\*' - /^\^*\\\*\\\*\\\//, + return builder; +}; - // '**/foo' <-> 'foo' - () => '^(?:.*\\/)?' - ], +const applyStyle = (self, string) => { + if (self.level <= 0 || !string) { + return self._isEmpty ? '' : string; + } - // starting - [ - // there will be no leading '/' - // (which has been replaced by section "leading slash") - // If starts with '**', adding a '^' to the regular expression also works - /^(?=[^^])/, - function startingReplacer () { - // If has a slash `/` at the beginning or middle - return !/\/(?!$)/.test(this) - // > Prior to 2.22.1 - // > If the pattern does not contain a slash /, - // > Git treats it as a shell glob pattern - // Actually, if there is only a trailing slash, - // git also treats it as a shell glob pattern + let styler = self._styler; - // After 2.22.1 (compatible but clearer) - // > If there is a separator at the beginning or middle (or both) - // > of the pattern, then the pattern is relative to the directory - // > level of the particular .gitignore file itself. - // > Otherwise the pattern may also match at any level below - // > the .gitignore level. - ? '(?:^|\\/)' + if (styler === undefined) { + return string; + } - // > Otherwise, Git treats the pattern as a shell glob suitable for - // > consumption by fnmatch(3) - : '^' - } - ], + const {openAll, closeAll} = styler; + if (string.indexOf('\u001B') !== -1) { + while (styler !== undefined) { + // Replace any instances already present with a re-opening code + // otherwise only the part of the string until said closing code + // will be colored, and the rest will simply be 'plain'. + string = stringReplaceAll(string, styler.close, styler.open); - // two globstars - [ - // Use lookahead assertions so that we could match more than one `'/**'` - /\\\/\\\*\\\*(?=\\\/|$)/g, + styler = styler.parent; + } + } - // Zero, one or several directories - // should not use '*', or it will be replaced by the next replacer + // We can move both next actions out of loop, because remaining actions in loop won't have + // any/visible effect on parts we add here. Close the styling before a linebreak and reopen + // after next line to fix a bleed issue on macOS: https://github.com/chalk/chalk/pull/92 + const lfIndex = string.indexOf('\n'); + if (lfIndex !== -1) { + string = stringEncaseCRLFWithFirstIndex(string, closeAll, openAll, lfIndex); + } - // Check if it is not the last `'/**'` - (_, index, str) => index + 6 < str.length + return openAll + string + closeAll; +}; - // case: /**/ - // > A slash followed by two consecutive asterisks then a slash matches - // > zero or more directories. - // > For example, "a/**/b" matches "a/b", "a/x/b", "a/x/y/b" and so on. - // '/**/' - ? '(?:\\/[^\\/]+)*' +let template; +const chalkTag = (chalk, ...strings) => { + const [firstString] = strings; - // case: /** - // > A trailing `"/**"` matches everything inside. + if (!Array.isArray(firstString)) { + // If chalk() was called by itself or with a string, + // return the string itself as a string. + return strings.join(' '); + } - // #21: everything inside but it should not include the current folder - : '\\/.+' - ], + const arguments_ = strings.slice(1); + const parts = [firstString.raw[0]]; - // intermediate wildcards - [ - // Never replace escaped '*' - // ignore rule '\*' will match the path '*' + for (let i = 1; i < firstString.length; i++) { + parts.push( + String(arguments_[i - 1]).replace(/[{}\\]/g, '\\$&'), + String(firstString.raw[i]) + ); + } - // 'abc.*/' -> go - // 'abc.*' -> skip this rule - /(^|[^\\]+)\\\*(?=.+)/g, + if (template === undefined) { + template = __webpack_require__(375); + } - // '*.js' matches '.js' - // '*.js' doesn't match 'abc' - (_, p1) => `${p1}[^\\/]*` - ], + return template(chalk, parts.join('')); +}; - [ - // unescape, revert step 3 except for back slash - // For example, if a user escape a '\\*', - // after step 3, the result will be '\\\\\\*' - /\\\\\\(?=[$.|*+(){^])/g, - () => ESCAPE - ], +Object.defineProperties(Chalk.prototype, styles); - [ - // '\\\\' -> '\\' - /\\\\/g, - () => ESCAPE - ], +const chalk = Chalk(); // eslint-disable-line new-cap +chalk.supportsColor = stdoutColor; +chalk.stderr = Chalk({level: stderrColor ? stderrColor.level : 0}); // eslint-disable-line new-cap +chalk.stderr.supportsColor = stderrColor; - [ - // > The range notation, e.g. [a-zA-Z], - // > can be used to match one of the characters in a range. +// For TypeScript +chalk.Level = { + None: 0, + Basic: 1, + Ansi256: 2, + TrueColor: 3, + 0: 'None', + 1: 'Basic', + 2: 'Ansi256', + 3: 'TrueColor' +}; - // `\` is escaped by step 3 - /(\\)?\[([^\]/]*?)(\\*)($|\])/g, - (match, leadEscape, range, endEscape, close) => leadEscape === ESCAPE - // '\\[bar]' -> '\\\\[bar\\]' - ? `\\[${range}${cleanRangeBackSlash(endEscape)}${close}` - : close === ']' - ? endEscape.length % 2 === 0 - // A normal case, and it is a range notation - // '[bar]' - // '[bar\\\\]' - ? `[${sanitizeRange(range)}${endEscape}]` - // Invalid range notaton - // '[bar\\]' -> '[bar\\\\]' - : '[]' - : '[]' - ], +module.exports = chalk; - // ending - [ - // 'js' will not match 'js.' - // 'ab' will not match 'abc' - /(?:[^*])$/, - // WTF! - // https://git-scm.com/docs/gitignore - // changes in [2.22.1](https://git-scm.com/docs/gitignore/2.22.1) - // which re-fixes #24, #38 +/***/ }), +/* 370 */ +/***/ (function(module, exports, __webpack_require__) { - // > If there is a separator at the end of the pattern then the pattern - // > will only match directories, otherwise the pattern can match both - // > files and directories. +"use strict"; +/* WEBPACK VAR INJECTION */(function(module) { - // 'js*' will not match 'a.js' - // 'js/' will not match 'a.js' - // 'js' will match 'a.js' and 'a.js/' - match => /\/$/.test(match) - // foo/ will not match 'foo' - ? `${match}$` - // foo matches 'foo' and 'foo/' - : `${match}(?=$|\\/$)` - ], +const wrapAnsi16 = (fn, offset) => (...args) => { + const code = fn(...args); + return `\u001B[${code + offset}m`; +}; - // trailing wildcard - [ - /(\^|\\\/)?\\\*$/, - (_, p1) => { - const prefix = p1 - // '\^': - // '/*' does not match EMPTY - // '/*' does not match everything +const wrapAnsi256 = (fn, offset) => (...args) => { + const code = fn(...args); + return `\u001B[${38 + offset};5;${code}m`; +}; - // '\\\/': - // 'abc/*' does not match 'abc/' - ? `${p1}[^/]+` +const wrapAnsi16m = (fn, offset) => (...args) => { + const rgb = fn(...args); + return `\u001B[${38 + offset};2;${rgb[0]};${rgb[1]};${rgb[2]}m`; +}; - // 'a*' matches 'a' - // 'a*' matches 'aa' - : '[^/]*' +const ansi2ansi = n => n; +const rgb2rgb = (r, g, b) => [r, g, b]; - return `${prefix}(?=$|\\/$)` - } - ], -] +const setLazyProperty = (object, property, get) => { + Object.defineProperty(object, property, { + get: () => { + const value = get(); -// A simple cache, because an ignore rule only has only one certain meaning -const regexCache = Object.create(null) + Object.defineProperty(object, property, { + value, + enumerable: true, + configurable: true + }); -// @param {pattern} -const makeRegex = (pattern, negative, ignorecase) => { - const r = regexCache[pattern] - if (r) { - return r - } + return value; + }, + enumerable: true, + configurable: true + }); +}; - // const replacers = negative - // ? NEGATIVE_REPLACERS - // : POSITIVE_REPLACERS +/** @type {typeof import('color-convert')} */ +let colorConvert; +const makeDynamicStyles = (wrap, targetSpace, identity, isBackground) => { + if (colorConvert === undefined) { + colorConvert = __webpack_require__(371); + } - const source = REPLACERS.reduce( - (prev, current) => prev.replace(current[0], current[1].bind(pattern)), - pattern - ) + const offset = isBackground ? 10 : 0; + const styles = {}; - return regexCache[pattern] = ignorecase - ? new RegExp(source, 'i') - : new RegExp(source) -} + for (const [sourceSpace, suite] of Object.entries(colorConvert)) { + const name = sourceSpace === 'ansi16' ? 'ansi' : sourceSpace; + if (sourceSpace === targetSpace) { + styles[name] = wrap(identity, offset); + } else if (typeof suite === 'object') { + styles[name] = wrap(suite[targetSpace], offset); + } + } -const isString = subject => typeof subject === 'string' - -// > A blank line matches no files, so it can serve as a separator for readability. -const checkPattern = pattern => pattern - && isString(pattern) - && !REGEX_TEST_BLANK_LINE.test(pattern) - - // > A line starting with # serves as a comment. - && pattern.indexOf('#') !== 0 + return styles; +}; -const splitPattern = pattern => pattern.split(REGEX_SPLITALL_CRLF) +function assembleStyles() { + const codes = new Map(); + const styles = { + modifier: { + reset: [0, 0], + // 21 isn't widely supported and 22 does the same thing + bold: [1, 22], + dim: [2, 22], + italic: [3, 23], + underline: [4, 24], + inverse: [7, 27], + hidden: [8, 28], + strikethrough: [9, 29] + }, + color: { + black: [30, 39], + red: [31, 39], + green: [32, 39], + yellow: [33, 39], + blue: [34, 39], + magenta: [35, 39], + cyan: [36, 39], + white: [37, 39], -class IgnoreRule { - constructor ( - origin, - pattern, - negative, - regex - ) { - this.origin = origin - this.pattern = pattern - this.negative = negative - this.regex = regex - } -} + // Bright color + blackBright: [90, 39], + redBright: [91, 39], + greenBright: [92, 39], + yellowBright: [93, 39], + blueBright: [94, 39], + magentaBright: [95, 39], + cyanBright: [96, 39], + whiteBright: [97, 39] + }, + bgColor: { + bgBlack: [40, 49], + bgRed: [41, 49], + bgGreen: [42, 49], + bgYellow: [43, 49], + bgBlue: [44, 49], + bgMagenta: [45, 49], + bgCyan: [46, 49], + bgWhite: [47, 49], -const createRule = (pattern, ignorecase) => { - const origin = pattern - let negative = false + // Bright color + bgBlackBright: [100, 49], + bgRedBright: [101, 49], + bgGreenBright: [102, 49], + bgYellowBright: [103, 49], + bgBlueBright: [104, 49], + bgMagentaBright: [105, 49], + bgCyanBright: [106, 49], + bgWhiteBright: [107, 49] + } + }; - // > An optional prefix "!" which negates the pattern; - if (pattern.indexOf('!') === 0) { - negative = true - pattern = pattern.substr(1) - } + // Alias bright black as gray (and grey) + styles.color.gray = styles.color.blackBright; + styles.bgColor.bgGray = styles.bgColor.bgBlackBright; + styles.color.grey = styles.color.blackBright; + styles.bgColor.bgGrey = styles.bgColor.bgBlackBright; - pattern = pattern - // > Put a backslash ("\") in front of the first "!" for patterns that - // > begin with a literal "!", for example, `"\!important!.txt"`. - .replace(REGEX_REPLACE_LEADING_EXCAPED_EXCLAMATION, '!') - // > Put a backslash ("\") in front of the first hash for patterns that - // > begin with a hash. - .replace(REGEX_REPLACE_LEADING_EXCAPED_HASH, '#') + for (const [groupName, group] of Object.entries(styles)) { + for (const [styleName, style] of Object.entries(group)) { + styles[styleName] = { + open: `\u001B[${style[0]}m`, + close: `\u001B[${style[1]}m` + }; - const regex = makeRegex(pattern, negative, ignorecase) + group[styleName] = styles[styleName]; - return new IgnoreRule( - origin, - pattern, - negative, - regex - ) -} + codes.set(style[0], style[1]); + } -const throwError = (message, Ctor) => { - throw new Ctor(message) -} + Object.defineProperty(styles, groupName, { + value: group, + enumerable: false + }); + } -const checkPath = (path, originalPath, doThrow) => { - if (!isString(path)) { - return doThrow( - `path must be a string, but got \`${originalPath}\``, - TypeError - ) - } + Object.defineProperty(styles, 'codes', { + value: codes, + enumerable: false + }); - // We don't know if we should ignore EMPTY, so throw - if (!path) { - return doThrow(`path must not be empty`, TypeError) - } + styles.color.close = '\u001B[39m'; + styles.bgColor.close = '\u001B[49m'; - // Check if it is a relative path - if (checkPath.isNotRelative(path)) { - const r = '`path.relative()`d' - return doThrow( - `path should be a ${r} string, but got "${originalPath}"`, - RangeError - ) - } + setLazyProperty(styles.color, 'ansi', () => makeDynamicStyles(wrapAnsi16, 'ansi16', ansi2ansi, false)); + setLazyProperty(styles.color, 'ansi256', () => makeDynamicStyles(wrapAnsi256, 'ansi256', ansi2ansi, false)); + setLazyProperty(styles.color, 'ansi16m', () => makeDynamicStyles(wrapAnsi16m, 'rgb', rgb2rgb, false)); + setLazyProperty(styles.bgColor, 'ansi', () => makeDynamicStyles(wrapAnsi16, 'ansi16', ansi2ansi, true)); + setLazyProperty(styles.bgColor, 'ansi256', () => makeDynamicStyles(wrapAnsi256, 'ansi256', ansi2ansi, true)); + setLazyProperty(styles.bgColor, 'ansi16m', () => makeDynamicStyles(wrapAnsi16m, 'rgb', rgb2rgb, true)); - return true + return styles; } -const isNotRelative = path => REGEX_TEST_INVALID_PATH.test(path) - -checkPath.isNotRelative = isNotRelative -checkPath.convert = p => p - -class Ignore { - constructor ({ - ignorecase = true - } = {}) { - this._rules = [] - this._ignorecase = ignorecase - define(this, KEY_IGNORE, true) - this._initCache() - } +// Make the export immutable +Object.defineProperty(module, 'exports', { + enumerable: true, + get: assembleStyles +}); - _initCache () { - this._ignoreCache = Object.create(null) - this._testCache = Object.create(null) - } +/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(115)(module))) - _addPattern (pattern) { - // #32 - if (pattern && pattern[KEY_IGNORE]) { - this._rules = this._rules.concat(pattern._rules) - this._added = true - return - } +/***/ }), +/* 371 */ +/***/ (function(module, exports, __webpack_require__) { - if (checkPattern(pattern)) { - const rule = createRule(pattern, this._ignorecase) - this._added = true - this._rules.push(rule) - } - } +const conversions = __webpack_require__(372); +const route = __webpack_require__(373); - // @param {Array | string | Ignore} pattern - add (pattern) { - this._added = false +const convert = {}; - makeArray( - isString(pattern) - ? splitPattern(pattern) - : pattern - ).forEach(this._addPattern, this) +const models = Object.keys(conversions); - // Some rules have just added to the ignore, - // making the behavior changed. - if (this._added) { - this._initCache() - } +function wrapRaw(fn) { + const wrappedFn = function (...args) { + const arg0 = args[0]; + if (arg0 === undefined || arg0 === null) { + return arg0; + } - return this - } + if (arg0.length > 1) { + args = arg0; + } - // legacy - addPattern (pattern) { - return this.add(pattern) - } + return fn(args); + }; - // | ignored : unignored - // negative | 0:0 | 0:1 | 1:0 | 1:1 - // -------- | ------- | ------- | ------- | -------- - // 0 | TEST | TEST | SKIP | X - // 1 | TESTIF | SKIP | TEST | X + // Preserve .conversion property if there is one + if ('conversion' in fn) { + wrappedFn.conversion = fn.conversion; + } - // - SKIP: always skip - // - TEST: always test - // - TESTIF: only test if checkUnignored - // - X: that never happen + return wrappedFn; +} - // @param {boolean} whether should check if the path is unignored, - // setting `checkUnignored` to `false` could reduce additional - // path matching. +function wrapRounded(fn) { + const wrappedFn = function (...args) { + const arg0 = args[0]; - // @returns {TestResult} true if a file is ignored - _testOne (path, checkUnignored) { - let ignored = false - let unignored = false + if (arg0 === undefined || arg0 === null) { + return arg0; + } - this._rules.forEach(rule => { - const {negative} = rule - if ( - unignored === negative && ignored !== unignored - || negative && !ignored && !unignored && !checkUnignored - ) { - return - } + if (arg0.length > 1) { + args = arg0; + } - const matched = rule.regex.test(path) + const result = fn(args); - if (matched) { - ignored = !negative - unignored = negative - } - }) + // We're assuming the result is an array here. + // see notice in conversions.js; don't use box types + // in conversion functions. + if (typeof result === 'object') { + for (let len = result.length, i = 0; i < len; i++) { + result[i] = Math.round(result[i]); + } + } - return { - ignored, - unignored - } - } + return result; + }; - // @returns {TestResult} - _test (originalPath, cache, checkUnignored, slices) { - const path = originalPath - // Supports nullable path - && checkPath.convert(originalPath) + // Preserve .conversion property if there is one + if ('conversion' in fn) { + wrappedFn.conversion = fn.conversion; + } - checkPath(path, originalPath, throwError) + return wrappedFn; +} - return this._t(path, cache, checkUnignored, slices) - } +models.forEach(fromModel => { + convert[fromModel] = {}; - _t (path, cache, checkUnignored, slices) { - if (path in cache) { - return cache[path] - } + Object.defineProperty(convert[fromModel], 'channels', {value: conversions[fromModel].channels}); + Object.defineProperty(convert[fromModel], 'labels', {value: conversions[fromModel].labels}); - if (!slices) { - // path/to/a.js - // ['path', 'to', 'a.js'] - slices = path.split(SLASH) - } + const routes = route(fromModel); + const routeModels = Object.keys(routes); - slices.pop() + routeModels.forEach(toModel => { + const fn = routes[toModel]; - // If the path has no parent directory, just test it - if (!slices.length) { - return cache[path] = this._testOne(path, checkUnignored) - } + convert[fromModel][toModel] = wrapRounded(fn); + convert[fromModel][toModel].raw = wrapRaw(fn); + }); +}); - const parent = this._t( - slices.join(SLASH) + SLASH, - cache, - checkUnignored, - slices - ) +module.exports = convert; - // If the path contains a parent directory, check the parent first - return cache[path] = parent.ignored - // > It is not possible to re-include a file if a parent directory of - // > that file is excluded. - ? parent - : this._testOne(path, checkUnignored) - } - ignores (path) { - return this._test(path, this._ignoreCache, false).ignored - } +/***/ }), +/* 372 */ +/***/ (function(module, exports, __webpack_require__) { - createFilter () { - return path => !this.ignores(path) - } +/* MIT license */ +/* eslint-disable no-mixed-operators */ +const cssKeywords = __webpack_require__(118); - filter (paths) { - return makeArray(paths).filter(this.createFilter()) - } +// NOTE: conversions should only return primitive values (i.e. arrays, or +// values that give correct `typeof` results). +// do not use box values types (i.e. Number(), String(), etc.) - // @returns {TestResult} - test (path) { - return this._test(path, this._testCache, true) - } +const reverseKeywords = {}; +for (const key of Object.keys(cssKeywords)) { + reverseKeywords[cssKeywords[key]] = key; } -const factory = options => new Ignore(options) - -const returnFalse = () => false - -const isPathValid = path => - checkPath(path && checkPath.convert(path), path, returnFalse) - -factory.isPathValid = isPathValid +const convert = { + rgb: {channels: 3, labels: 'rgb'}, + hsl: {channels: 3, labels: 'hsl'}, + hsv: {channels: 3, labels: 'hsv'}, + hwb: {channels: 3, labels: 'hwb'}, + cmyk: {channels: 4, labels: 'cmyk'}, + xyz: {channels: 3, labels: 'xyz'}, + lab: {channels: 3, labels: 'lab'}, + lch: {channels: 3, labels: 'lch'}, + hex: {channels: 1, labels: ['hex']}, + keyword: {channels: 1, labels: ['keyword']}, + ansi16: {channels: 1, labels: ['ansi16']}, + ansi256: {channels: 1, labels: ['ansi256']}, + hcg: {channels: 3, labels: ['h', 'c', 'g']}, + apple: {channels: 3, labels: ['r16', 'g16', 'b16']}, + gray: {channels: 1, labels: ['gray']} +}; -// Fixes typescript -factory.default = factory +module.exports = convert; -module.exports = factory +// Hide .channels and .labels properties +for (const model of Object.keys(convert)) { + if (!('channels' in convert[model])) { + throw new Error('missing channels property: ' + model); + } -// Windows -// -------------------------------------------------------------- -/* istanbul ignore if */ -if ( - // Detect `process` so that it can run in browsers. - typeof process !== 'undefined' - && ( - process.env && process.env.IGNORE_TEST_WIN32 - || process.platform === 'win32' - ) -) { - /* eslint no-control-regex: "off" */ - const makePosix = str => /^\\\\\?\\/.test(str) - || /["<>|\u0000-\u001F]+/u.test(str) - ? str - : str.replace(/\\/g, '/') + if (!('labels' in convert[model])) { + throw new Error('missing channel labels property: ' + model); + } - checkPath.convert = makePosix + if (convert[model].labels.length !== convert[model].channels) { + throw new Error('channel and label counts mismatch: ' + model); + } - // 'C:\\foo' <- 'C:\\foo' has been converted to 'C:/' - // 'd:\\foo' - const REGIX_IS_WINDOWS_PATH_ABSOLUTE = /^[a-z]:\//i - checkPath.isNotRelative = path => - REGIX_IS_WINDOWS_PATH_ABSOLUTE.test(path) - || isNotRelative(path) + const {channels, labels} = convert[model]; + delete convert[model].channels; + delete convert[model].labels; + Object.defineProperty(convert[model], 'channels', {value: channels}); + Object.defineProperty(convert[model], 'labels', {value: labels}); } +convert.rgb.hsl = function (rgb) { + const r = rgb[0] / 255; + const g = rgb[1] / 255; + const b = rgb[2] / 255; + const min = Math.min(r, g, b); + const max = Math.max(r, g, b); + const delta = max - min; + let h; + let s; -/***/ }), -/* 365 */ -/***/ (function(module, exports, __webpack_require__) { + if (max === min) { + h = 0; + } else if (r === max) { + h = (g - b) / delta; + } else if (g === max) { + h = 2 + (b - r) / delta; + } else if (b === max) { + h = 4 + (r - g) / delta; + } -"use strict"; + h = Math.min(h * 60, 360); -module.exports = path => { - const isExtendedLengthPath = /^\\\\\?\\/.test(path); - const hasNonAscii = /[^\u0000-\u0080]+/.test(path); // eslint-disable-line no-control-regex + if (h < 0) { + h += 360; + } - if (isExtendedLengthPath || hasNonAscii) { - return path; + const l = (min + max) / 2; + + if (max === min) { + s = 0; + } else if (l <= 0.5) { + s = delta / (max + min); + } else { + s = delta / (2 - max - min); } - return path.replace(/\\/g, '/'); + return [h, s * 100, l * 100]; }; +convert.rgb.hsv = function (rgb) { + let rdif; + let gdif; + let bdif; + let h; + let s; -/***/ }), -/* 366 */ -/***/ (function(module, exports, __webpack_require__) { + const r = rgb[0] / 255; + const g = rgb[1] / 255; + const b = rgb[2] / 255; + const v = Math.max(r, g, b); + const diff = v - Math.min(r, g, b); + const diffc = function (c) { + return (v - c) / 6 / diff + 1 / 2; + }; -"use strict"; + if (diff === 0) { + h = 0; + s = 0; + } else { + s = diff / v; + rdif = diffc(r); + gdif = diffc(g); + bdif = diffc(b); -const {Transform} = __webpack_require__(137); + if (r === v) { + h = bdif - gdif; + } else if (g === v) { + h = (1 / 3) + rdif - bdif; + } else if (b === v) { + h = (2 / 3) + gdif - rdif; + } -class ObjectTransform extends Transform { - constructor() { - super({ - objectMode: true - }); + if (h < 0) { + h += 1; + } else if (h > 1) { + h -= 1; + } } -} -class FilterStream extends ObjectTransform { - constructor(filter) { - super(); - this._filter = filter; - } + return [ + h * 360, + s * 100, + v * 100 + ]; +}; - _transform(data, encoding, callback) { - if (this._filter(data)) { - this.push(data); - } +convert.rgb.hwb = function (rgb) { + const r = rgb[0]; + const g = rgb[1]; + let b = rgb[2]; + const h = convert.rgb.hsl(rgb)[0]; + const w = 1 / 255 * Math.min(r, Math.min(g, b)); - callback(); - } + b = 1 - 1 / 255 * Math.max(r, Math.max(g, b)); + + return [h, w * 100, b * 100]; +}; + +convert.rgb.cmyk = function (rgb) { + const r = rgb[0] / 255; + const g = rgb[1] / 255; + const b = rgb[2] / 255; + + const k = Math.min(1 - r, 1 - g, 1 - b); + const c = (1 - r - k) / (1 - k) || 0; + const m = (1 - g - k) / (1 - k) || 0; + const y = (1 - b - k) / (1 - k) || 0; + + return [c * 100, m * 100, y * 100, k * 100]; +}; + +function comparativeDistance(x, y) { + /* + See https://en.m.wikipedia.org/wiki/Euclidean_distance#Squared_Euclidean_distance + */ + return ( + ((x[0] - y[0]) ** 2) + + ((x[1] - y[1]) ** 2) + + ((x[2] - y[2]) ** 2) + ); } -class UniqueStream extends ObjectTransform { - constructor() { - super(); - this._pushed = new Set(); +convert.rgb.keyword = function (rgb) { + const reversed = reverseKeywords[rgb]; + if (reversed) { + return reversed; } - _transform(data, encoding, callback) { - if (!this._pushed.has(data)) { - this.push(data); - this._pushed.add(data); - } + let currentClosestDistance = Infinity; + let currentClosestKeyword; - callback(); + for (const keyword of Object.keys(cssKeywords)) { + const value = cssKeywords[keyword]; + + // Compute comparative distance + const distance = comparativeDistance(rgb, value); + + // Check if its less, if so set as closest + if (distance < currentClosestDistance) { + currentClosestDistance = distance; + currentClosestKeyword = keyword; + } } -} -module.exports = { - FilterStream, - UniqueStream + return currentClosestKeyword; }; +convert.keyword.rgb = function (keyword) { + return cssKeywords[keyword]; +}; -/***/ }), -/* 367 */ -/***/ (function(module, exports, __webpack_require__) { - -/*! - * is-glob - * - * Copyright (c) 2014-2017, Jon Schlinkert. - * Released under the MIT License. - */ +convert.rgb.xyz = function (rgb) { + let r = rgb[0] / 255; + let g = rgb[1] / 255; + let b = rgb[2] / 255; -var isExtglob = __webpack_require__(302); -var chars = { '{': '}', '(': ')', '[': ']'}; -var strictRegex = /\\(.)|(^!|\*|[\].+)]\?|\[[^\\\]]+\]|\{[^\\}]+\}|\(\?[:!=][^\\)]+\)|\([^|]+\|[^\\)]+\))/; -var relaxedRegex = /\\(.)|(^!|[*?{}()[\]]|\(\?)/; + // Assume sRGB + r = r > 0.04045 ? (((r + 0.055) / 1.055) ** 2.4) : (r / 12.92); + g = g > 0.04045 ? (((g + 0.055) / 1.055) ** 2.4) : (g / 12.92); + b = b > 0.04045 ? (((b + 0.055) / 1.055) ** 2.4) : (b / 12.92); -module.exports = function isGlob(str, options) { - if (typeof str !== 'string' || str === '') { - return false; - } + const x = (r * 0.4124) + (g * 0.3576) + (b * 0.1805); + const y = (r * 0.2126) + (g * 0.7152) + (b * 0.0722); + const z = (r * 0.0193) + (g * 0.1192) + (b * 0.9505); - if (isExtglob(str)) { - return true; - } + return [x * 100, y * 100, z * 100]; +}; - var regex = strictRegex; - var match; +convert.rgb.lab = function (rgb) { + const xyz = convert.rgb.xyz(rgb); + let x = xyz[0]; + let y = xyz[1]; + let z = xyz[2]; - // optionally relax regex - if (options && options.strict === false) { - regex = relaxedRegex; - } + x /= 95.047; + y /= 100; + z /= 108.883; - while ((match = regex.exec(str))) { - if (match[2]) return true; - var idx = match.index + match[0].length; + x = x > 0.008856 ? (x ** (1 / 3)) : (7.787 * x) + (16 / 116); + y = y > 0.008856 ? (y ** (1 / 3)) : (7.787 * y) + (16 / 116); + z = z > 0.008856 ? (z ** (1 / 3)) : (7.787 * z) + (16 / 116); - // if an open bracket/brace/paren is escaped, - // set the index to the next closing character - var open = match[1]; - var close = open ? chars[open] : null; - if (open && close) { - var n = str.indexOf(close, idx); - if (n !== -1) { - idx = n + 1; - } - } + const l = (116 * y) - 16; + const a = 500 * (x - y); + const b = 200 * (y - z); - str = str.slice(idx); - } - return false; + return [l, a, b]; }; +convert.hsl.rgb = function (hsl) { + const h = hsl[0] / 360; + const s = hsl[1] / 100; + const l = hsl[2] / 100; + let t2; + let t3; + let val; -/***/ }), -/* 368 */ -/***/ (function(module, exports, __webpack_require__) { + if (s === 0) { + val = l * 255; + return [val, val, val]; + } -"use strict"; + if (l < 0.5) { + t2 = l * (1 + s); + } else { + t2 = l + s - l * s; + } -const path = __webpack_require__(4); + const t1 = 2 * l - t2; -module.exports = path_ => { - let cwd = process.cwd(); + const rgb = [0, 0, 0]; + for (let i = 0; i < 3; i++) { + t3 = h + 1 / 3 * -(i - 1); + if (t3 < 0) { + t3++; + } - path_ = path.resolve(path_); + if (t3 > 1) { + t3--; + } - if (process.platform === 'win32') { - cwd = cwd.toLowerCase(); - path_ = path_.toLowerCase(); + if (6 * t3 < 1) { + val = t1 + (t2 - t1) * 6 * t3; + } else if (2 * t3 < 1) { + val = t2; + } else if (3 * t3 < 2) { + val = t1 + (t2 - t1) * (2 / 3 - t3) * 6; + } else { + val = t1; + } + + rgb[i] = val * 255; } - return path_ === cwd; + return rgb; }; +convert.hsl.hsv = function (hsl) { + const h = hsl[0]; + let s = hsl[1] / 100; + let l = hsl[2] / 100; + let smin = s; + const lmin = Math.max(l, 0.01); -/***/ }), -/* 369 */ -/***/ (function(module, exports, __webpack_require__) { + l *= 2; + s *= (l <= 1) ? l : 2 - l; + smin *= lmin <= 1 ? lmin : 2 - lmin; + const v = (l + s) / 2; + const sv = l === 0 ? (2 * smin) / (lmin + smin) : (2 * s) / (l + s); -"use strict"; + return [h, sv * 100, v * 100]; +}; -const path = __webpack_require__(4); +convert.hsv.rgb = function (hsv) { + const h = hsv[0] / 60; + const s = hsv[1] / 100; + let v = hsv[2] / 100; + const hi = Math.floor(h) % 6; -module.exports = (childPath, parentPath) => { - childPath = path.resolve(childPath); - parentPath = path.resolve(parentPath); + const f = h - Math.floor(h); + const p = 255 * v * (1 - s); + const q = 255 * v * (1 - (s * f)); + const t = 255 * v * (1 - (s * (1 - f))); + v *= 255; - if (process.platform === 'win32') { - childPath = childPath.toLowerCase(); - parentPath = parentPath.toLowerCase(); + switch (hi) { + case 0: + return [v, t, p]; + case 1: + return [q, v, p]; + case 2: + return [p, v, t]; + case 3: + return [p, q, v]; + case 4: + return [t, p, v]; + case 5: + return [v, p, q]; } +}; - if (childPath === parentPath) { - return false; - } +convert.hsv.hsl = function (hsv) { + const h = hsv[0]; + const s = hsv[1] / 100; + const v = hsv[2] / 100; + const vmin = Math.max(v, 0.01); + let sl; + let l; - childPath += path.sep; - parentPath += path.sep; + l = (2 - s) * v; + const lmin = (2 - s) * vmin; + sl = s * vmin; + sl /= (lmin <= 1) ? lmin : 2 - lmin; + sl = sl || 0; + l /= 2; - return childPath.startsWith(parentPath); + return [h, sl * 100, l * 100]; }; +// http://dev.w3.org/csswg/css-color/#hwb-to-rgb +convert.hwb.rgb = function (hwb) { + const h = hwb[0] / 360; + let wh = hwb[1] / 100; + let bl = hwb[2] / 100; + const ratio = wh + bl; + let f; -/***/ }), -/* 370 */ -/***/ (function(module, exports, __webpack_require__) { + // Wh + bl cant be > 1 + if (ratio > 1) { + wh /= ratio; + bl /= ratio; + } -const assert = __webpack_require__(139) -const path = __webpack_require__(4) -const fs = __webpack_require__(133) -let glob = undefined -try { - glob = __webpack_require__(146) -} catch (_err) { - // treat glob as optional. -} + const i = Math.floor(6 * h); + const v = 1 - bl; + f = 6 * h - i; -const defaultGlobOpts = { - nosort: true, - silent: true -} + if ((i & 0x01) !== 0) { + f = 1 - f; + } -// for EMFILE handling -let timeout = 0 + const n = wh + f * (v - wh); // Linear interpolation -const isWindows = (process.platform === "win32") + let r; + let g; + let b; + /* eslint-disable max-statements-per-line,no-multi-spaces */ + switch (i) { + default: + case 6: + case 0: r = v; g = n; b = wh; break; + case 1: r = n; g = v; b = wh; break; + case 2: r = wh; g = v; b = n; break; + case 3: r = wh; g = n; b = v; break; + case 4: r = n; g = wh; b = v; break; + case 5: r = v; g = wh; b = n; break; + } + /* eslint-enable max-statements-per-line,no-multi-spaces */ -const defaults = options => { - const methods = [ - 'unlink', - 'chmod', - 'stat', - 'lstat', - 'rmdir', - 'readdir' - ] - methods.forEach(m => { - options[m] = options[m] || fs[m] - m = m + 'Sync' - options[m] = options[m] || fs[m] - }) + return [r * 255, g * 255, b * 255]; +}; - options.maxBusyTries = options.maxBusyTries || 3 - options.emfileWait = options.emfileWait || 1000 - if (options.glob === false) { - options.disableGlob = true - } - if (options.disableGlob !== true && glob === undefined) { - throw Error('glob dependency not found, set `options.disableGlob = true` if intentional') - } - options.disableGlob = options.disableGlob || false - options.glob = options.glob || defaultGlobOpts -} +convert.cmyk.rgb = function (cmyk) { + const c = cmyk[0] / 100; + const m = cmyk[1] / 100; + const y = cmyk[2] / 100; + const k = cmyk[3] / 100; -const rimraf = (p, options, cb) => { - if (typeof options === 'function') { - cb = options - options = {} - } + const r = 1 - Math.min(1, c * (1 - k) + k); + const g = 1 - Math.min(1, m * (1 - k) + k); + const b = 1 - Math.min(1, y * (1 - k) + k); - assert(p, 'rimraf: missing path') - assert.equal(typeof p, 'string', 'rimraf: path should be a string') - assert.equal(typeof cb, 'function', 'rimraf: callback function required') - assert(options, 'rimraf: invalid options argument provided') - assert.equal(typeof options, 'object', 'rimraf: options should be object') + return [r * 255, g * 255, b * 255]; +}; - defaults(options) +convert.xyz.rgb = function (xyz) { + const x = xyz[0] / 100; + const y = xyz[1] / 100; + const z = xyz[2] / 100; + let r; + let g; + let b; - let busyTries = 0 - let errState = null - let n = 0 + r = (x * 3.2406) + (y * -1.5372) + (z * -0.4986); + g = (x * -0.9689) + (y * 1.8758) + (z * 0.0415); + b = (x * 0.0557) + (y * -0.2040) + (z * 1.0570); - const next = (er) => { - errState = errState || er - if (--n === 0) - cb(errState) - } + // Assume sRGB + r = r > 0.0031308 + ? ((1.055 * (r ** (1.0 / 2.4))) - 0.055) + : r * 12.92; - const afterGlob = (er, results) => { - if (er) - return cb(er) + g = g > 0.0031308 + ? ((1.055 * (g ** (1.0 / 2.4))) - 0.055) + : g * 12.92; - n = results.length - if (n === 0) - return cb() + b = b > 0.0031308 + ? ((1.055 * (b ** (1.0 / 2.4))) - 0.055) + : b * 12.92; - results.forEach(p => { - const CB = (er) => { - if (er) { - if ((er.code === "EBUSY" || er.code === "ENOTEMPTY" || er.code === "EPERM") && - busyTries < options.maxBusyTries) { - busyTries ++ - // try again, with the same exact callback as this one. - return setTimeout(() => rimraf_(p, options, CB), busyTries * 100) - } + r = Math.min(Math.max(0, r), 1); + g = Math.min(Math.max(0, g), 1); + b = Math.min(Math.max(0, b), 1); - // this one won't happen if graceful-fs is used. - if (er.code === "EMFILE" && timeout < options.emfileWait) { - return setTimeout(() => rimraf_(p, options, CB), timeout ++) - } + return [r * 255, g * 255, b * 255]; +}; - // already gone - if (er.code === "ENOENT") er = null - } +convert.xyz.lab = function (xyz) { + let x = xyz[0]; + let y = xyz[1]; + let z = xyz[2]; - timeout = 0 - next(er) - } - rimraf_(p, options, CB) - }) - } + x /= 95.047; + y /= 100; + z /= 108.883; - if (options.disableGlob || !glob.hasMagic(p)) - return afterGlob(null, [p]) + x = x > 0.008856 ? (x ** (1 / 3)) : (7.787 * x) + (16 / 116); + y = y > 0.008856 ? (y ** (1 / 3)) : (7.787 * y) + (16 / 116); + z = z > 0.008856 ? (z ** (1 / 3)) : (7.787 * z) + (16 / 116); - options.lstat(p, (er, stat) => { - if (!er) - return afterGlob(null, [p]) + const l = (116 * y) - 16; + const a = 500 * (x - y); + const b = 200 * (y - z); - glob(p, options.glob, afterGlob) - }) + return [l, a, b]; +}; -} +convert.lab.xyz = function (lab) { + const l = lab[0]; + const a = lab[1]; + const b = lab[2]; + let x; + let y; + let z; -// Two possible strategies. -// 1. Assume it's a file. unlink it, then do the dir stuff on EPERM or EISDIR -// 2. Assume it's a directory. readdir, then do the file stuff on ENOTDIR -// -// Both result in an extra syscall when you guess wrong. However, there -// are likely far more normal files in the world than directories. This -// is based on the assumption that a the average number of files per -// directory is >= 1. -// -// If anyone ever complains about this, then I guess the strategy could -// be made configurable somehow. But until then, YAGNI. -const rimraf_ = (p, options, cb) => { - assert(p) - assert(options) - assert(typeof cb === 'function') + y = (l + 16) / 116; + x = a / 500 + y; + z = y - b / 200; - // sunos lets the root user unlink directories, which is... weird. - // so we have to lstat here and make sure it's not a dir. - options.lstat(p, (er, st) => { - if (er && er.code === "ENOENT") - return cb(null) + const y2 = y ** 3; + const x2 = x ** 3; + const z2 = z ** 3; + y = y2 > 0.008856 ? y2 : (y - 16 / 116) / 7.787; + x = x2 > 0.008856 ? x2 : (x - 16 / 116) / 7.787; + z = z2 > 0.008856 ? z2 : (z - 16 / 116) / 7.787; - // Windows can EPERM on stat. Life is suffering. - if (er && er.code === "EPERM" && isWindows) - fixWinEPERM(p, options, er, cb) + x *= 95.047; + y *= 100; + z *= 108.883; - if (st && st.isDirectory()) - return rmdir(p, options, er, cb) + return [x, y, z]; +}; - options.unlink(p, er => { - if (er) { - if (er.code === "ENOENT") - return cb(null) - if (er.code === "EPERM") - return (isWindows) - ? fixWinEPERM(p, options, er, cb) - : rmdir(p, options, er, cb) - if (er.code === "EISDIR") - return rmdir(p, options, er, cb) - } - return cb(er) - }) - }) -} +convert.lab.lch = function (lab) { + const l = lab[0]; + const a = lab[1]; + const b = lab[2]; + let h; -const fixWinEPERM = (p, options, er, cb) => { - assert(p) - assert(options) - assert(typeof cb === 'function') + const hr = Math.atan2(b, a); + h = hr * 360 / 2 / Math.PI; - options.chmod(p, 0o666, er2 => { - if (er2) - cb(er2.code === "ENOENT" ? null : er) - else - options.stat(p, (er3, stats) => { - if (er3) - cb(er3.code === "ENOENT" ? null : er) - else if (stats.isDirectory()) - rmdir(p, options, er, cb) - else - options.unlink(p, cb) - }) - }) -} + if (h < 0) { + h += 360; + } -const fixWinEPERMSync = (p, options, er) => { - assert(p) - assert(options) + const c = Math.sqrt(a * a + b * b); - try { - options.chmodSync(p, 0o666) - } catch (er2) { - if (er2.code === "ENOENT") - return - else - throw er - } + return [l, c, h]; +}; - let stats - try { - stats = options.statSync(p) - } catch (er3) { - if (er3.code === "ENOENT") - return - else - throw er - } +convert.lch.lab = function (lch) { + const l = lch[0]; + const c = lch[1]; + const h = lch[2]; - if (stats.isDirectory()) - rmdirSync(p, options, er) - else - options.unlinkSync(p) -} + const hr = h / 360 * 2 * Math.PI; + const a = c * Math.cos(hr); + const b = c * Math.sin(hr); -const rmdir = (p, options, originalEr, cb) => { - assert(p) - assert(options) - assert(typeof cb === 'function') + return [l, a, b]; +}; - // try to rmdir first, and only readdir on ENOTEMPTY or EEXIST (SunOS) - // if we guessed wrong, and it's not a directory, then - // raise the original error. - options.rmdir(p, er => { - if (er && (er.code === "ENOTEMPTY" || er.code === "EEXIST" || er.code === "EPERM")) - rmkids(p, options, cb) - else if (er && er.code === "ENOTDIR") - cb(originalEr) - else - cb(er) - }) -} +convert.rgb.ansi16 = function (args, saturation = null) { + const [r, g, b] = args; + let value = saturation === null ? convert.rgb.hsv(args)[2] : saturation; // Hsv -> ansi16 optimization -const rmkids = (p, options, cb) => { - assert(p) - assert(options) - assert(typeof cb === 'function') + value = Math.round(value / 50); - options.readdir(p, (er, files) => { - if (er) - return cb(er) - let n = files.length - if (n === 0) - return options.rmdir(p, cb) - let errState - files.forEach(f => { - rimraf(path.join(p, f), options, er => { - if (errState) - return - if (er) - return cb(errState = er) - if (--n === 0) - options.rmdir(p, cb) - }) - }) - }) -} + if (value === 0) { + return 30; + } -// this looks simpler, and is strictly *faster*, but will -// tie up the JavaScript thread and fail on excessively -// deep directory trees. -const rimrafSync = (p, options) => { - options = options || {} - defaults(options) + let ansi = 30 + + ((Math.round(b / 255) << 2) + | (Math.round(g / 255) << 1) + | Math.round(r / 255)); - assert(p, 'rimraf: missing path') - assert.equal(typeof p, 'string', 'rimraf: path should be a string') - assert(options, 'rimraf: missing options') - assert.equal(typeof options, 'object', 'rimraf: options should be object') + if (value === 2) { + ansi += 60; + } - let results + return ansi; +}; - if (options.disableGlob || !glob.hasMagic(p)) { - results = [p] - } else { - try { - options.lstatSync(p) - results = [p] - } catch (er) { - results = glob.sync(p, options.glob) - } - } +convert.hsv.ansi16 = function (args) { + // Optimization here; we already know the value and don't need to get + // it converted for us. + return convert.rgb.ansi16(convert.hsv.rgb(args), args[2]); +}; - if (!results.length) - return +convert.rgb.ansi256 = function (args) { + const r = args[0]; + const g = args[1]; + const b = args[2]; - for (let i = 0; i < results.length; i++) { - const p = results[i] + // We use the extended greyscale palette here, with the exception of + // black and white. normal palette only has 4 greyscale shades. + if (r === g && g === b) { + if (r < 8) { + return 16; + } - let st - try { - st = options.lstatSync(p) - } catch (er) { - if (er.code === "ENOENT") - return + if (r > 248) { + return 231; + } - // Windows can EPERM on stat. Life is suffering. - if (er.code === "EPERM" && isWindows) - fixWinEPERMSync(p, options, er) - } + return Math.round(((r - 8) / 247) * 24) + 232; + } - try { - // sunos lets the root user unlink directories, which is... weird. - if (st && st.isDirectory()) - rmdirSync(p, options, null) - else - options.unlinkSync(p) - } catch (er) { - if (er.code === "ENOENT") - return - if (er.code === "EPERM") - return isWindows ? fixWinEPERMSync(p, options, er) : rmdirSync(p, options, er) - if (er.code !== "EISDIR") - throw er + const ansi = 16 + + (36 * Math.round(r / 255 * 5)) + + (6 * Math.round(g / 255 * 5)) + + Math.round(b / 255 * 5); - rmdirSync(p, options, er) - } - } -} + return ansi; +}; -const rmdirSync = (p, options, originalEr) => { - assert(p) - assert(options) +convert.ansi16.rgb = function (args) { + let color = args % 10; - try { - options.rmdirSync(p) - } catch (er) { - if (er.code === "ENOENT") - return - if (er.code === "ENOTDIR") - throw originalEr - if (er.code === "ENOTEMPTY" || er.code === "EEXIST" || er.code === "EPERM") - rmkidsSync(p, options) - } -} + // Handle greyscale + if (color === 0 || color === 7) { + if (args > 50) { + color += 3.5; + } -const rmkidsSync = (p, options) => { - assert(p) - assert(options) - options.readdirSync(p).forEach(f => rimrafSync(path.join(p, f), options)) + color = color / 10.5 * 255; - // We only end up here once we got ENOTEMPTY at least once, and - // at this point, we are guaranteed to have removed all the kids. - // So, we know that it won't be ENOENT or ENOTDIR or anything else. - // try really hard to delete stuff on windows, because it has a - // PROFOUNDLY annoying habit of not closing handles promptly when - // files are deleted, resulting in spurious ENOTEMPTY errors. - const retries = isWindows ? 100 : 1 - let i = 0 - do { - let threw = true - try { - const ret = options.rmdirSync(p, options) - threw = false - return ret - } finally { - if (++i < retries && threw) - continue - } - } while (true) -} + return [color, color, color]; + } -module.exports = rimraf -rimraf.sync = rimrafSync + const mult = (~~(args > 50) + 1) * 0.5; + const r = ((color & 1) * mult) * 255; + const g = (((color >> 1) & 1) * mult) * 255; + const b = (((color >> 2) & 1) * mult) * 255; + return [r, g, b]; +}; -/***/ }), -/* 371 */ -/***/ (function(module, exports, __webpack_require__) { +convert.ansi256.rgb = function (args) { + // Handle greyscale + if (args >= 232) { + const c = (args - 232) * 10 + 8; + return [c, c, c]; + } -"use strict"; + args -= 16; -const AggregateError = __webpack_require__(372); + let rem; + const r = Math.floor(args / 36) / 5 * 255; + const g = Math.floor((rem = args % 36) / 6) / 5 * 255; + const b = (rem % 6) / 5 * 255; -module.exports = async ( - iterable, - mapper, - { - concurrency = Infinity, - stopOnError = true - } = {} -) => { - return new Promise((resolve, reject) => { - if (typeof mapper !== 'function') { - throw new TypeError('Mapper function is required'); - } + return [r, g, b]; +}; - if (!(typeof concurrency === 'number' && concurrency >= 1)) { - throw new TypeError(`Expected \`concurrency\` to be a number from 1 and up, got \`${concurrency}\` (${typeof concurrency})`); - } +convert.rgb.hex = function (args) { + const integer = ((Math.round(args[0]) & 0xFF) << 16) + + ((Math.round(args[1]) & 0xFF) << 8) + + (Math.round(args[2]) & 0xFF); - const ret = []; - const errors = []; - const iterator = iterable[Symbol.iterator](); - let isRejected = false; - let isIterableDone = false; - let resolvingCount = 0; - let currentIndex = 0; + const string = integer.toString(16).toUpperCase(); + return '000000'.substring(string.length) + string; +}; - const next = () => { - if (isRejected) { - return; - } +convert.hex.rgb = function (args) { + const match = args.toString(16).match(/[a-f0-9]{6}|[a-f0-9]{3}/i); + if (!match) { + return [0, 0, 0]; + } - const nextItem = iterator.next(); - const i = currentIndex; - currentIndex++; + let colorString = match[0]; - if (nextItem.done) { - isIterableDone = true; + if (match[0].length === 3) { + colorString = colorString.split('').map(char => { + return char + char; + }).join(''); + } - if (resolvingCount === 0) { - if (!stopOnError && errors.length !== 0) { - reject(new AggregateError(errors)); - } else { - resolve(ret); - } - } + const integer = parseInt(colorString, 16); + const r = (integer >> 16) & 0xFF; + const g = (integer >> 8) & 0xFF; + const b = integer & 0xFF; - return; - } + return [r, g, b]; +}; - resolvingCount++; +convert.rgb.hcg = function (rgb) { + const r = rgb[0] / 255; + const g = rgb[1] / 255; + const b = rgb[2] / 255; + const max = Math.max(Math.max(r, g), b); + const min = Math.min(Math.min(r, g), b); + const chroma = (max - min); + let grayscale; + let hue; - (async () => { - try { - const element = await nextItem.value; - ret[i] = await mapper(element, i); - resolvingCount--; - next(); - } catch (error) { - if (stopOnError) { - isRejected = true; - reject(error); - } else { - errors.push(error); - resolvingCount--; - next(); - } - } - })(); - }; + if (chroma < 1) { + grayscale = min / (1 - chroma); + } else { + grayscale = 0; + } - for (let i = 0; i < concurrency; i++) { - next(); + if (chroma <= 0) { + hue = 0; + } else + if (max === r) { + hue = ((g - b) / chroma) % 6; + } else + if (max === g) { + hue = 2 + (b - r) / chroma; + } else { + hue = 4 + (r - g) / chroma; + } - if (isIterableDone) { - break; - } - } - }); + hue /= 6; + hue %= 1; + + return [hue * 360, chroma * 100, grayscale * 100]; }; +convert.hsl.hcg = function (hsl) { + const s = hsl[1] / 100; + const l = hsl[2] / 100; -/***/ }), -/* 372 */ -/***/ (function(module, exports, __webpack_require__) { + const c = l < 0.5 ? (2.0 * s * l) : (2.0 * s * (1.0 - l)); -"use strict"; + let f = 0; + if (c < 1.0) { + f = (l - 0.5 * c) / (1.0 - c); + } -const indentString = __webpack_require__(373); -const cleanStack = __webpack_require__(374); + return [hsl[0], c * 100, f * 100]; +}; -const cleanInternalStack = stack => stack.replace(/\s+at .*aggregate-error\/index.js:\d+:\d+\)?/g, ''); +convert.hsv.hcg = function (hsv) { + const s = hsv[1] / 100; + const v = hsv[2] / 100; -class AggregateError extends Error { - constructor(errors) { - if (!Array.isArray(errors)) { - throw new TypeError(`Expected input to be an Array, got ${typeof errors}`); - } + const c = s * v; + let f = 0; - errors = [...errors].map(error => { - if (error instanceof Error) { - return error; - } + if (c < 1.0) { + f = (v - c) / (1 - c); + } - if (error !== null && typeof error === 'object') { - // Handle plain error objects with message property and/or possibly other metadata - return Object.assign(new Error(error.message), error); - } + return [hsv[0], c * 100, f * 100]; +}; - return new Error(error); - }); +convert.hcg.rgb = function (hcg) { + const h = hcg[0] / 360; + const c = hcg[1] / 100; + const g = hcg[2] / 100; - let message = errors - .map(error => { - // The `stack` property is not standardized, so we can't assume it exists - return typeof error.stack === 'string' ? cleanInternalStack(cleanStack(error.stack)) : String(error); - }) - .join('\n'); - message = '\n' + indentString(message, 4); - super(message); + if (c === 0.0) { + return [g * 255, g * 255, g * 255]; + } - this.name = 'AggregateError'; + const pure = [0, 0, 0]; + const hi = (h % 1) * 6; + const v = hi % 1; + const w = 1 - v; + let mg = 0; - Object.defineProperty(this, '_errors', {value: errors}); + /* eslint-disable max-statements-per-line */ + switch (Math.floor(hi)) { + case 0: + pure[0] = 1; pure[1] = v; pure[2] = 0; break; + case 1: + pure[0] = w; pure[1] = 1; pure[2] = 0; break; + case 2: + pure[0] = 0; pure[1] = 1; pure[2] = v; break; + case 3: + pure[0] = 0; pure[1] = w; pure[2] = 1; break; + case 4: + pure[0] = v; pure[1] = 0; pure[2] = 1; break; + default: + pure[0] = 1; pure[1] = 0; pure[2] = w; } + /* eslint-enable max-statements-per-line */ - * [Symbol.iterator]() { - for (const error of this._errors) { - yield error; - } - } -} + mg = (1.0 - c) * g; -module.exports = AggregateError; + return [ + (c * pure[0] + mg) * 255, + (c * pure[1] + mg) * 255, + (c * pure[2] + mg) * 255 + ]; +}; +convert.hcg.hsv = function (hcg) { + const c = hcg[1] / 100; + const g = hcg[2] / 100; -/***/ }), -/* 373 */ -/***/ (function(module, exports, __webpack_require__) { + const v = c + g * (1.0 - c); + let f = 0; -"use strict"; + if (v > 0.0) { + f = c / v; + } + return [hcg[0], f * 100, v * 100]; +}; -module.exports = (string, count = 1, options) => { - options = { - indent: ' ', - includeEmptyLines: false, - ...options - }; +convert.hcg.hsl = function (hcg) { + const c = hcg[1] / 100; + const g = hcg[2] / 100; - if (typeof string !== 'string') { - throw new TypeError( - `Expected \`input\` to be a \`string\`, got \`${typeof string}\`` - ); - } + const l = g * (1.0 - c) + 0.5 * c; + let s = 0; - if (typeof count !== 'number') { - throw new TypeError( - `Expected \`count\` to be a \`number\`, got \`${typeof count}\`` - ); + if (l > 0.0 && l < 0.5) { + s = c / (2 * l); + } else + if (l >= 0.5 && l < 1.0) { + s = c / (2 * (1 - l)); } - if (typeof options.indent !== 'string') { - throw new TypeError( - `Expected \`options.indent\` to be a \`string\`, got \`${typeof options.indent}\`` - ); - } + return [hcg[0], s * 100, l * 100]; +}; - if (count === 0) { - return string; - } +convert.hcg.hwb = function (hcg) { + const c = hcg[1] / 100; + const g = hcg[2] / 100; + const v = c + g * (1.0 - c); + return [hcg[0], (v - c) * 100, (1 - v) * 100]; +}; - const regex = options.includeEmptyLines ? /^/gm : /^(?!\s*$)/gm; +convert.hwb.hcg = function (hwb) { + const w = hwb[1] / 100; + const b = hwb[2] / 100; + const v = 1 - b; + const c = v - w; + let g = 0; - return string.replace(regex, options.indent.repeat(count)); + if (c < 1) { + g = (v - c) / (1 - c); + } + + return [hwb[0], c * 100, g * 100]; }; +convert.apple.rgb = function (apple) { + return [(apple[0] / 65535) * 255, (apple[1] / 65535) * 255, (apple[2] / 65535) * 255]; +}; -/***/ }), -/* 374 */ -/***/ (function(module, exports, __webpack_require__) { +convert.rgb.apple = function (rgb) { + return [(rgb[0] / 255) * 65535, (rgb[1] / 255) * 65535, (rgb[2] / 255) * 65535]; +}; -"use strict"; +convert.gray.rgb = function (args) { + return [args[0] / 100 * 255, args[0] / 100 * 255, args[0] / 100 * 255]; +}; -const os = __webpack_require__(120); +convert.gray.hsl = function (args) { + return [0, 0, args[0]]; +}; -const extractPathRegex = /\s+at.*(?:\(|\s)(.*)\)?/; -const pathRegex = /^(?:(?:(?:node|(?:internal\/[\w/]*|.*node_modules\/(?:babel-polyfill|pirates)\/.*)?\w+)\.js:\d+:\d+)|native)/; -const homeDir = typeof os.homedir === 'undefined' ? '' : os.homedir(); +convert.gray.hsv = convert.gray.hsl; -module.exports = (stack, options) => { - options = Object.assign({pretty: false}, options); +convert.gray.hwb = function (gray) { + return [0, 100, gray[0]]; +}; - return stack.replace(/\\/g, '/') - .split('\n') - .filter(line => { - const pathMatches = line.match(extractPathRegex); - if (pathMatches === null || !pathMatches[1]) { - return true; - } +convert.gray.cmyk = function (gray) { + return [0, 0, 0, gray[0]]; +}; - const match = pathMatches[1]; +convert.gray.lab = function (gray) { + return [gray[0], 0, 0]; +}; - // Electron - if ( - match.includes('.app/Contents/Resources/electron.asar') || - match.includes('.app/Contents/Resources/default_app.asar') - ) { - return false; - } +convert.gray.hex = function (gray) { + const val = Math.round(gray[0] / 100 * 255) & 0xFF; + const integer = (val << 16) + (val << 8) + val; - return !pathRegex.test(match); - }) - .filter(line => line.trim() !== '') - .map(line => { - if (options.pretty) { - return line.replace(extractPathRegex, (m, p1) => m.replace(p1, p1.replace(homeDir, '~'))); - } + const string = integer.toString(16).toUpperCase(); + return '000000'.substring(string.length) + string; +}; - return line; - }) - .join('\n'); +convert.rgb.gray = function (rgb) { + const val = (rgb[0] + rgb[1] + rgb[2]) / 3; + return [val / 255 * 100]; }; /***/ }), -/* 375 */ +/* 373 */ /***/ (function(module, exports, __webpack_require__) { -"use strict"; - -const chalk = __webpack_require__(376); -const cliCursor = __webpack_require__(385); -const cliSpinners = __webpack_require__(389); -const logSymbols = __webpack_require__(391); - -class Ora { - constructor(options) { - if (typeof options === 'string') { - options = { - text: options - }; - } - - this.options = Object.assign({ - text: '', - color: 'cyan', - stream: process.stderr - }, options); - - const sp = this.options.spinner; - this.spinner = typeof sp === 'object' ? sp : (process.platform === 'win32' ? cliSpinners.line : (cliSpinners[sp] || cliSpinners.dots)); // eslint-disable-line no-nested-ternary +const conversions = __webpack_require__(372); - if (this.spinner.frames === undefined) { - throw new Error('Spinner must define `frames`'); - } +/* + This function routes a model to all other models. - this.text = this.options.text; - this.color = this.options.color; - this.interval = this.options.interval || this.spinner.interval || 100; - this.stream = this.options.stream; - this.id = null; - this.frameIndex = 0; - this.enabled = typeof this.options.enabled === 'boolean' ? this.options.enabled : ((this.stream && this.stream.isTTY) && !process.env.CI); - } - frame() { - const frames = this.spinner.frames; - let frame = frames[this.frameIndex]; + all functions that are routed have a property `.conversion` attached + to the returned synthetic function. This property is an array + of strings, each with the steps in between the 'from' and 'to' + color models (inclusive). - if (this.color) { - frame = chalk[this.color](frame); - } + conversions that are not possible simply are not included. +*/ - this.frameIndex = ++this.frameIndex % frames.length; +function buildGraph() { + const graph = {}; + // https://jsperf.com/object-keys-vs-for-in-with-closure/3 + const models = Object.keys(conversions); - return frame + ' ' + this.text; + for (let len = models.length, i = 0; i < len; i++) { + graph[models[i]] = { + // http://jsperf.com/1-vs-infinity + // micro-opt, but this is simple. + distance: -1, + parent: null + }; } - clear() { - if (!this.enabled) { - return this; - } - this.stream.clearLine(); - this.stream.cursorTo(0); + return graph; +} - return this; - } - render() { - this.clear(); - this.stream.write(this.frame()); +// https://en.wikipedia.org/wiki/Breadth-first_search +function deriveBFS(fromModel) { + const graph = buildGraph(); + const queue = [fromModel]; // Unshift -> queue -> pop - return this; - } - start(text) { - if (text) { - this.text = text; - } + graph[fromModel].distance = 0; - if (!this.enabled || this.id) { - return this; - } + while (queue.length) { + const current = queue.pop(); + const adjacents = Object.keys(conversions[current]); - cliCursor.hide(this.stream); - this.render(); - this.id = setInterval(this.render.bind(this), this.interval); + for (let len = adjacents.length, i = 0; i < len; i++) { + const adjacent = adjacents[i]; + const node = graph[adjacent]; - return this; - } - stop() { - if (!this.enabled) { - return this; + if (node.distance === -1) { + node.distance = graph[current].distance + 1; + node.parent = current; + queue.unshift(adjacent); + } } - - clearInterval(this.id); - this.id = null; - this.frameIndex = 0; - this.clear(); - cliCursor.show(this.stream); - - return this; - } - succeed(text) { - return this.stopAndPersist({symbol: logSymbols.success, text}); - } - fail(text) { - return this.stopAndPersist({symbol: logSymbols.error, text}); - } - warn(text) { - return this.stopAndPersist({symbol: logSymbols.warning, text}); } - info(text) { - return this.stopAndPersist({symbol: logSymbols.info, text}); - } - stopAndPersist(options) { - if (!this.enabled) { - return this; - } - // Legacy argument - // TODO: Deprecate sometime in the future - if (typeof options === 'string') { - options = { - symbol: options - }; - } + return graph; +} - options = options || {}; +function link(from, to) { + return function (args) { + return to(from(args)); + }; +} - this.stop(); - this.stream.write(`${options.symbol || ' '} ${options.text || this.text}\n`); +function wrapConversion(toModel, graph) { + const path = [graph[toModel].parent, toModel]; + let fn = conversions[graph[toModel].parent][toModel]; - return this; + let cur = graph[toModel].parent; + while (graph[cur].parent) { + path.unshift(graph[cur].parent); + fn = link(conversions[graph[cur].parent][cur], fn); + cur = graph[cur].parent; } -} -module.exports = function (opts) { - return new Ora(opts); -}; + fn.conversion = path; + return fn; +} -module.exports.promise = (action, options) => { - if (typeof action.then !== 'function') { - throw new TypeError('Parameter `action` must be a Promise'); - } +module.exports = function (fromModel) { + const graph = deriveBFS(fromModel); + const conversion = {}; - const spinner = new Ora(options); - spinner.start(); + const models = Object.keys(graph); + for (let len = models.length, i = 0; i < len; i++) { + const toModel = models[i]; + const node = graph[toModel]; - action.then( - () => { - spinner.succeed(); - }, - () => { - spinner.fail(); + if (node.parent === null) { + // No possible conversion, or this node is the source model. + continue; } - ); - return spinner; + conversion[toModel] = wrapConversion(toModel, graph); + } + + return conversion; }; + /***/ }), -/* 376 */ +/* 374 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const escapeStringRegexp = __webpack_require__(178); -const ansiStyles = __webpack_require__(377); -const stdoutColor = __webpack_require__(382).stdout; -const template = __webpack_require__(384); +const stringReplaceAll = (string, substring, replacer) => { + let index = string.indexOf(substring); + if (index === -1) { + return string; + } -const isSimpleWindowsTerm = process.platform === 'win32' && !(process.env.TERM || '').toLowerCase().startsWith('xterm'); + const substringLength = substring.length; + let endIndex = 0; + let returnValue = ''; + do { + returnValue += string.substr(endIndex, index - endIndex) + substring + replacer; + endIndex = index + substringLength; + index = string.indexOf(substring, endIndex); + } while (index !== -1); -// `supportsColor.level` → `ansiStyles.color[name]` mapping -const levelMapping = ['ansi', 'ansi', 'ansi256', 'ansi16m']; + returnValue += string.substr(endIndex); + return returnValue; +}; -// `color-convert` models to exclude from the Chalk API due to conflicts and such -const skipModels = new Set(['gray']); +const stringEncaseCRLFWithFirstIndex = (string, prefix, postfix, index) => { + let endIndex = 0; + let returnValue = ''; + do { + const gotCR = string[index - 1] === '\r'; + returnValue += string.substr(endIndex, (gotCR ? index - 1 : index) - endIndex) + prefix + (gotCR ? '\r\n' : '\n') + postfix; + endIndex = index + 1; + index = string.indexOf('\n', endIndex); + } while (index !== -1); -const styles = Object.create(null); + returnValue += string.substr(endIndex); + return returnValue; +}; -function applyOptions(obj, options) { - options = options || {}; +module.exports = { + stringReplaceAll, + stringEncaseCRLFWithFirstIndex +}; - // Detect level if not set manually - const scLevel = stdoutColor ? stdoutColor.level : 0; - obj.level = options.level === undefined ? scLevel : options.level; - obj.enabled = 'enabled' in options ? options.enabled : obj.level > 0; -} -function Chalk(options) { - // We check for this.template here since calling `chalk.constructor()` - // by itself will have a `this` of a previously constructed chalk object - if (!this || !(this instanceof Chalk) || this.template) { - const chalk = {}; - applyOptions(chalk, options); +/***/ }), +/* 375 */ +/***/ (function(module, exports, __webpack_require__) { - chalk.template = function () { - const args = [].slice.call(arguments); - return chalkTag.apply(null, [chalk.template].concat(args)); - }; +"use strict"; - Object.setPrototypeOf(chalk, Chalk.prototype); - Object.setPrototypeOf(chalk.template, chalk); +const TEMPLATE_REGEX = /(?:\\(u(?:[a-f\d]{4}|\{[a-f\d]{1,6}\})|x[a-f\d]{2}|.))|(?:\{(~)?(\w+(?:\([^)]*\))?(?:\.\w+(?:\([^)]*\))?)*)(?:[ \t]|(?=\r?\n)))|(\})|((?:.|[\r\n\f])+?)/gi; +const STYLE_REGEX = /(?:^|\.)(\w+)(?:\(([^)]*)\))?/g; +const STRING_REGEX = /^(['"])((?:\\.|(?!\1)[^\\])*)\1$/; +const ESCAPE_REGEX = /\\(u(?:[a-f\d]{4}|\{[a-f\d]{1,6}\})|x[a-f\d]{2}|.)|([^\\])/gi; - chalk.template.constructor = Chalk; +const ESCAPES = new Map([ + ['n', '\n'], + ['r', '\r'], + ['t', '\t'], + ['b', '\b'], + ['f', '\f'], + ['v', '\v'], + ['0', '\0'], + ['\\', '\\'], + ['e', '\u001B'], + ['a', '\u0007'] +]); - return chalk.template; +function unescape(c) { + const u = c[0] === 'u'; + const bracket = c[1] === '{'; + + if ((u && !bracket && c.length === 5) || (c[0] === 'x' && c.length === 3)) { + return String.fromCharCode(parseInt(c.slice(1), 16)); } - applyOptions(this, options); -} + if (u && bracket) { + return String.fromCodePoint(parseInt(c.slice(2, -1), 16)); + } -// Use bright blue on Windows as the normal blue color is illegible -if (isSimpleWindowsTerm) { - ansiStyles.blue.open = '\u001B[94m'; + return ESCAPES.get(c) || c; } -for (const key of Object.keys(ansiStyles)) { - ansiStyles[key].closeRe = new RegExp(escapeStringRegexp(ansiStyles[key].close), 'g'); +function parseArguments(name, arguments_) { + const results = []; + const chunks = arguments_.trim().split(/\s*,\s*/g); + let matches; - styles[key] = { - get() { - const codes = ansiStyles[key]; - return build.call(this, this._styles ? this._styles.concat(codes) : [codes], this._empty, key); + for (const chunk of chunks) { + const number = Number(chunk); + if (!Number.isNaN(number)) { + results.push(number); + } else if ((matches = chunk.match(STRING_REGEX))) { + results.push(matches[2].replace(ESCAPE_REGEX, (m, escape, character) => escape ? unescape(escape) : character)); + } else { + throw new Error(`Invalid Chalk template style argument: ${chunk} (in style '${name}')`); } - }; -} - -styles.visible = { - get() { - return build.call(this, this._styles || [], true, 'visible'); - } -}; - -ansiStyles.color.closeRe = new RegExp(escapeStringRegexp(ansiStyles.color.close), 'g'); -for (const model of Object.keys(ansiStyles.color.ansi)) { - if (skipModels.has(model)) { - continue; } - styles[model] = { - get() { - const level = this.level; - return function () { - const open = ansiStyles.color[levelMapping[level]][model].apply(null, arguments); - const codes = { - open, - close: ansiStyles.color.close, - closeRe: ansiStyles.color.closeRe - }; - return build.call(this, this._styles ? this._styles.concat(codes) : [codes], this._empty, model); - }; - } - }; + return results; } -ansiStyles.bgColor.closeRe = new RegExp(escapeStringRegexp(ansiStyles.bgColor.close), 'g'); -for (const model of Object.keys(ansiStyles.bgColor.ansi)) { - if (skipModels.has(model)) { - continue; - } +function parseStyle(style) { + STYLE_REGEX.lastIndex = 0; - const bgModel = 'bg' + model[0].toUpperCase() + model.slice(1); - styles[bgModel] = { - get() { - const level = this.level; - return function () { - const open = ansiStyles.bgColor[levelMapping[level]][model].apply(null, arguments); - const codes = { - open, - close: ansiStyles.bgColor.close, - closeRe: ansiStyles.bgColor.closeRe - }; - return build.call(this, this._styles ? this._styles.concat(codes) : [codes], this._empty, model); - }; - } - }; -} + const results = []; + let matches; -const proto = Object.defineProperties(() => {}, styles); + while ((matches = STYLE_REGEX.exec(style)) !== null) { + const name = matches[1]; -function build(_styles, _empty, key) { - const builder = function () { - return applyStyle.apply(builder, arguments); - }; + if (matches[2]) { + const args = parseArguments(name, matches[2]); + results.push([name].concat(args)); + } else { + results.push([name]); + } + } - builder._styles = _styles; - builder._empty = _empty; + return results; +} - const self = this; +function buildStyle(chalk, styles) { + const enabled = {}; - Object.defineProperty(builder, 'level', { - enumerable: true, - get() { - return self.level; - }, - set(level) { - self.level = level; + for (const layer of styles) { + for (const style of layer.styles) { + enabled[style[0]] = layer.inverse ? null : style.slice(1); } - }); + } - Object.defineProperty(builder, 'enabled', { - enumerable: true, - get() { - return self.enabled; - }, - set(enabled) { - self.enabled = enabled; + let current = chalk; + for (const [styleName, styles] of Object.entries(enabled)) { + if (!Array.isArray(styles)) { + continue; } - }); - // See below for fix regarding invisible grey/dim combination on Windows - builder.hasGrey = this.hasGrey || key === 'gray' || key === 'grey'; + if (!(styleName in current)) { + throw new Error(`Unknown Chalk style: ${styleName}`); + } - // `__proto__` is used because we must return a function, but there is - // no way to create a function with a different prototype - builder.__proto__ = proto; // eslint-disable-line no-proto + current = styles.length > 0 ? current[styleName](...styles) : current[styleName]; + } - return builder; + return current; } -function applyStyle() { - // Support varags, but simply cast to string in case there's only one arg - const args = arguments; - const argsLen = args.length; - let str = String(arguments[0]); - - if (argsLen === 0) { - return ''; - } +module.exports = (chalk, temporary) => { + const styles = []; + const chunks = []; + let chunk = []; - if (argsLen > 1) { + // eslint-disable-next-line max-params + temporary.replace(TEMPLATE_REGEX, (m, escapeCharacter, inverse, style, close, character) => { + if (escapeCharacter) { + chunk.push(unescape(escapeCharacter)); + } else if (style) { + const string = chunk.join(''); + chunk = []; + chunks.push(styles.length === 0 ? string : buildStyle(chalk, styles)(string)); + styles.push({inverse, styles: parseStyle(style)}); + } else if (close) { + if (styles.length === 0) { + throw new Error('Found extraneous } in Chalk template literal'); + } + + chunks.push(buildStyle(chalk, styles)(chunk.join(''))); + chunk = []; + styles.pop(); + } else { + chunk.push(character); + } + }); + + chunks.push(chunk.join('')); + + if (styles.length > 0) { + const errMsg = `Chalk template literal is missing ${styles.length} closing bracket${styles.length === 1 ? '' : 's'} (\`}\`)`; + throw new Error(errMsg); + } + + return chunks.join(''); +}; + + +/***/ }), +/* 376 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +const restoreCursor = __webpack_require__(377); + +let isHidden = false; + +exports.show = (writableStream = process.stderr) => { + if (!writableStream.isTTY) { + return; + } + + isHidden = false; + writableStream.write('\u001B[?25h'); +}; + +exports.hide = (writableStream = process.stderr) => { + if (!writableStream.isTTY) { + return; + } + + restoreCursor(); + isHidden = true; + writableStream.write('\u001B[?25l'); +}; + +exports.toggle = (force, writableStream) => { + if (force !== undefined) { + isHidden = force; + } + + if (isHidden) { + exports.show(writableStream); + } else { + exports.hide(writableStream); + } +}; + + +/***/ }), +/* 377 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +const onetime = __webpack_require__(378); +const signalExit = __webpack_require__(218); + +module.exports = onetime(() => { + signalExit(() => { + process.stderr.write('\u001B[?25h'); + }, {alwaysLast: true}); +}); + + +/***/ }), +/* 378 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +const mimicFn = __webpack_require__(379); + +const calledFunctions = new WeakMap(); + +const oneTime = (fn, options = {}) => { + if (typeof fn !== 'function') { + throw new TypeError('Expected a function'); + } + + let ret; + let isCalled = false; + let callCount = 0; + const functionName = fn.displayName || fn.name || ''; + + const onetime = function (...args) { + calledFunctions.set(onetime, ++callCount); + + if (isCalled) { + if (options.throw === true) { + throw new Error(`Function \`${functionName}\` can only be called once`); + } + + return ret; + } + + isCalled = true; + ret = fn.apply(this, args); + fn = null; + + return ret; + }; + + mimicFn(onetime, fn); + calledFunctions.set(onetime, callCount); + + return onetime; +}; + +module.exports = oneTime; +// TODO: Remove this for the next major release +module.exports.default = oneTime; + +module.exports.callCount = fn => { + if (!calledFunctions.has(fn)) { + throw new Error(`The given function \`${fn.name}\` is not wrapped by the \`onetime\` package`); + } + + return calledFunctions.get(fn); +}; + + +/***/ }), +/* 379 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +const mimicFn = (to, from) => { + for (const prop of Reflect.ownKeys(from)) { + Object.defineProperty(to, prop, Object.getOwnPropertyDescriptor(from, prop)); + } + + return to; +}; + +module.exports = mimicFn; +// TODO: Remove this for the next major release +module.exports.default = mimicFn; + + +/***/ }), +/* 380 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +const spinners = Object.assign({}, __webpack_require__(381)); + +const spinnersList = Object.keys(spinners); + +Object.defineProperty(spinners, 'random', { + get() { + const randomIndex = Math.floor(Math.random() * spinnersList.length); + const spinnerName = spinnersList[randomIndex]; + return spinners[spinnerName]; + } +}); + +module.exports = spinners; +// TODO: Remove this for the next major release +module.exports.default = spinners; + + +/***/ }), +/* 381 */ +/***/ (function(module) { + +module.exports = JSON.parse("{\"dots\":{\"interval\":80,\"frames\":[\"⠋\",\"⠙\",\"⠹\",\"⠸\",\"⠼\",\"⠴\",\"⠦\",\"⠧\",\"⠇\",\"⠏\"]},\"dots2\":{\"interval\":80,\"frames\":[\"⣾\",\"⣽\",\"⣻\",\"⢿\",\"⡿\",\"⣟\",\"⣯\",\"⣷\"]},\"dots3\":{\"interval\":80,\"frames\":[\"⠋\",\"⠙\",\"⠚\",\"⠞\",\"⠖\",\"⠦\",\"⠴\",\"⠲\",\"⠳\",\"⠓\"]},\"dots4\":{\"interval\":80,\"frames\":[\"⠄\",\"⠆\",\"⠇\",\"⠋\",\"⠙\",\"⠸\",\"⠰\",\"⠠\",\"⠰\",\"⠸\",\"⠙\",\"⠋\",\"⠇\",\"⠆\"]},\"dots5\":{\"interval\":80,\"frames\":[\"⠋\",\"⠙\",\"⠚\",\"⠒\",\"⠂\",\"⠂\",\"⠒\",\"⠲\",\"⠴\",\"⠦\",\"⠖\",\"⠒\",\"⠐\",\"⠐\",\"⠒\",\"⠓\",\"⠋\"]},\"dots6\":{\"interval\":80,\"frames\":[\"⠁\",\"⠉\",\"⠙\",\"⠚\",\"⠒\",\"⠂\",\"⠂\",\"⠒\",\"⠲\",\"⠴\",\"⠤\",\"⠄\",\"⠄\",\"⠤\",\"⠴\",\"⠲\",\"⠒\",\"⠂\",\"⠂\",\"⠒\",\"⠚\",\"⠙\",\"⠉\",\"⠁\"]},\"dots7\":{\"interval\":80,\"frames\":[\"⠈\",\"⠉\",\"⠋\",\"⠓\",\"⠒\",\"⠐\",\"⠐\",\"⠒\",\"⠖\",\"⠦\",\"⠤\",\"⠠\",\"⠠\",\"⠤\",\"⠦\",\"⠖\",\"⠒\",\"⠐\",\"⠐\",\"⠒\",\"⠓\",\"⠋\",\"⠉\",\"⠈\"]},\"dots8\":{\"interval\":80,\"frames\":[\"⠁\",\"⠁\",\"⠉\",\"⠙\",\"⠚\",\"⠒\",\"⠂\",\"⠂\",\"⠒\",\"⠲\",\"⠴\",\"⠤\",\"⠄\",\"⠄\",\"⠤\",\"⠠\",\"⠠\",\"⠤\",\"⠦\",\"⠖\",\"⠒\",\"⠐\",\"⠐\",\"⠒\",\"⠓\",\"⠋\",\"⠉\",\"⠈\",\"⠈\"]},\"dots9\":{\"interval\":80,\"frames\":[\"⢹\",\"⢺\",\"⢼\",\"⣸\",\"⣇\",\"⡧\",\"⡗\",\"⡏\"]},\"dots10\":{\"interval\":80,\"frames\":[\"⢄\",\"⢂\",\"⢁\",\"⡁\",\"⡈\",\"⡐\",\"⡠\"]},\"dots11\":{\"interval\":100,\"frames\":[\"⠁\",\"⠂\",\"⠄\",\"⡀\",\"⢀\",\"⠠\",\"⠐\",\"⠈\"]},\"dots12\":{\"interval\":80,\"frames\":[\"⢀⠀\",\"⡀⠀\",\"⠄⠀\",\"⢂⠀\",\"⡂⠀\",\"⠅⠀\",\"⢃⠀\",\"⡃⠀\",\"⠍⠀\",\"⢋⠀\",\"⡋⠀\",\"⠍⠁\",\"⢋⠁\",\"⡋⠁\",\"⠍⠉\",\"⠋⠉\",\"⠋⠉\",\"⠉⠙\",\"⠉⠙\",\"⠉⠩\",\"⠈⢙\",\"⠈⡙\",\"⢈⠩\",\"⡀⢙\",\"⠄⡙\",\"⢂⠩\",\"⡂⢘\",\"⠅⡘\",\"⢃⠨\",\"⡃⢐\",\"⠍⡐\",\"⢋⠠\",\"⡋⢀\",\"⠍⡁\",\"⢋⠁\",\"⡋⠁\",\"⠍⠉\",\"⠋⠉\",\"⠋⠉\",\"⠉⠙\",\"⠉⠙\",\"⠉⠩\",\"⠈⢙\",\"⠈⡙\",\"⠈⠩\",\"⠀⢙\",\"⠀⡙\",\"⠀⠩\",\"⠀⢘\",\"⠀⡘\",\"⠀⠨\",\"⠀⢐\",\"⠀⡐\",\"⠀⠠\",\"⠀⢀\",\"⠀⡀\"]},\"dots8Bit\":{\"interval\":80,\"frames\":[\"⠀\",\"⠁\",\"⠂\",\"⠃\",\"⠄\",\"⠅\",\"⠆\",\"⠇\",\"⡀\",\"⡁\",\"⡂\",\"⡃\",\"⡄\",\"⡅\",\"⡆\",\"⡇\",\"⠈\",\"⠉\",\"⠊\",\"⠋\",\"⠌\",\"⠍\",\"⠎\",\"⠏\",\"⡈\",\"⡉\",\"⡊\",\"⡋\",\"⡌\",\"⡍\",\"⡎\",\"⡏\",\"⠐\",\"⠑\",\"⠒\",\"⠓\",\"⠔\",\"⠕\",\"⠖\",\"⠗\",\"⡐\",\"⡑\",\"⡒\",\"⡓\",\"⡔\",\"⡕\",\"⡖\",\"⡗\",\"⠘\",\"⠙\",\"⠚\",\"⠛\",\"⠜\",\"⠝\",\"⠞\",\"⠟\",\"⡘\",\"⡙\",\"⡚\",\"⡛\",\"⡜\",\"⡝\",\"⡞\",\"⡟\",\"⠠\",\"⠡\",\"⠢\",\"⠣\",\"⠤\",\"⠥\",\"⠦\",\"⠧\",\"⡠\",\"⡡\",\"⡢\",\"⡣\",\"⡤\",\"⡥\",\"⡦\",\"⡧\",\"⠨\",\"⠩\",\"⠪\",\"⠫\",\"⠬\",\"⠭\",\"⠮\",\"⠯\",\"⡨\",\"⡩\",\"⡪\",\"⡫\",\"⡬\",\"⡭\",\"⡮\",\"⡯\",\"⠰\",\"⠱\",\"⠲\",\"⠳\",\"⠴\",\"⠵\",\"⠶\",\"⠷\",\"⡰\",\"⡱\",\"⡲\",\"⡳\",\"⡴\",\"⡵\",\"⡶\",\"⡷\",\"⠸\",\"⠹\",\"⠺\",\"⠻\",\"⠼\",\"⠽\",\"⠾\",\"⠿\",\"⡸\",\"⡹\",\"⡺\",\"⡻\",\"⡼\",\"⡽\",\"⡾\",\"⡿\",\"⢀\",\"⢁\",\"⢂\",\"⢃\",\"⢄\",\"⢅\",\"⢆\",\"⢇\",\"⣀\",\"⣁\",\"⣂\",\"⣃\",\"⣄\",\"⣅\",\"⣆\",\"⣇\",\"⢈\",\"⢉\",\"⢊\",\"⢋\",\"⢌\",\"⢍\",\"⢎\",\"⢏\",\"⣈\",\"⣉\",\"⣊\",\"⣋\",\"⣌\",\"⣍\",\"⣎\",\"⣏\",\"⢐\",\"⢑\",\"⢒\",\"⢓\",\"⢔\",\"⢕\",\"⢖\",\"⢗\",\"⣐\",\"⣑\",\"⣒\",\"⣓\",\"⣔\",\"⣕\",\"⣖\",\"⣗\",\"⢘\",\"⢙\",\"⢚\",\"⢛\",\"⢜\",\"⢝\",\"⢞\",\"⢟\",\"⣘\",\"⣙\",\"⣚\",\"⣛\",\"⣜\",\"⣝\",\"⣞\",\"⣟\",\"⢠\",\"⢡\",\"⢢\",\"⢣\",\"⢤\",\"⢥\",\"⢦\",\"⢧\",\"⣠\",\"⣡\",\"⣢\",\"⣣\",\"⣤\",\"⣥\",\"⣦\",\"⣧\",\"⢨\",\"⢩\",\"⢪\",\"⢫\",\"⢬\",\"⢭\",\"⢮\",\"⢯\",\"⣨\",\"⣩\",\"⣪\",\"⣫\",\"⣬\",\"⣭\",\"⣮\",\"⣯\",\"⢰\",\"⢱\",\"⢲\",\"⢳\",\"⢴\",\"⢵\",\"⢶\",\"⢷\",\"⣰\",\"⣱\",\"⣲\",\"⣳\",\"⣴\",\"⣵\",\"⣶\",\"⣷\",\"⢸\",\"⢹\",\"⢺\",\"⢻\",\"⢼\",\"⢽\",\"⢾\",\"⢿\",\"⣸\",\"⣹\",\"⣺\",\"⣻\",\"⣼\",\"⣽\",\"⣾\",\"⣿\"]},\"line\":{\"interval\":130,\"frames\":[\"-\",\"\\\\\",\"|\",\"/\"]},\"line2\":{\"interval\":100,\"frames\":[\"⠂\",\"-\",\"–\",\"—\",\"–\",\"-\"]},\"pipe\":{\"interval\":100,\"frames\":[\"┤\",\"┘\",\"┴\",\"└\",\"├\",\"┌\",\"┬\",\"┐\"]},\"simpleDots\":{\"interval\":400,\"frames\":[\". \",\".. \",\"...\",\" \"]},\"simpleDotsScrolling\":{\"interval\":200,\"frames\":[\". \",\".. \",\"...\",\" ..\",\" .\",\" \"]},\"star\":{\"interval\":70,\"frames\":[\"✶\",\"✸\",\"✹\",\"✺\",\"✹\",\"✷\"]},\"star2\":{\"interval\":80,\"frames\":[\"+\",\"x\",\"*\"]},\"flip\":{\"interval\":70,\"frames\":[\"_\",\"_\",\"_\",\"-\",\"`\",\"`\",\"'\",\"´\",\"-\",\"_\",\"_\",\"_\"]},\"hamburger\":{\"interval\":100,\"frames\":[\"☱\",\"☲\",\"☴\"]},\"growVertical\":{\"interval\":120,\"frames\":[\"▁\",\"▃\",\"▄\",\"▅\",\"▆\",\"▇\",\"▆\",\"▅\",\"▄\",\"▃\"]},\"growHorizontal\":{\"interval\":120,\"frames\":[\"▏\",\"▎\",\"▍\",\"▌\",\"▋\",\"▊\",\"▉\",\"▊\",\"▋\",\"▌\",\"▍\",\"▎\"]},\"balloon\":{\"interval\":140,\"frames\":[\" \",\".\",\"o\",\"O\",\"@\",\"*\",\" \"]},\"balloon2\":{\"interval\":120,\"frames\":[\".\",\"o\",\"O\",\"°\",\"O\",\"o\",\".\"]},\"noise\":{\"interval\":100,\"frames\":[\"▓\",\"▒\",\"░\"]},\"bounce\":{\"interval\":120,\"frames\":[\"⠁\",\"⠂\",\"⠄\",\"⠂\"]},\"boxBounce\":{\"interval\":120,\"frames\":[\"▖\",\"▘\",\"▝\",\"▗\"]},\"boxBounce2\":{\"interval\":100,\"frames\":[\"▌\",\"▀\",\"▐\",\"▄\"]},\"triangle\":{\"interval\":50,\"frames\":[\"◢\",\"◣\",\"◤\",\"◥\"]},\"arc\":{\"interval\":100,\"frames\":[\"◜\",\"◠\",\"◝\",\"◞\",\"◡\",\"◟\"]},\"circle\":{\"interval\":120,\"frames\":[\"◡\",\"⊙\",\"◠\"]},\"squareCorners\":{\"interval\":180,\"frames\":[\"◰\",\"◳\",\"◲\",\"◱\"]},\"circleQuarters\":{\"interval\":120,\"frames\":[\"◴\",\"◷\",\"◶\",\"◵\"]},\"circleHalves\":{\"interval\":50,\"frames\":[\"◐\",\"◓\",\"◑\",\"◒\"]},\"squish\":{\"interval\":100,\"frames\":[\"╫\",\"╪\"]},\"toggle\":{\"interval\":250,\"frames\":[\"⊶\",\"⊷\"]},\"toggle2\":{\"interval\":80,\"frames\":[\"▫\",\"▪\"]},\"toggle3\":{\"interval\":120,\"frames\":[\"□\",\"■\"]},\"toggle4\":{\"interval\":100,\"frames\":[\"■\",\"□\",\"▪\",\"▫\"]},\"toggle5\":{\"interval\":100,\"frames\":[\"▮\",\"▯\"]},\"toggle6\":{\"interval\":300,\"frames\":[\"ဝ\",\"၀\"]},\"toggle7\":{\"interval\":80,\"frames\":[\"⦾\",\"⦿\"]},\"toggle8\":{\"interval\":100,\"frames\":[\"◍\",\"◌\"]},\"toggle9\":{\"interval\":100,\"frames\":[\"◉\",\"◎\"]},\"toggle10\":{\"interval\":100,\"frames\":[\"㊂\",\"㊀\",\"㊁\"]},\"toggle11\":{\"interval\":50,\"frames\":[\"⧇\",\"⧆\"]},\"toggle12\":{\"interval\":120,\"frames\":[\"☗\",\"☖\"]},\"toggle13\":{\"interval\":80,\"frames\":[\"=\",\"*\",\"-\"]},\"arrow\":{\"interval\":100,\"frames\":[\"←\",\"↖\",\"↑\",\"↗\",\"→\",\"↘\",\"↓\",\"↙\"]},\"arrow2\":{\"interval\":80,\"frames\":[\"⬆️ \",\"↗️ \",\"➡️ \",\"↘️ \",\"⬇️ \",\"↙️ \",\"⬅️ \",\"↖️ \"]},\"arrow3\":{\"interval\":120,\"frames\":[\"▹▹▹▹▹\",\"▸▹▹▹▹\",\"▹▸▹▹▹\",\"▹▹▸▹▹\",\"▹▹▹▸▹\",\"▹▹▹▹▸\"]},\"bouncingBar\":{\"interval\":80,\"frames\":[\"[ ]\",\"[= ]\",\"[== ]\",\"[=== ]\",\"[ ===]\",\"[ ==]\",\"[ =]\",\"[ ]\",\"[ =]\",\"[ ==]\",\"[ ===]\",\"[====]\",\"[=== ]\",\"[== ]\",\"[= ]\"]},\"bouncingBall\":{\"interval\":80,\"frames\":[\"( ● )\",\"( ● )\",\"( ● )\",\"( ● )\",\"( ●)\",\"( ● )\",\"( ● )\",\"( ● )\",\"( ● )\",\"(● )\"]},\"smiley\":{\"interval\":200,\"frames\":[\"😄 \",\"😝 \"]},\"monkey\":{\"interval\":300,\"frames\":[\"🙈 \",\"🙈 \",\"🙉 \",\"🙊 \"]},\"hearts\":{\"interval\":100,\"frames\":[\"💛 \",\"💙 \",\"💜 \",\"💚 \",\"❤️ \"]},\"clock\":{\"interval\":100,\"frames\":[\"🕛 \",\"🕐 \",\"🕑 \",\"🕒 \",\"🕓 \",\"🕔 \",\"🕕 \",\"🕖 \",\"🕗 \",\"🕘 \",\"🕙 \",\"🕚 \"]},\"earth\":{\"interval\":180,\"frames\":[\"🌍 \",\"🌎 \",\"🌏 \"]},\"material\":{\"interval\":17,\"frames\":[\"█▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁\",\"██▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁\",\"███▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁\",\"████▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁\",\"██████▁▁▁▁▁▁▁▁▁▁▁▁▁▁\",\"██████▁▁▁▁▁▁▁▁▁▁▁▁▁▁\",\"███████▁▁▁▁▁▁▁▁▁▁▁▁▁\",\"████████▁▁▁▁▁▁▁▁▁▁▁▁\",\"█████████▁▁▁▁▁▁▁▁▁▁▁\",\"█████████▁▁▁▁▁▁▁▁▁▁▁\",\"██████████▁▁▁▁▁▁▁▁▁▁\",\"███████████▁▁▁▁▁▁▁▁▁\",\"█████████████▁▁▁▁▁▁▁\",\"██████████████▁▁▁▁▁▁\",\"██████████████▁▁▁▁▁▁\",\"▁██████████████▁▁▁▁▁\",\"▁██████████████▁▁▁▁▁\",\"▁██████████████▁▁▁▁▁\",\"▁▁██████████████▁▁▁▁\",\"▁▁▁██████████████▁▁▁\",\"▁▁▁▁█████████████▁▁▁\",\"▁▁▁▁██████████████▁▁\",\"▁▁▁▁██████████████▁▁\",\"▁▁▁▁▁██████████████▁\",\"▁▁▁▁▁██████████████▁\",\"▁▁▁▁▁██████████████▁\",\"▁▁▁▁▁▁██████████████\",\"▁▁▁▁▁▁██████████████\",\"▁▁▁▁▁▁▁█████████████\",\"▁▁▁▁▁▁▁█████████████\",\"▁▁▁▁▁▁▁▁████████████\",\"▁▁▁▁▁▁▁▁████████████\",\"▁▁▁▁▁▁▁▁▁███████████\",\"▁▁▁▁▁▁▁▁▁███████████\",\"▁▁▁▁▁▁▁▁▁▁██████████\",\"▁▁▁▁▁▁▁▁▁▁██████████\",\"▁▁▁▁▁▁▁▁▁▁▁▁████████\",\"▁▁▁▁▁▁▁▁▁▁▁▁▁███████\",\"▁▁▁▁▁▁▁▁▁▁▁▁▁▁██████\",\"▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█████\",\"▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█████\",\"█▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁████\",\"██▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁███\",\"██▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁███\",\"███▁▁▁▁▁▁▁▁▁▁▁▁▁▁███\",\"████▁▁▁▁▁▁▁▁▁▁▁▁▁▁██\",\"█████▁▁▁▁▁▁▁▁▁▁▁▁▁▁█\",\"█████▁▁▁▁▁▁▁▁▁▁▁▁▁▁█\",\"██████▁▁▁▁▁▁▁▁▁▁▁▁▁█\",\"████████▁▁▁▁▁▁▁▁▁▁▁▁\",\"█████████▁▁▁▁▁▁▁▁▁▁▁\",\"█████████▁▁▁▁▁▁▁▁▁▁▁\",\"█████████▁▁▁▁▁▁▁▁▁▁▁\",\"█████████▁▁▁▁▁▁▁▁▁▁▁\",\"███████████▁▁▁▁▁▁▁▁▁\",\"████████████▁▁▁▁▁▁▁▁\",\"████████████▁▁▁▁▁▁▁▁\",\"██████████████▁▁▁▁▁▁\",\"██████████████▁▁▁▁▁▁\",\"▁██████████████▁▁▁▁▁\",\"▁██████████████▁▁▁▁▁\",\"▁▁▁█████████████▁▁▁▁\",\"▁▁▁▁▁████████████▁▁▁\",\"▁▁▁▁▁████████████▁▁▁\",\"▁▁▁▁▁▁███████████▁▁▁\",\"▁▁▁▁▁▁▁▁█████████▁▁▁\",\"▁▁▁▁▁▁▁▁█████████▁▁▁\",\"▁▁▁▁▁▁▁▁▁█████████▁▁\",\"▁▁▁▁▁▁▁▁▁█████████▁▁\",\"▁▁▁▁▁▁▁▁▁▁█████████▁\",\"▁▁▁▁▁▁▁▁▁▁▁████████▁\",\"▁▁▁▁▁▁▁▁▁▁▁████████▁\",\"▁▁▁▁▁▁▁▁▁▁▁▁███████▁\",\"▁▁▁▁▁▁▁▁▁▁▁▁███████▁\",\"▁▁▁▁▁▁▁▁▁▁▁▁▁███████\",\"▁▁▁▁▁▁▁▁▁▁▁▁▁███████\",\"▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█████\",\"▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁████\",\"▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁████\",\"▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁████\",\"▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁███\",\"▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁███\",\"▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁██\",\"▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁██\",\"▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁██\",\"▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█\",\"▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█\",\"▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█\",\"▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁\",\"▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁\",\"▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁\",\"▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁\"]},\"moon\":{\"interval\":80,\"frames\":[\"🌑 \",\"🌒 \",\"🌓 \",\"🌔 \",\"🌕 \",\"🌖 \",\"🌗 \",\"🌘 \"]},\"runner\":{\"interval\":140,\"frames\":[\"🚶 \",\"🏃 \"]},\"pong\":{\"interval\":80,\"frames\":[\"▐⠂ ▌\",\"▐⠈ ▌\",\"▐ ⠂ ▌\",\"▐ ⠠ ▌\",\"▐ ⡀ ▌\",\"▐ ⠠ ▌\",\"▐ ⠂ ▌\",\"▐ ⠈ ▌\",\"▐ ⠂ ▌\",\"▐ ⠠ ▌\",\"▐ ⡀ ▌\",\"▐ ⠠ ▌\",\"▐ ⠂ ▌\",\"▐ ⠈ ▌\",\"▐ ⠂▌\",\"▐ ⠠▌\",\"▐ ⡀▌\",\"▐ ⠠ ▌\",\"▐ ⠂ ▌\",\"▐ ⠈ ▌\",\"▐ ⠂ ▌\",\"▐ ⠠ ▌\",\"▐ ⡀ ▌\",\"▐ ⠠ ▌\",\"▐ ⠂ ▌\",\"▐ ⠈ ▌\",\"▐ ⠂ ▌\",\"▐ ⠠ ▌\",\"▐ ⡀ ▌\",\"▐⠠ ▌\"]},\"shark\":{\"interval\":120,\"frames\":[\"▐|\\\\____________▌\",\"▐_|\\\\___________▌\",\"▐__|\\\\__________▌\",\"▐___|\\\\_________▌\",\"▐____|\\\\________▌\",\"▐_____|\\\\_______▌\",\"▐______|\\\\______▌\",\"▐_______|\\\\_____▌\",\"▐________|\\\\____▌\",\"▐_________|\\\\___▌\",\"▐__________|\\\\__▌\",\"▐___________|\\\\_▌\",\"▐____________|\\\\▌\",\"▐____________/|▌\",\"▐___________/|_▌\",\"▐__________/|__▌\",\"▐_________/|___▌\",\"▐________/|____▌\",\"▐_______/|_____▌\",\"▐______/|______▌\",\"▐_____/|_______▌\",\"▐____/|________▌\",\"▐___/|_________▌\",\"▐__/|__________▌\",\"▐_/|___________▌\",\"▐/|____________▌\"]},\"dqpb\":{\"interval\":100,\"frames\":[\"d\",\"q\",\"p\",\"b\"]},\"weather\":{\"interval\":100,\"frames\":[\"☀️ \",\"☀️ \",\"☀️ \",\"🌤 \",\"⛅️ \",\"🌥 \",\"☁️ \",\"🌧 \",\"🌨 \",\"🌧 \",\"🌨 \",\"🌧 \",\"🌨 \",\"⛈ \",\"🌨 \",\"🌧 \",\"🌨 \",\"☁️ \",\"🌥 \",\"⛅️ \",\"🌤 \",\"☀️ \",\"☀️ \"]},\"christmas\":{\"interval\":400,\"frames\":[\"🌲\",\"🎄\"]},\"grenade\":{\"interval\":80,\"frames\":[\"، \",\"′ \",\" ´ \",\" ‾ \",\" ⸌\",\" ⸊\",\" |\",\" ⁎\",\" ⁕\",\" ෴ \",\" ⁓\",\" \",\" \",\" \"]},\"point\":{\"interval\":125,\"frames\":[\"∙∙∙\",\"●∙∙\",\"∙●∙\",\"∙∙●\",\"∙∙∙\"]},\"layer\":{\"interval\":150,\"frames\":[\"-\",\"=\",\"≡\"]},\"betaWave\":{\"interval\":80,\"frames\":[\"ρββββββ\",\"βρβββββ\",\"ββρββββ\",\"βββρβββ\",\"ββββρββ\",\"βββββρβ\",\"ββββββρ\"]}}"); + +/***/ }), +/* 382 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +const chalk = __webpack_require__(383); + +const isSupported = process.platform !== 'win32' || process.env.CI || process.env.TERM === 'xterm-256color'; + +const main = { + info: chalk.blue('ℹ'), + success: chalk.green('✔'), + warning: chalk.yellow('⚠'), + error: chalk.red('✖') +}; + +const fallbacks = { + info: chalk.blue('i'), + success: chalk.green('√'), + warning: chalk.yellow('‼'), + error: chalk.red('×') +}; + +module.exports = isSupported ? main : fallbacks; + + +/***/ }), +/* 383 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +const escapeStringRegexp = __webpack_require__(179); +const ansiStyles = __webpack_require__(384); +const stdoutColor = __webpack_require__(389).stdout; + +const template = __webpack_require__(390); + +const isSimpleWindowsTerm = process.platform === 'win32' && !(process.env.TERM || '').toLowerCase().startsWith('xterm'); + +// `supportsColor.level` → `ansiStyles.color[name]` mapping +const levelMapping = ['ansi', 'ansi', 'ansi256', 'ansi16m']; + +// `color-convert` models to exclude from the Chalk API due to conflicts and such +const skipModels = new Set(['gray']); + +const styles = Object.create(null); + +function applyOptions(obj, options) { + options = options || {}; + + // Detect level if not set manually + const scLevel = stdoutColor ? stdoutColor.level : 0; + obj.level = options.level === undefined ? scLevel : options.level; + obj.enabled = 'enabled' in options ? options.enabled : obj.level > 0; +} + +function Chalk(options) { + // We check for this.template here since calling `chalk.constructor()` + // by itself will have a `this` of a previously constructed chalk object + if (!this || !(this instanceof Chalk) || this.template) { + const chalk = {}; + applyOptions(chalk, options); + + chalk.template = function () { + const args = [].slice.call(arguments); + return chalkTag.apply(null, [chalk.template].concat(args)); + }; + + Object.setPrototypeOf(chalk, Chalk.prototype); + Object.setPrototypeOf(chalk.template, chalk); + + chalk.template.constructor = Chalk; + + return chalk.template; + } + + applyOptions(this, options); +} + +// Use bright blue on Windows as the normal blue color is illegible +if (isSimpleWindowsTerm) { + ansiStyles.blue.open = '\u001B[94m'; +} + +for (const key of Object.keys(ansiStyles)) { + ansiStyles[key].closeRe = new RegExp(escapeStringRegexp(ansiStyles[key].close), 'g'); + + styles[key] = { + get() { + const codes = ansiStyles[key]; + return build.call(this, this._styles ? this._styles.concat(codes) : [codes], this._empty, key); + } + }; +} + +styles.visible = { + get() { + return build.call(this, this._styles || [], true, 'visible'); + } +}; + +ansiStyles.color.closeRe = new RegExp(escapeStringRegexp(ansiStyles.color.close), 'g'); +for (const model of Object.keys(ansiStyles.color.ansi)) { + if (skipModels.has(model)) { + continue; + } + + styles[model] = { + get() { + const level = this.level; + return function () { + const open = ansiStyles.color[levelMapping[level]][model].apply(null, arguments); + const codes = { + open, + close: ansiStyles.color.close, + closeRe: ansiStyles.color.closeRe + }; + return build.call(this, this._styles ? this._styles.concat(codes) : [codes], this._empty, model); + }; + } + }; +} + +ansiStyles.bgColor.closeRe = new RegExp(escapeStringRegexp(ansiStyles.bgColor.close), 'g'); +for (const model of Object.keys(ansiStyles.bgColor.ansi)) { + if (skipModels.has(model)) { + continue; + } + + const bgModel = 'bg' + model[0].toUpperCase() + model.slice(1); + styles[bgModel] = { + get() { + const level = this.level; + return function () { + const open = ansiStyles.bgColor[levelMapping[level]][model].apply(null, arguments); + const codes = { + open, + close: ansiStyles.bgColor.close, + closeRe: ansiStyles.bgColor.closeRe + }; + return build.call(this, this._styles ? this._styles.concat(codes) : [codes], this._empty, model); + }; + } + }; +} + +const proto = Object.defineProperties(() => {}, styles); + +function build(_styles, _empty, key) { + const builder = function () { + return applyStyle.apply(builder, arguments); + }; + + builder._styles = _styles; + builder._empty = _empty; + + const self = this; + + Object.defineProperty(builder, 'level', { + enumerable: true, + get() { + return self.level; + }, + set(level) { + self.level = level; + } + }); + + Object.defineProperty(builder, 'enabled', { + enumerable: true, + get() { + return self.enabled; + }, + set(enabled) { + self.enabled = enabled; + } + }); + + // See below for fix regarding invisible grey/dim combination on Windows + builder.hasGrey = this.hasGrey || key === 'gray' || key === 'grey'; + + // `__proto__` is used because we must return a function, but there is + // no way to create a function with a different prototype + builder.__proto__ = proto; // eslint-disable-line no-proto + + return builder; +} + +function applyStyle() { + // Support varags, but simply cast to string in case there's only one arg + const args = arguments; + const argsLen = args.length; + let str = String(arguments[0]); + + if (argsLen === 0) { + return ''; + } + + if (argsLen > 1) { // Don't slice `arguments`, it prevents V8 optimizations for (let a = 1; a < argsLen; a++) { str += ' ' + args[a]; @@ -48521,12 +49070,12 @@ module.exports.default = module.exports; // For TypeScript /***/ }), -/* 377 */ +/* 384 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; /* WEBPACK VAR INJECTION */(function(module) { -const colorConvert = __webpack_require__(378); +const colorConvert = __webpack_require__(385); const wrapAnsi16 = (fn, offset) => function () { const code = fn.apply(colorConvert, arguments); @@ -48691,14 +49240,14 @@ Object.defineProperty(module, 'exports', { get: assembleStyles }); -/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(114)(module))) +/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(115)(module))) /***/ }), -/* 378 */ +/* 385 */ /***/ (function(module, exports, __webpack_require__) { -var conversions = __webpack_require__(379); -var route = __webpack_require__(381); +var conversions = __webpack_require__(386); +var route = __webpack_require__(388); var convert = {}; @@ -48778,11 +49327,11 @@ module.exports = convert; /***/ }), -/* 379 */ +/* 386 */ /***/ (function(module, exports, __webpack_require__) { /* MIT license */ -var cssKeywords = __webpack_require__(380); +var cssKeywords = __webpack_require__(387); // NOTE: conversions should only return primitive values (i.e. arrays, or // values that give correct `typeof` results). @@ -49652,7 +50201,7 @@ convert.rgb.gray = function (rgb) { /***/ }), -/* 380 */ +/* 387 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -49811,10 +50360,10 @@ module.exports = { /***/ }), -/* 381 */ +/* 388 */ /***/ (function(module, exports, __webpack_require__) { -var conversions = __webpack_require__(379); +var conversions = __webpack_require__(386); /* this function routes a model to all other models. @@ -49914,13 +50463,13 @@ module.exports = function (fromModel) { /***/ }), -/* 382 */ +/* 389 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const os = __webpack_require__(120); -const hasFlag = __webpack_require__(383); +const os = __webpack_require__(121); +const hasFlag = __webpack_require__(186); const env = process.env; @@ -50052,22 +50601,7 @@ module.exports = { /***/ }), -/* 383 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - -module.exports = (flag, argv) => { - argv = argv || process.argv; - const prefix = flag.startsWith('-') ? '' : (flag.length === 1 ? '-' : '--'); - const pos = argv.indexOf(prefix + flag); - const terminatorPos = argv.indexOf('--'); - return pos !== -1 && (terminatorPos === -1 ? true : pos < terminatorPos); -}; - - -/***/ }), -/* 384 */ +/* 390 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -50202,879 +50736,717 @@ module.exports = (chalk, tmp) => { /***/ }), -/* 385 */ +/* 391 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const restoreCursor = __webpack_require__(386); - -let hidden = false; +const ansiRegex = __webpack_require__(392); -exports.show = stream => { - const s = stream || process.stderr; - - if (!s.isTTY) { - return; - } +module.exports = string => typeof string === 'string' ? string.replace(ansiRegex(), '') : string; - hidden = false; - s.write('\u001b[?25h'); -}; -exports.hide = stream => { - const s = stream || process.stderr; +/***/ }), +/* 392 */ +/***/ (function(module, exports, __webpack_require__) { - if (!s.isTTY) { - return; - } +"use strict"; - restoreCursor(); - hidden = true; - s.write('\u001b[?25l'); -}; -exports.toggle = (force, stream) => { - if (force !== undefined) { - hidden = force; - } +module.exports = ({onlyFirst = false} = {}) => { + const pattern = [ + '[\\u001B\\u009B][[\\]()#;?]*(?:(?:(?:[a-zA-Z\\d]*(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]*)*)?\\u0007)', + '(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PR-TZcf-ntqry=><~]))' + ].join('|'); - if (hidden) { - exports.show(stream); - } else { - exports.hide(stream); - } + return new RegExp(pattern, onlyFirst ? undefined : 'g'); }; /***/ }), -/* 386 */ +/* 393 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const onetime = __webpack_require__(387); -const signalExit = __webpack_require__(217); -module.exports = onetime(() => { - signalExit(() => { - process.stderr.write('\u001b[?25h'); - }, {alwaysLast: true}); -}); +var defaults = __webpack_require__(394) +var combining = __webpack_require__(396) +var DEFAULTS = { + nul: 0, + control: 0 +} -/***/ }), -/* 387 */ -/***/ (function(module, exports, __webpack_require__) { +module.exports = function wcwidth(str) { + return wcswidth(str, DEFAULTS) +} -"use strict"; +module.exports.config = function(opts) { + opts = defaults(opts || {}, DEFAULTS) + return function wcwidth(str) { + return wcswidth(str, opts) + } +} -const mimicFn = __webpack_require__(388); +/* + * The following functions define the column width of an ISO 10646 + * character as follows: + * - The null character (U+0000) has a column width of 0. + * - Other C0/C1 control characters and DEL will lead to a return value + * of -1. + * - Non-spacing and enclosing combining characters (general category + * code Mn or Me in the + * Unicode database) have a column width of 0. + * - SOFT HYPHEN (U+00AD) has a column width of 1. + * - Other format characters (general category code Cf in the Unicode + * database) and ZERO WIDTH + * SPACE (U+200B) have a column width of 0. + * - Hangul Jamo medial vowels and final consonants (U+1160-U+11FF) + * have a column width of 0. + * - Spacing characters in the East Asian Wide (W) or East Asian + * Full-width (F) category as + * defined in Unicode Technical Report #11 have a column width of 2. + * - All remaining characters (including all printable ISO 8859-1 and + * WGL4 characters, Unicode control characters, etc.) have a column + * width of 1. + * This implementation assumes that characters are encoded in ISO 10646. +*/ -module.exports = (fn, opts) => { - // TODO: Remove this in v3 - if (opts === true) { - throw new TypeError('The second argument is now an options object'); - } +function wcswidth(str, opts) { + if (typeof str !== 'string') return wcwidth(str, opts) - if (typeof fn !== 'function') { - throw new TypeError('Expected a function'); - } + var s = 0 + for (var i = 0; i < str.length; i++) { + var n = wcwidth(str.charCodeAt(i), opts) + if (n < 0) return -1 + s += n + } - opts = opts || {}; + return s +} - let ret; - let called = false; - const fnName = fn.displayName || fn.name || ''; +function wcwidth(ucs, opts) { + // test for 8-bit control characters + if (ucs === 0) return opts.nul + if (ucs < 32 || (ucs >= 0x7f && ucs < 0xa0)) return opts.control - const onetime = function () { - if (called) { - if (opts.throw === true) { - throw new Error(`Function \`${fnName}\` can only be called once`); - } + // binary search in table of non-spacing characters + if (bisearch(ucs)) return 0 - return ret; - } + // if we arrive here, ucs is not a combining or C0/C1 control character + return 1 + + (ucs >= 0x1100 && + (ucs <= 0x115f || // Hangul Jamo init. consonants + ucs == 0x2329 || ucs == 0x232a || + (ucs >= 0x2e80 && ucs <= 0xa4cf && + ucs != 0x303f) || // CJK ... Yi + (ucs >= 0xac00 && ucs <= 0xd7a3) || // Hangul Syllables + (ucs >= 0xf900 && ucs <= 0xfaff) || // CJK Compatibility Ideographs + (ucs >= 0xfe10 && ucs <= 0xfe19) || // Vertical forms + (ucs >= 0xfe30 && ucs <= 0xfe6f) || // CJK Compatibility Forms + (ucs >= 0xff00 && ucs <= 0xff60) || // Fullwidth Forms + (ucs >= 0xffe0 && ucs <= 0xffe6) || + (ucs >= 0x20000 && ucs <= 0x2fffd) || + (ucs >= 0x30000 && ucs <= 0x3fffd))); +} - called = true; - ret = fn.apply(this, arguments); - fn = null; +function bisearch(ucs) { + var min = 0 + var max = combining.length - 1 + var mid - return ret; - }; + if (ucs < combining[0][0] || ucs > combining[max][1]) return false - mimicFn(onetime, fn); + while (max >= min) { + mid = Math.floor((min + max) / 2) + if (ucs > combining[mid][1]) min = mid + 1 + else if (ucs < combining[mid][0]) max = mid - 1 + else return true + } - return onetime; -}; + return false +} /***/ }), -/* 388 */ +/* 394 */ /***/ (function(module, exports, __webpack_require__) { -"use strict"; +var clone = __webpack_require__(395); -module.exports = (to, from) => { - // TODO: use `Reflect.ownKeys()` when targeting Node.js 6 - for (const prop of Object.getOwnPropertyNames(from).concat(Object.getOwnPropertySymbols(from))) { - Object.defineProperty(to, prop, Object.getOwnPropertyDescriptor(from, prop)); - } +module.exports = function(options, defaults) { + options = options || {}; - return to; -}; + Object.keys(defaults).forEach(function(key) { + if (typeof options[key] === 'undefined') { + options[key] = clone(defaults[key]); + } + }); + return options; +}; /***/ }), -/* 389 */ +/* 395 */ /***/ (function(module, exports, __webpack_require__) { -"use strict"; +var clone = (function() { +'use strict'; -module.exports = __webpack_require__(390); +/** + * Clones (copies) an Object using deep copying. + * + * This function supports circular references by default, but if you are certain + * there are no circular references in your object, you can save some CPU time + * by calling clone(obj, false). + * + * Caution: if `circular` is false and `parent` contains circular references, + * your program may enter an infinite loop and crash. + * + * @param `parent` - the object to be cloned + * @param `circular` - set to true if the object to be cloned may contain + * circular references. (optional - true by default) + * @param `depth` - set to a number if the object is only to be cloned to + * a particular depth. (optional - defaults to Infinity) + * @param `prototype` - sets the prototype to be used when cloning an object. + * (optional - defaults to parent prototype). +*/ +function clone(parent, circular, depth, prototype) { + var filter; + if (typeof circular === 'object') { + depth = circular.depth; + prototype = circular.prototype; + filter = circular.filter; + circular = circular.circular + } + // maintain two arrays for circular references, where corresponding parents + // and children have the same index + var allParents = []; + var allChildren = []; + + var useBuffer = typeof Buffer != 'undefined'; + + if (typeof circular == 'undefined') + circular = true; + + if (typeof depth == 'undefined') + depth = Infinity; + + // recurse this function so we don't reset allParents and allChildren + function _clone(parent, depth) { + // cloning null always returns null + if (parent === null) + return null; + if (depth == 0) + return parent; + + var child; + var proto; + if (typeof parent != 'object') { + return parent; + } + + if (clone.__isArray(parent)) { + child = []; + } else if (clone.__isRegExp(parent)) { + child = new RegExp(parent.source, __getRegExpFlags(parent)); + if (parent.lastIndex) child.lastIndex = parent.lastIndex; + } else if (clone.__isDate(parent)) { + child = new Date(parent.getTime()); + } else if (useBuffer && Buffer.isBuffer(parent)) { + if (Buffer.allocUnsafe) { + // Node.js >= 4.5.0 + child = Buffer.allocUnsafe(parent.length); + } else { + // Older Node.js versions + child = new Buffer(parent.length); + } + parent.copy(child); + return child; + } else { + if (typeof prototype == 'undefined') { + proto = Object.getPrototypeOf(parent); + child = Object.create(proto); + } + else { + child = Object.create(prototype); + proto = prototype; + } + } -/***/ }), -/* 390 */ -/***/ (function(module) { + if (circular) { + var index = allParents.indexOf(parent); -module.exports = JSON.parse("{\"dots\":{\"interval\":80,\"frames\":[\"⠋\",\"⠙\",\"⠹\",\"⠸\",\"⠼\",\"⠴\",\"⠦\",\"⠧\",\"⠇\",\"⠏\"]},\"dots2\":{\"interval\":80,\"frames\":[\"⣾\",\"⣽\",\"⣻\",\"⢿\",\"⡿\",\"⣟\",\"⣯\",\"⣷\"]},\"dots3\":{\"interval\":80,\"frames\":[\"⠋\",\"⠙\",\"⠚\",\"⠞\",\"⠖\",\"⠦\",\"⠴\",\"⠲\",\"⠳\",\"⠓\"]},\"dots4\":{\"interval\":80,\"frames\":[\"⠄\",\"⠆\",\"⠇\",\"⠋\",\"⠙\",\"⠸\",\"⠰\",\"⠠\",\"⠰\",\"⠸\",\"⠙\",\"⠋\",\"⠇\",\"⠆\"]},\"dots5\":{\"interval\":80,\"frames\":[\"⠋\",\"⠙\",\"⠚\",\"⠒\",\"⠂\",\"⠂\",\"⠒\",\"⠲\",\"⠴\",\"⠦\",\"⠖\",\"⠒\",\"⠐\",\"⠐\",\"⠒\",\"⠓\",\"⠋\"]},\"dots6\":{\"interval\":80,\"frames\":[\"⠁\",\"⠉\",\"⠙\",\"⠚\",\"⠒\",\"⠂\",\"⠂\",\"⠒\",\"⠲\",\"⠴\",\"⠤\",\"⠄\",\"⠄\",\"⠤\",\"⠴\",\"⠲\",\"⠒\",\"⠂\",\"⠂\",\"⠒\",\"⠚\",\"⠙\",\"⠉\",\"⠁\"]},\"dots7\":{\"interval\":80,\"frames\":[\"⠈\",\"⠉\",\"⠋\",\"⠓\",\"⠒\",\"⠐\",\"⠐\",\"⠒\",\"⠖\",\"⠦\",\"⠤\",\"⠠\",\"⠠\",\"⠤\",\"⠦\",\"⠖\",\"⠒\",\"⠐\",\"⠐\",\"⠒\",\"⠓\",\"⠋\",\"⠉\",\"⠈\"]},\"dots8\":{\"interval\":80,\"frames\":[\"⠁\",\"⠁\",\"⠉\",\"⠙\",\"⠚\",\"⠒\",\"⠂\",\"⠂\",\"⠒\",\"⠲\",\"⠴\",\"⠤\",\"⠄\",\"⠄\",\"⠤\",\"⠠\",\"⠠\",\"⠤\",\"⠦\",\"⠖\",\"⠒\",\"⠐\",\"⠐\",\"⠒\",\"⠓\",\"⠋\",\"⠉\",\"⠈\",\"⠈\"]},\"dots9\":{\"interval\":80,\"frames\":[\"⢹\",\"⢺\",\"⢼\",\"⣸\",\"⣇\",\"⡧\",\"⡗\",\"⡏\"]},\"dots10\":{\"interval\":80,\"frames\":[\"⢄\",\"⢂\",\"⢁\",\"⡁\",\"⡈\",\"⡐\",\"⡠\"]},\"dots11\":{\"interval\":100,\"frames\":[\"⠁\",\"⠂\",\"⠄\",\"⡀\",\"⢀\",\"⠠\",\"⠐\",\"⠈\"]},\"dots12\":{\"interval\":80,\"frames\":[\"⢀⠀\",\"⡀⠀\",\"⠄⠀\",\"⢂⠀\",\"⡂⠀\",\"⠅⠀\",\"⢃⠀\",\"⡃⠀\",\"⠍⠀\",\"⢋⠀\",\"⡋⠀\",\"⠍⠁\",\"⢋⠁\",\"⡋⠁\",\"⠍⠉\",\"⠋⠉\",\"⠋⠉\",\"⠉⠙\",\"⠉⠙\",\"⠉⠩\",\"⠈⢙\",\"⠈⡙\",\"⢈⠩\",\"⡀⢙\",\"⠄⡙\",\"⢂⠩\",\"⡂⢘\",\"⠅⡘\",\"⢃⠨\",\"⡃⢐\",\"⠍⡐\",\"⢋⠠\",\"⡋⢀\",\"⠍⡁\",\"⢋⠁\",\"⡋⠁\",\"⠍⠉\",\"⠋⠉\",\"⠋⠉\",\"⠉⠙\",\"⠉⠙\",\"⠉⠩\",\"⠈⢙\",\"⠈⡙\",\"⠈⠩\",\"⠀⢙\",\"⠀⡙\",\"⠀⠩\",\"⠀⢘\",\"⠀⡘\",\"⠀⠨\",\"⠀⢐\",\"⠀⡐\",\"⠀⠠\",\"⠀⢀\",\"⠀⡀\"]},\"line\":{\"interval\":130,\"frames\":[\"-\",\"\\\\\",\"|\",\"/\"]},\"line2\":{\"interval\":100,\"frames\":[\"⠂\",\"-\",\"–\",\"—\",\"–\",\"-\"]},\"pipe\":{\"interval\":100,\"frames\":[\"┤\",\"┘\",\"┴\",\"└\",\"├\",\"┌\",\"┬\",\"┐\"]},\"simpleDots\":{\"interval\":400,\"frames\":[\". \",\".. \",\"...\",\" \"]},\"simpleDotsScrolling\":{\"interval\":200,\"frames\":[\". \",\".. \",\"...\",\" ..\",\" .\",\" \"]},\"star\":{\"interval\":70,\"frames\":[\"✶\",\"✸\",\"✹\",\"✺\",\"✹\",\"✷\"]},\"star2\":{\"interval\":80,\"frames\":[\"+\",\"x\",\"*\"]},\"flip\":{\"interval\":70,\"frames\":[\"_\",\"_\",\"_\",\"-\",\"`\",\"`\",\"'\",\"´\",\"-\",\"_\",\"_\",\"_\"]},\"hamburger\":{\"interval\":100,\"frames\":[\"☱\",\"☲\",\"☴\"]},\"growVertical\":{\"interval\":120,\"frames\":[\"▁\",\"▃\",\"▄\",\"▅\",\"▆\",\"▇\",\"▆\",\"▅\",\"▄\",\"▃\"]},\"growHorizontal\":{\"interval\":120,\"frames\":[\"▏\",\"▎\",\"▍\",\"▌\",\"▋\",\"▊\",\"▉\",\"▊\",\"▋\",\"▌\",\"▍\",\"▎\"]},\"balloon\":{\"interval\":140,\"frames\":[\" \",\".\",\"o\",\"O\",\"@\",\"*\",\" \"]},\"balloon2\":{\"interval\":120,\"frames\":[\".\",\"o\",\"O\",\"°\",\"O\",\"o\",\".\"]},\"noise\":{\"interval\":100,\"frames\":[\"▓\",\"▒\",\"░\"]},\"bounce\":{\"interval\":120,\"frames\":[\"⠁\",\"⠂\",\"⠄\",\"⠂\"]},\"boxBounce\":{\"interval\":120,\"frames\":[\"▖\",\"▘\",\"▝\",\"▗\"]},\"boxBounce2\":{\"interval\":100,\"frames\":[\"▌\",\"▀\",\"▐\",\"▄\"]},\"triangle\":{\"interval\":50,\"frames\":[\"◢\",\"◣\",\"◤\",\"◥\"]},\"arc\":{\"interval\":100,\"frames\":[\"◜\",\"◠\",\"◝\",\"◞\",\"◡\",\"◟\"]},\"circle\":{\"interval\":120,\"frames\":[\"◡\",\"⊙\",\"◠\"]},\"squareCorners\":{\"interval\":180,\"frames\":[\"◰\",\"◳\",\"◲\",\"◱\"]},\"circleQuarters\":{\"interval\":120,\"frames\":[\"◴\",\"◷\",\"◶\",\"◵\"]},\"circleHalves\":{\"interval\":50,\"frames\":[\"◐\",\"◓\",\"◑\",\"◒\"]},\"squish\":{\"interval\":100,\"frames\":[\"╫\",\"╪\"]},\"toggle\":{\"interval\":250,\"frames\":[\"⊶\",\"⊷\"]},\"toggle2\":{\"interval\":80,\"frames\":[\"▫\",\"▪\"]},\"toggle3\":{\"interval\":120,\"frames\":[\"□\",\"■\"]},\"toggle4\":{\"interval\":100,\"frames\":[\"■\",\"□\",\"▪\",\"▫\"]},\"toggle5\":{\"interval\":100,\"frames\":[\"▮\",\"▯\"]},\"toggle6\":{\"interval\":300,\"frames\":[\"ဝ\",\"၀\"]},\"toggle7\":{\"interval\":80,\"frames\":[\"⦾\",\"⦿\"]},\"toggle8\":{\"interval\":100,\"frames\":[\"◍\",\"◌\"]},\"toggle9\":{\"interval\":100,\"frames\":[\"◉\",\"◎\"]},\"toggle10\":{\"interval\":100,\"frames\":[\"㊂\",\"㊀\",\"㊁\"]},\"toggle11\":{\"interval\":50,\"frames\":[\"⧇\",\"⧆\"]},\"toggle12\":{\"interval\":120,\"frames\":[\"☗\",\"☖\"]},\"toggle13\":{\"interval\":80,\"frames\":[\"=\",\"*\",\"-\"]},\"arrow\":{\"interval\":100,\"frames\":[\"←\",\"↖\",\"↑\",\"↗\",\"→\",\"↘\",\"↓\",\"↙\"]},\"arrow2\":{\"interval\":80,\"frames\":[\"⬆️ \",\"↗️ \",\"➡️ \",\"↘️ \",\"⬇️ \",\"↙️ \",\"⬅️ \",\"↖️ \"]},\"arrow3\":{\"interval\":120,\"frames\":[\"▹▹▹▹▹\",\"▸▹▹▹▹\",\"▹▸▹▹▹\",\"▹▹▸▹▹\",\"▹▹▹▸▹\",\"▹▹▹▹▸\"]},\"bouncingBar\":{\"interval\":80,\"frames\":[\"[ ]\",\"[= ]\",\"[== ]\",\"[=== ]\",\"[ ===]\",\"[ ==]\",\"[ =]\",\"[ ]\",\"[ =]\",\"[ ==]\",\"[ ===]\",\"[====]\",\"[=== ]\",\"[== ]\",\"[= ]\"]},\"bouncingBall\":{\"interval\":80,\"frames\":[\"( ● )\",\"( ● )\",\"( ● )\",\"( ● )\",\"( ●)\",\"( ● )\",\"( ● )\",\"( ● )\",\"( ● )\",\"(● )\"]},\"smiley\":{\"interval\":200,\"frames\":[\"😄 \",\"😝 \"]},\"monkey\":{\"interval\":300,\"frames\":[\"🙈 \",\"🙈 \",\"🙉 \",\"🙊 \"]},\"hearts\":{\"interval\":100,\"frames\":[\"💛 \",\"💙 \",\"💜 \",\"💚 \",\"❤️ \"]},\"clock\":{\"interval\":100,\"frames\":[\"🕐 \",\"🕑 \",\"🕒 \",\"🕓 \",\"🕔 \",\"🕕 \",\"🕖 \",\"🕗 \",\"🕘 \",\"🕙 \",\"🕚 \"]},\"earth\":{\"interval\":180,\"frames\":[\"🌍 \",\"🌎 \",\"🌏 \"]},\"moon\":{\"interval\":80,\"frames\":[\"🌑 \",\"🌒 \",\"🌓 \",\"🌔 \",\"🌕 \",\"🌖 \",\"🌗 \",\"🌘 \"]},\"runner\":{\"interval\":140,\"frames\":[\"🚶 \",\"🏃 \"]},\"pong\":{\"interval\":80,\"frames\":[\"▐⠂ ▌\",\"▐⠈ ▌\",\"▐ ⠂ ▌\",\"▐ ⠠ ▌\",\"▐ ⡀ ▌\",\"▐ ⠠ ▌\",\"▐ ⠂ ▌\",\"▐ ⠈ ▌\",\"▐ ⠂ ▌\",\"▐ ⠠ ▌\",\"▐ ⡀ ▌\",\"▐ ⠠ ▌\",\"▐ ⠂ ▌\",\"▐ ⠈ ▌\",\"▐ ⠂▌\",\"▐ ⠠▌\",\"▐ ⡀▌\",\"▐ ⠠ ▌\",\"▐ ⠂ ▌\",\"▐ ⠈ ▌\",\"▐ ⠂ ▌\",\"▐ ⠠ ▌\",\"▐ ⡀ ▌\",\"▐ ⠠ ▌\",\"▐ ⠂ ▌\",\"▐ ⠈ ▌\",\"▐ ⠂ ▌\",\"▐ ⠠ ▌\",\"▐ ⡀ ▌\",\"▐⠠ ▌\"]},\"shark\":{\"interval\":120,\"frames\":[\"▐|\\\\____________▌\",\"▐_|\\\\___________▌\",\"▐__|\\\\__________▌\",\"▐___|\\\\_________▌\",\"▐____|\\\\________▌\",\"▐_____|\\\\_______▌\",\"▐______|\\\\______▌\",\"▐_______|\\\\_____▌\",\"▐________|\\\\____▌\",\"▐_________|\\\\___▌\",\"▐__________|\\\\__▌\",\"▐___________|\\\\_▌\",\"▐____________|\\\\▌\",\"▐____________/|▌\",\"▐___________/|_▌\",\"▐__________/|__▌\",\"▐_________/|___▌\",\"▐________/|____▌\",\"▐_______/|_____▌\",\"▐______/|______▌\",\"▐_____/|_______▌\",\"▐____/|________▌\",\"▐___/|_________▌\",\"▐__/|__________▌\",\"▐_/|___________▌\",\"▐/|____________▌\"]},\"dqpb\":{\"interval\":100,\"frames\":[\"d\",\"q\",\"p\",\"b\"]},\"weather\":{\"interval\":100,\"frames\":[\"☀️ \",\"☀️ \",\"☀️ \",\"🌤 \",\"⛅️ \",\"🌥 \",\"☁️ \",\"🌧 \",\"🌨 \",\"🌧 \",\"🌨 \",\"🌧 \",\"🌨 \",\"⛈ \",\"🌨 \",\"🌧 \",\"🌨 \",\"☁️ \",\"🌥 \",\"⛅️ \",\"🌤 \",\"☀️ \",\"☀️ \"]},\"christmas\":{\"interval\":400,\"frames\":[\"🌲\",\"🎄\"]}}"); + if (index != -1) { + return allChildren[index]; + } + allParents.push(parent); + allChildren.push(child); + } -/***/ }), -/* 391 */ -/***/ (function(module, exports, __webpack_require__) { + for (var i in parent) { + var attrs; + if (proto) { + attrs = Object.getOwnPropertyDescriptor(proto, i); + } -"use strict"; + if (attrs && attrs.set == null) { + continue; + } + child[i] = _clone(parent[i], depth - 1); + } -const chalk = __webpack_require__(392); + return child; + } -const isSupported = process.platform !== 'win32' || process.env.CI || process.env.TERM === 'xterm-256color'; + return _clone(parent, depth); +} -const main = { - info: chalk.blue('ℹ'), - success: chalk.green('✔'), - warning: chalk.yellow('⚠'), - error: chalk.red('✖') +/** + * Simple flat clone using prototype, accepts only objects, usefull for property + * override on FLAT configuration object (no nested props). + * + * USE WITH CAUTION! This may not behave as you wish if you do not know how this + * works. + */ +clone.clonePrototype = function clonePrototype(parent) { + if (parent === null) + return null; + + var c = function () {}; + c.prototype = parent; + return new c(); }; -const fallbacks = { - info: chalk.blue('i'), - success: chalk.green('√'), - warning: chalk.yellow('‼'), - error: chalk.red('×') +// private utility functions + +function __objToStr(o) { + return Object.prototype.toString.call(o); }; +clone.__objToStr = __objToStr; -module.exports = isSupported ? main : fallbacks; +function __isDate(o) { + return typeof o === 'object' && __objToStr(o) === '[object Date]'; +}; +clone.__isDate = __isDate; + +function __isArray(o) { + return typeof o === 'object' && __objToStr(o) === '[object Array]'; +}; +clone.__isArray = __isArray; + +function __isRegExp(o) { + return typeof o === 'object' && __objToStr(o) === '[object RegExp]'; +}; +clone.__isRegExp = __isRegExp; + +function __getRegExpFlags(re) { + var flags = ''; + if (re.global) flags += 'g'; + if (re.ignoreCase) flags += 'i'; + if (re.multiline) flags += 'm'; + return flags; +}; +clone.__getRegExpFlags = __getRegExpFlags; + +return clone; +})(); + +if ( true && module.exports) { + module.exports = clone; +} /***/ }), -/* 392 */ +/* 396 */ +/***/ (function(module, exports) { + +module.exports = [ + [ 0x0300, 0x036F ], [ 0x0483, 0x0486 ], [ 0x0488, 0x0489 ], + [ 0x0591, 0x05BD ], [ 0x05BF, 0x05BF ], [ 0x05C1, 0x05C2 ], + [ 0x05C4, 0x05C5 ], [ 0x05C7, 0x05C7 ], [ 0x0600, 0x0603 ], + [ 0x0610, 0x0615 ], [ 0x064B, 0x065E ], [ 0x0670, 0x0670 ], + [ 0x06D6, 0x06E4 ], [ 0x06E7, 0x06E8 ], [ 0x06EA, 0x06ED ], + [ 0x070F, 0x070F ], [ 0x0711, 0x0711 ], [ 0x0730, 0x074A ], + [ 0x07A6, 0x07B0 ], [ 0x07EB, 0x07F3 ], [ 0x0901, 0x0902 ], + [ 0x093C, 0x093C ], [ 0x0941, 0x0948 ], [ 0x094D, 0x094D ], + [ 0x0951, 0x0954 ], [ 0x0962, 0x0963 ], [ 0x0981, 0x0981 ], + [ 0x09BC, 0x09BC ], [ 0x09C1, 0x09C4 ], [ 0x09CD, 0x09CD ], + [ 0x09E2, 0x09E3 ], [ 0x0A01, 0x0A02 ], [ 0x0A3C, 0x0A3C ], + [ 0x0A41, 0x0A42 ], [ 0x0A47, 0x0A48 ], [ 0x0A4B, 0x0A4D ], + [ 0x0A70, 0x0A71 ], [ 0x0A81, 0x0A82 ], [ 0x0ABC, 0x0ABC ], + [ 0x0AC1, 0x0AC5 ], [ 0x0AC7, 0x0AC8 ], [ 0x0ACD, 0x0ACD ], + [ 0x0AE2, 0x0AE3 ], [ 0x0B01, 0x0B01 ], [ 0x0B3C, 0x0B3C ], + [ 0x0B3F, 0x0B3F ], [ 0x0B41, 0x0B43 ], [ 0x0B4D, 0x0B4D ], + [ 0x0B56, 0x0B56 ], [ 0x0B82, 0x0B82 ], [ 0x0BC0, 0x0BC0 ], + [ 0x0BCD, 0x0BCD ], [ 0x0C3E, 0x0C40 ], [ 0x0C46, 0x0C48 ], + [ 0x0C4A, 0x0C4D ], [ 0x0C55, 0x0C56 ], [ 0x0CBC, 0x0CBC ], + [ 0x0CBF, 0x0CBF ], [ 0x0CC6, 0x0CC6 ], [ 0x0CCC, 0x0CCD ], + [ 0x0CE2, 0x0CE3 ], [ 0x0D41, 0x0D43 ], [ 0x0D4D, 0x0D4D ], + [ 0x0DCA, 0x0DCA ], [ 0x0DD2, 0x0DD4 ], [ 0x0DD6, 0x0DD6 ], + [ 0x0E31, 0x0E31 ], [ 0x0E34, 0x0E3A ], [ 0x0E47, 0x0E4E ], + [ 0x0EB1, 0x0EB1 ], [ 0x0EB4, 0x0EB9 ], [ 0x0EBB, 0x0EBC ], + [ 0x0EC8, 0x0ECD ], [ 0x0F18, 0x0F19 ], [ 0x0F35, 0x0F35 ], + [ 0x0F37, 0x0F37 ], [ 0x0F39, 0x0F39 ], [ 0x0F71, 0x0F7E ], + [ 0x0F80, 0x0F84 ], [ 0x0F86, 0x0F87 ], [ 0x0F90, 0x0F97 ], + [ 0x0F99, 0x0FBC ], [ 0x0FC6, 0x0FC6 ], [ 0x102D, 0x1030 ], + [ 0x1032, 0x1032 ], [ 0x1036, 0x1037 ], [ 0x1039, 0x1039 ], + [ 0x1058, 0x1059 ], [ 0x1160, 0x11FF ], [ 0x135F, 0x135F ], + [ 0x1712, 0x1714 ], [ 0x1732, 0x1734 ], [ 0x1752, 0x1753 ], + [ 0x1772, 0x1773 ], [ 0x17B4, 0x17B5 ], [ 0x17B7, 0x17BD ], + [ 0x17C6, 0x17C6 ], [ 0x17C9, 0x17D3 ], [ 0x17DD, 0x17DD ], + [ 0x180B, 0x180D ], [ 0x18A9, 0x18A9 ], [ 0x1920, 0x1922 ], + [ 0x1927, 0x1928 ], [ 0x1932, 0x1932 ], [ 0x1939, 0x193B ], + [ 0x1A17, 0x1A18 ], [ 0x1B00, 0x1B03 ], [ 0x1B34, 0x1B34 ], + [ 0x1B36, 0x1B3A ], [ 0x1B3C, 0x1B3C ], [ 0x1B42, 0x1B42 ], + [ 0x1B6B, 0x1B73 ], [ 0x1DC0, 0x1DCA ], [ 0x1DFE, 0x1DFF ], + [ 0x200B, 0x200F ], [ 0x202A, 0x202E ], [ 0x2060, 0x2063 ], + [ 0x206A, 0x206F ], [ 0x20D0, 0x20EF ], [ 0x302A, 0x302F ], + [ 0x3099, 0x309A ], [ 0xA806, 0xA806 ], [ 0xA80B, 0xA80B ], + [ 0xA825, 0xA826 ], [ 0xFB1E, 0xFB1E ], [ 0xFE00, 0xFE0F ], + [ 0xFE20, 0xFE23 ], [ 0xFEFF, 0xFEFF ], [ 0xFFF9, 0xFFFB ], + [ 0x10A01, 0x10A03 ], [ 0x10A05, 0x10A06 ], [ 0x10A0C, 0x10A0F ], + [ 0x10A38, 0x10A3A ], [ 0x10A3F, 0x10A3F ], [ 0x1D167, 0x1D169 ], + [ 0x1D173, 0x1D182 ], [ 0x1D185, 0x1D18B ], [ 0x1D1AA, 0x1D1AD ], + [ 0x1D242, 0x1D244 ], [ 0xE0001, 0xE0001 ], [ 0xE0020, 0xE007F ], + [ 0xE0100, 0xE01EF ] +] + + +/***/ }), +/* 397 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const escapeStringRegexp = __webpack_require__(178); -const ansiStyles = __webpack_require__(393); -const stdoutColor = __webpack_require__(184).stdout; -const template = __webpack_require__(394); +module.exports = ({stream = process.stdout} = {}) => { + return Boolean( + stream && stream.isTTY && + process.env.TERM !== 'dumb' && + !('CI' in process.env) + ); +}; -const isSimpleWindowsTerm = process.platform === 'win32' && !(process.env.TERM || '').toLowerCase().startsWith('xterm'); -// `supportsColor.level` → `ansiStyles.color[name]` mapping -const levelMapping = ['ansi', 'ansi', 'ansi256', 'ansi16m']; +/***/ }), +/* 398 */ +/***/ (function(module, exports, __webpack_require__) { -// `color-convert` models to exclude from the Chalk API due to conflicts and such -const skipModels = new Set(['gray']); +var Stream = __webpack_require__(138) -const styles = Object.create(null); +module.exports = MuteStream -function applyOptions(obj, options) { - options = options || {}; +// var out = new MuteStream(process.stdout) +// argument auto-pipes +function MuteStream (opts) { + Stream.apply(this) + opts = opts || {} + this.writable = this.readable = true + this.muted = false + this.on('pipe', this._onpipe) + this.replace = opts.replace - // Detect level if not set manually - const scLevel = stdoutColor ? stdoutColor.level : 0; - obj.level = options.level === undefined ? scLevel : options.level; - obj.enabled = 'enabled' in options ? options.enabled : obj.level > 0; + // For readline-type situations + // This much at the start of a line being redrawn after a ctrl char + // is seen (such as backspace) won't be redrawn as the replacement + this._prompt = opts.prompt || null + this._hadControl = false } -function Chalk(options) { - // We check for this.template here since calling `chalk.constructor()` - // by itself will have a `this` of a previously constructed chalk object - if (!this || !(this instanceof Chalk) || this.template) { - const chalk = {}; - applyOptions(chalk, options); +MuteStream.prototype = Object.create(Stream.prototype) - chalk.template = function () { - const args = [].slice.call(arguments); - return chalkTag.apply(null, [chalk.template].concat(args)); - }; +Object.defineProperty(MuteStream.prototype, 'constructor', { + value: MuteStream, + enumerable: false +}) - Object.setPrototypeOf(chalk, Chalk.prototype); - Object.setPrototypeOf(chalk.template, chalk); +MuteStream.prototype.mute = function () { + this.muted = true +} - chalk.template.constructor = Chalk; +MuteStream.prototype.unmute = function () { + this.muted = false +} - return chalk.template; - } +Object.defineProperty(MuteStream.prototype, '_onpipe', { + value: onPipe, + enumerable: false, + writable: true, + configurable: true +}) - applyOptions(this, options); +function onPipe (src) { + this._src = src } -// Use bright blue on Windows as the normal blue color is illegible -if (isSimpleWindowsTerm) { - ansiStyles.blue.open = '\u001B[94m'; -} +Object.defineProperty(MuteStream.prototype, 'isTTY', { + get: getIsTTY, + set: setIsTTY, + enumerable: true, + configurable: true +}) -for (const key of Object.keys(ansiStyles)) { - ansiStyles[key].closeRe = new RegExp(escapeStringRegexp(ansiStyles[key].close), 'g'); +function getIsTTY () { + return( (this._dest) ? this._dest.isTTY + : (this._src) ? this._src.isTTY + : false + ) +} - styles[key] = { - get() { - const codes = ansiStyles[key]; - return build.call(this, this._styles ? this._styles.concat(codes) : [codes], this._empty, key); - } - }; +// basically just get replace the getter/setter with a regular value +function setIsTTY (isTTY) { + Object.defineProperty(this, 'isTTY', { + value: isTTY, + enumerable: true, + writable: true, + configurable: true + }) } -styles.visible = { - get() { - return build.call(this, this._styles || [], true, 'visible'); - } -}; +Object.defineProperty(MuteStream.prototype, 'rows', { + get: function () { + return( this._dest ? this._dest.rows + : this._src ? this._src.rows + : undefined ) + }, enumerable: true, configurable: true }) -ansiStyles.color.closeRe = new RegExp(escapeStringRegexp(ansiStyles.color.close), 'g'); -for (const model of Object.keys(ansiStyles.color.ansi)) { - if (skipModels.has(model)) { - continue; - } +Object.defineProperty(MuteStream.prototype, 'columns', { + get: function () { + return( this._dest ? this._dest.columns + : this._src ? this._src.columns + : undefined ) + }, enumerable: true, configurable: true }) - styles[model] = { - get() { - const level = this.level; - return function () { - const open = ansiStyles.color[levelMapping[level]][model].apply(null, arguments); - const codes = { - open, - close: ansiStyles.color.close, - closeRe: ansiStyles.color.closeRe - }; - return build.call(this, this._styles ? this._styles.concat(codes) : [codes], this._empty, model); - }; - } - }; + +MuteStream.prototype.pipe = function (dest, options) { + this._dest = dest + return Stream.prototype.pipe.call(this, dest, options) } -ansiStyles.bgColor.closeRe = new RegExp(escapeStringRegexp(ansiStyles.bgColor.close), 'g'); -for (const model of Object.keys(ansiStyles.bgColor.ansi)) { - if (skipModels.has(model)) { - continue; - } +MuteStream.prototype.pause = function () { + if (this._src) return this._src.pause() +} - const bgModel = 'bg' + model[0].toUpperCase() + model.slice(1); - styles[bgModel] = { - get() { - const level = this.level; - return function () { - const open = ansiStyles.bgColor[levelMapping[level]][model].apply(null, arguments); - const codes = { - open, - close: ansiStyles.bgColor.close, - closeRe: ansiStyles.bgColor.closeRe - }; - return build.call(this, this._styles ? this._styles.concat(codes) : [codes], this._empty, model); - }; - } - }; +MuteStream.prototype.resume = function () { + if (this._src) return this._src.resume() } -const proto = Object.defineProperties(() => {}, styles); +MuteStream.prototype.write = function (c) { + if (this.muted) { + if (!this.replace) return true + if (c.match(/^\u001b/)) { + if(c.indexOf(this._prompt) === 0) { + c = c.substr(this._prompt.length); + c = c.replace(/./g, this.replace); + c = this._prompt + c; + } + this._hadControl = true + return this.emit('data', c) + } else { + if (this._prompt && this._hadControl && + c.indexOf(this._prompt) === 0) { + this._hadControl = false + this.emit('data', this._prompt) + c = c.substr(this._prompt.length) + } + c = c.toString().replace(/./g, this.replace) + } + } + this.emit('data', c) +} -function build(_styles, _empty, key) { - const builder = function () { - return applyStyle.apply(builder, arguments); - }; +MuteStream.prototype.end = function (c) { + if (this.muted) { + if (c && this.replace) { + c = c.toString().replace(/./g, this.replace) + } else { + c = null + } + } + if (c) this.emit('data', c) + this.emit('end') +} - builder._styles = _styles; - builder._empty = _empty; +function proxy (fn) { return function () { + var d = this._dest + var s = this._src + if (d && d[fn]) d[fn].apply(d, arguments) + if (s && s[fn]) s[fn].apply(s, arguments) +}} - const self = this; +MuteStream.prototype.destroy = proxy('destroy') +MuteStream.prototype.destroySoon = proxy('destroySoon') +MuteStream.prototype.close = proxy('close') - Object.defineProperty(builder, 'level', { - enumerable: true, - get() { - return self.level; - }, - set(level) { - self.level = level; - } - }); - Object.defineProperty(builder, 'enabled', { - enumerable: true, - get() { - return self.enabled; - }, - set(enabled) { - self.enabled = enabled; - } - }); +/***/ }), +/* 399 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { - // See below for fix regarding invisible grey/dim combination on Windows - builder.hasGrey = this.hasGrey || key === 'gray' || key === 'grey'; +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "RunCommand", function() { return RunCommand; }); +/* harmony import */ var _utils_errors__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(163); +/* harmony import */ var _utils_log__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(144); +/* harmony import */ var _utils_parallelize__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(145); +/* harmony import */ var _utils_projects__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(146); +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ - // `__proto__` is used because we must return a function, but there is - // no way to create a function with a different prototype - builder.__proto__ = proto; // eslint-disable-line no-proto - return builder; -} -function applyStyle() { - // Support varags, but simply cast to string in case there's only one arg - const args = arguments; - const argsLen = args.length; - let str = String(arguments[0]); - if (argsLen === 0) { - return ''; - } +const RunCommand = { + description: 'Run script defined in package.json in each package that contains that script.', + name: 'run', - if (argsLen > 1) { - // Don't slice `arguments`, it prevents V8 optimizations - for (let a = 1; a < argsLen; a++) { - str += ' ' + args[a]; - } - } + async run(projects, projectGraph, { + extraArgs + }) { + const batchedProjects = Object(_utils_projects__WEBPACK_IMPORTED_MODULE_3__["topologicallyBatchProjects"])(projects, projectGraph); - if (!this.enabled || this.level <= 0 || !str) { - return this._empty ? '' : str; - } + if (extraArgs.length === 0) { + throw new _utils_errors__WEBPACK_IMPORTED_MODULE_0__["CliError"]('No script specified'); + } - // Turns out that on Windows dimmed gray text becomes invisible in cmd.exe, - // see https://github.com/chalk/chalk/issues/58 - // If we're on Windows and we're dealing with a gray color, temporarily make 'dim' a noop. - const originalDim = ansiStyles.dim.open; - if (isSimpleWindowsTerm && this.hasGrey) { - ansiStyles.dim.open = ''; - } + const scriptName = extraArgs[0]; + const scriptArgs = extraArgs.slice(1); + await Object(_utils_parallelize__WEBPACK_IMPORTED_MODULE_2__["parallelizeBatches"])(batchedProjects, async project => { + if (project.hasScript(scriptName)) { + _utils_log__WEBPACK_IMPORTED_MODULE_1__["log"].info(`[${project.name}] running "${scriptName}" script`); + await project.runScriptStreaming(scriptName, { + args: scriptArgs + }); + _utils_log__WEBPACK_IMPORTED_MODULE_1__["log"].success(`[${project.name}] complete`); + } + }); + } - for (const code of this._styles.slice().reverse()) { - // Replace any instances already present with a re-opening code - // otherwise only the part of the string until said closing code - // will be colored, and the rest will simply be 'plain'. - str = code.open + str.replace(code.closeRe, code.open) + code.close; +}; - // Close the styling before a linebreak and reopen - // after next line to fix a bleed issue on macOS - // https://github.com/chalk/chalk/pull/92 - str = str.replace(/\r?\n/g, `${code.close}$&${code.open}`); - } +/***/ }), +/* 400 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { - // Reset the original `dim` if we changed it to work around the Windows dimmed gray issue - ansiStyles.dim.open = originalDim; +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "WatchCommand", function() { return WatchCommand; }); +/* harmony import */ var _utils_errors__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(163); +/* harmony import */ var _utils_log__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(144); +/* harmony import */ var _utils_parallelize__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(145); +/* harmony import */ var _utils_projects__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(146); +/* harmony import */ var _utils_watch__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(401); +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ - return str; -} -function chalkTag(chalk, strings) { - if (!Array.isArray(strings)) { - // If chalk() was called by itself or with a string, - // return the string itself as a string. - return [].slice.call(arguments, 1).join(' '); - } - const args = [].slice.call(arguments, 2); - const parts = [strings.raw[0]]; - for (let i = 1; i < strings.length; i++) { - parts.push(String(args[i - 1]).replace(/[{}\\]/g, '\\$&')); - parts.push(String(strings.raw[i])); - } - return template(chalk, parts.join('')); -} -Object.defineProperties(Chalk.prototype, styles); +/** + * Name of the script in the package/project package.json file to run during `kbn watch`. + */ +const watchScriptName = 'kbn:watch'; +/** + * Name of the Kibana project. + */ -module.exports = Chalk(); // eslint-disable-line new-cap -module.exports.supportsColor = stdoutColor; -module.exports.default = module.exports; // For TypeScript +const kibanaProjectName = 'kibana'; +/** + * Command that traverses through list of available projects/packages that have `kbn:watch` script in their + * package.json files, groups them into topology aware batches and then processes theses batches one by one + * running `kbn:watch` scripts in parallel within the same batch. + * + * Command internally relies on the fact that most of the build systems that are triggered by `kbn:watch` + * will emit special "marker" once build/watch process is ready that we can use as completion condition for + * the `kbn:watch` script and eventually for the entire batch. Currently we support completion "markers" for + * `webpack` and `tsc` only, for the rest we rely on predefined timeouts. + */ +const WatchCommand = { + description: 'Runs `kbn:watch` script for every project.', + name: 'watch', -/***/ }), -/* 393 */ -/***/ (function(module, exports, __webpack_require__) { + async run(projects, projectGraph) { + const projectsToWatch = new Map(); -"use strict"; -/* WEBPACK VAR INJECTION */(function(module) { -const colorConvert = __webpack_require__(180); + for (const project of projects.values()) { + // We can't watch project that doesn't have `kbn:watch` script. + if (project.hasScript(watchScriptName)) { + projectsToWatch.set(project.name, project); + } + } -const wrapAnsi16 = (fn, offset) => function () { - const code = fn.apply(colorConvert, arguments); - return `\u001B[${code + offset}m`; -}; + if (projectsToWatch.size === 0) { + throw new _utils_errors__WEBPACK_IMPORTED_MODULE_0__["CliError"](`There are no projects to watch found. Make sure that projects define 'kbn:watch' script in 'package.json'.`); + } -const wrapAnsi256 = (fn, offset) => function () { - const code = fn.apply(colorConvert, arguments); - return `\u001B[${38 + offset};5;${code}m`; -}; + const projectNames = Array.from(projectsToWatch.keys()); + _utils_log__WEBPACK_IMPORTED_MODULE_1__["log"].info(`Running ${watchScriptName} scripts for [${projectNames.join(', ')}].`); // Kibana should always be run the last, so we don't rely on automatic + // topological batching and push it to the last one-entry batch manually. + + const shouldWatchKibanaProject = projectsToWatch.delete(kibanaProjectName); + const batchedProjects = Object(_utils_projects__WEBPACK_IMPORTED_MODULE_3__["topologicallyBatchProjects"])(projectsToWatch, projectGraph); + + if (shouldWatchKibanaProject) { + batchedProjects.push([projects.get(kibanaProjectName)]); + } + + await Object(_utils_parallelize__WEBPACK_IMPORTED_MODULE_2__["parallelizeBatches"])(batchedProjects, async pkg => { + const completionHint = await Object(_utils_watch__WEBPACK_IMPORTED_MODULE_4__["waitUntilWatchIsReady"])(pkg.runScriptStreaming(watchScriptName, { + debug: false + }).stdout); + _utils_log__WEBPACK_IMPORTED_MODULE_1__["log"].success(`[${pkg.name}] Initial build completed (${completionHint}).`); + }); + } -const wrapAnsi16m = (fn, offset) => function () { - const rgb = fn.apply(colorConvert, arguments); - return `\u001B[${38 + offset};2;${rgb[0]};${rgb[1]};${rgb[2]}m`; }; -function assembleStyles() { - const codes = new Map(); - const styles = { - modifier: { - reset: [0, 0], - // 21 isn't widely supported and 22 does the same thing - bold: [1, 22], - dim: [2, 22], - italic: [3, 23], - underline: [4, 24], - inverse: [7, 27], - hidden: [8, 28], - strikethrough: [9, 29] - }, - color: { - black: [30, 39], - red: [31, 39], - green: [32, 39], - yellow: [33, 39], - blue: [34, 39], - magenta: [35, 39], - cyan: [36, 39], - white: [37, 39], - gray: [90, 39], - - // Bright color - redBright: [91, 39], - greenBright: [92, 39], - yellowBright: [93, 39], - blueBright: [94, 39], - magentaBright: [95, 39], - cyanBright: [96, 39], - whiteBright: [97, 39] - }, - bgColor: { - bgBlack: [40, 49], - bgRed: [41, 49], - bgGreen: [42, 49], - bgYellow: [43, 49], - bgBlue: [44, 49], - bgMagenta: [45, 49], - bgCyan: [46, 49], - bgWhite: [47, 49], - - // Bright color - bgBlackBright: [100, 49], - bgRedBright: [101, 49], - bgGreenBright: [102, 49], - bgYellowBright: [103, 49], - bgBlueBright: [104, 49], - bgMagentaBright: [105, 49], - bgCyanBright: [106, 49], - bgWhiteBright: [107, 49] - } - }; - - // Fix humans - styles.color.grey = styles.color.gray; - - for (const groupName of Object.keys(styles)) { - const group = styles[groupName]; - - for (const styleName of Object.keys(group)) { - const style = group[styleName]; - - styles[styleName] = { - open: `\u001B[${style[0]}m`, - close: `\u001B[${style[1]}m` - }; - - group[styleName] = styles[styleName]; - - codes.set(style[0], style[1]); - } - - Object.defineProperty(styles, groupName, { - value: group, - enumerable: false - }); - - Object.defineProperty(styles, 'codes', { - value: codes, - enumerable: false - }); - } - - const ansi2ansi = n => n; - const rgb2rgb = (r, g, b) => [r, g, b]; - - styles.color.close = '\u001B[39m'; - styles.bgColor.close = '\u001B[49m'; - - styles.color.ansi = { - ansi: wrapAnsi16(ansi2ansi, 0) - }; - styles.color.ansi256 = { - ansi256: wrapAnsi256(ansi2ansi, 0) - }; - styles.color.ansi16m = { - rgb: wrapAnsi16m(rgb2rgb, 0) - }; - - styles.bgColor.ansi = { - ansi: wrapAnsi16(ansi2ansi, 10) - }; - styles.bgColor.ansi256 = { - ansi256: wrapAnsi256(ansi2ansi, 10) - }; - styles.bgColor.ansi16m = { - rgb: wrapAnsi16m(rgb2rgb, 10) - }; - - for (let key of Object.keys(colorConvert)) { - if (typeof colorConvert[key] !== 'object') { - continue; - } - - const suite = colorConvert[key]; - - if (key === 'ansi16') { - key = 'ansi'; - } - - if ('ansi16' in suite) { - styles.color.ansi[key] = wrapAnsi16(suite.ansi16, 0); - styles.bgColor.ansi[key] = wrapAnsi16(suite.ansi16, 10); - } - - if ('ansi256' in suite) { - styles.color.ansi256[key] = wrapAnsi256(suite.ansi256, 0); - styles.bgColor.ansi256[key] = wrapAnsi256(suite.ansi256, 10); - } - - if ('rgb' in suite) { - styles.color.ansi16m[key] = wrapAnsi16m(suite.rgb, 0); - styles.bgColor.ansi16m[key] = wrapAnsi16m(suite.rgb, 10); - } - } - - return styles; -} - -// Make the export immutable -Object.defineProperty(module, 'exports', { - enumerable: true, - get: assembleStyles -}); - -/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(114)(module))) - -/***/ }), -/* 394 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - -const TEMPLATE_REGEX = /(?:\\(u[a-f\d]{4}|x[a-f\d]{2}|.))|(?:\{(~)?(\w+(?:\([^)]*\))?(?:\.\w+(?:\([^)]*\))?)*)(?:[ \t]|(?=\r?\n)))|(\})|((?:.|[\r\n\f])+?)/gi; -const STYLE_REGEX = /(?:^|\.)(\w+)(?:\(([^)]*)\))?/g; -const STRING_REGEX = /^(['"])((?:\\.|(?!\1)[^\\])*)\1$/; -const ESCAPE_REGEX = /\\(u[a-f\d]{4}|x[a-f\d]{2}|.)|([^\\])/gi; - -const ESCAPES = new Map([ - ['n', '\n'], - ['r', '\r'], - ['t', '\t'], - ['b', '\b'], - ['f', '\f'], - ['v', '\v'], - ['0', '\0'], - ['\\', '\\'], - ['e', '\u001B'], - ['a', '\u0007'] -]); - -function unescape(c) { - if ((c[0] === 'u' && c.length === 5) || (c[0] === 'x' && c.length === 3)) { - return String.fromCharCode(parseInt(c.slice(1), 16)); - } - - return ESCAPES.get(c) || c; -} - -function parseArguments(name, args) { - const results = []; - const chunks = args.trim().split(/\s*,\s*/g); - let matches; - - for (const chunk of chunks) { - if (!isNaN(chunk)) { - results.push(Number(chunk)); - } else if ((matches = chunk.match(STRING_REGEX))) { - results.push(matches[2].replace(ESCAPE_REGEX, (m, escape, chr) => escape ? unescape(escape) : chr)); - } else { - throw new Error(`Invalid Chalk template style argument: ${chunk} (in style '${name}')`); - } - } - - return results; -} - -function parseStyle(style) { - STYLE_REGEX.lastIndex = 0; - - const results = []; - let matches; - - while ((matches = STYLE_REGEX.exec(style)) !== null) { - const name = matches[1]; - - if (matches[2]) { - const args = parseArguments(name, matches[2]); - results.push([name].concat(args)); - } else { - results.push([name]); - } - } - - return results; -} - -function buildStyle(chalk, styles) { - const enabled = {}; - - for (const layer of styles) { - for (const style of layer.styles) { - enabled[style[0]] = layer.inverse ? null : style.slice(1); - } - } - - let current = chalk; - for (const styleName of Object.keys(enabled)) { - if (Array.isArray(enabled[styleName])) { - if (!(styleName in current)) { - throw new Error(`Unknown Chalk style: ${styleName}`); - } - - if (enabled[styleName].length > 0) { - current = current[styleName].apply(current, enabled[styleName]); - } else { - current = current[styleName]; - } - } - } - - return current; -} - -module.exports = (chalk, tmp) => { - const styles = []; - const chunks = []; - let chunk = []; - - // eslint-disable-next-line max-params - tmp.replace(TEMPLATE_REGEX, (m, escapeChar, inverse, style, close, chr) => { - if (escapeChar) { - chunk.push(unescape(escapeChar)); - } else if (style) { - const str = chunk.join(''); - chunk = []; - chunks.push(styles.length === 0 ? str : buildStyle(chalk, styles)(str)); - styles.push({inverse, styles: parseStyle(style)}); - } else if (close) { - if (styles.length === 0) { - throw new Error('Found extraneous } in Chalk template literal'); - } - - chunks.push(buildStyle(chalk, styles)(chunk.join(''))); - chunk = []; - styles.pop(); - } else { - chunk.push(chr); - } - }); - - chunks.push(chunk.join('')); - - if (styles.length > 0) { - const errMsg = `Chalk template literal is missing ${styles.length} closing bracket${styles.length === 1 ? '' : 's'} (\`}\`)`; - throw new Error(errMsg); - } - - return chunks.join(''); -}; - - /***/ }), -/* 395 */ -/***/ (function(module, __webpack_exports__, __webpack_require__) { - -"use strict"; -__webpack_require__.r(__webpack_exports__); -/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "RunCommand", function() { return RunCommand; }); -/* harmony import */ var _utils_errors__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(162); -/* harmony import */ var _utils_log__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(143); -/* harmony import */ var _utils_parallelize__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(144); -/* harmony import */ var _utils_projects__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(145); -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - - - - -const RunCommand = { - description: 'Run script defined in package.json in each package that contains that script.', - name: 'run', - - async run(projects, projectGraph, { - extraArgs - }) { - const batchedProjects = Object(_utils_projects__WEBPACK_IMPORTED_MODULE_3__["topologicallyBatchProjects"])(projects, projectGraph); - - if (extraArgs.length === 0) { - throw new _utils_errors__WEBPACK_IMPORTED_MODULE_0__["CliError"]('No script specified'); - } - - const scriptName = extraArgs[0]; - const scriptArgs = extraArgs.slice(1); - await Object(_utils_parallelize__WEBPACK_IMPORTED_MODULE_2__["parallelizeBatches"])(batchedProjects, async project => { - if (project.hasScript(scriptName)) { - _utils_log__WEBPACK_IMPORTED_MODULE_1__["log"].info(`[${project.name}] running "${scriptName}" script`); - await project.runScriptStreaming(scriptName, { - args: scriptArgs - }); - _utils_log__WEBPACK_IMPORTED_MODULE_1__["log"].success(`[${project.name}] complete`); - } - }); - } - -}; - -/***/ }), -/* 396 */ -/***/ (function(module, __webpack_exports__, __webpack_require__) { - -"use strict"; -__webpack_require__.r(__webpack_exports__); -/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "WatchCommand", function() { return WatchCommand; }); -/* harmony import */ var _utils_errors__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(162); -/* harmony import */ var _utils_log__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(143); -/* harmony import */ var _utils_parallelize__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(144); -/* harmony import */ var _utils_projects__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(145); -/* harmony import */ var _utils_watch__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(397); -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - - - - - - -/** - * Name of the script in the package/project package.json file to run during `kbn watch`. - */ -const watchScriptName = 'kbn:watch'; -/** - * Name of the Kibana project. - */ - -const kibanaProjectName = 'kibana'; -/** - * Command that traverses through list of available projects/packages that have `kbn:watch` script in their - * package.json files, groups them into topology aware batches and then processes theses batches one by one - * running `kbn:watch` scripts in parallel within the same batch. - * - * Command internally relies on the fact that most of the build systems that are triggered by `kbn:watch` - * will emit special "marker" once build/watch process is ready that we can use as completion condition for - * the `kbn:watch` script and eventually for the entire batch. Currently we support completion "markers" for - * `webpack` and `tsc` only, for the rest we rely on predefined timeouts. - */ - -const WatchCommand = { - description: 'Runs `kbn:watch` script for every project.', - name: 'watch', - - async run(projects, projectGraph) { - const projectsToWatch = new Map(); - - for (const project of projects.values()) { - // We can't watch project that doesn't have `kbn:watch` script. - if (project.hasScript(watchScriptName)) { - projectsToWatch.set(project.name, project); - } - } - - if (projectsToWatch.size === 0) { - throw new _utils_errors__WEBPACK_IMPORTED_MODULE_0__["CliError"](`There are no projects to watch found. Make sure that projects define 'kbn:watch' script in 'package.json'.`); - } - - const projectNames = Array.from(projectsToWatch.keys()); - _utils_log__WEBPACK_IMPORTED_MODULE_1__["log"].info(`Running ${watchScriptName} scripts for [${projectNames.join(', ')}].`); // Kibana should always be run the last, so we don't rely on automatic - // topological batching and push it to the last one-entry batch manually. - - const shouldWatchKibanaProject = projectsToWatch.delete(kibanaProjectName); - const batchedProjects = Object(_utils_projects__WEBPACK_IMPORTED_MODULE_3__["topologicallyBatchProjects"])(projectsToWatch, projectGraph); - - if (shouldWatchKibanaProject) { - batchedProjects.push([projects.get(kibanaProjectName)]); - } - - await Object(_utils_parallelize__WEBPACK_IMPORTED_MODULE_2__["parallelizeBatches"])(batchedProjects, async pkg => { - const completionHint = await Object(_utils_watch__WEBPACK_IMPORTED_MODULE_4__["waitUntilWatchIsReady"])(pkg.runScriptStreaming(watchScriptName, { - debug: false - }).stdout); - _utils_log__WEBPACK_IMPORTED_MODULE_1__["log"].success(`[${pkg.name}] Initial build completed (${completionHint}).`); - }); - } - -}; - -/***/ }), -/* 397 */ +/* 401 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "waitUntilWatchIsReady", function() { return waitUntilWatchIsReady; }); /* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(8); -/* harmony import */ var rxjs_operators__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(398); +/* harmony import */ var rxjs_operators__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(402); /* * Licensed to Elasticsearch B.V. under one or more contributor * license agreements. See the NOTICE file distributed with @@ -51141,141 +51513,141 @@ function waitUntilWatchIsReady(stream, opts = {}) { } /***/ }), -/* 398 */ +/* 402 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); -/* harmony import */ var _internal_operators_audit__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(399); +/* harmony import */ var _internal_operators_audit__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(403); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "audit", function() { return _internal_operators_audit__WEBPACK_IMPORTED_MODULE_0__["audit"]; }); -/* harmony import */ var _internal_operators_auditTime__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(400); +/* harmony import */ var _internal_operators_auditTime__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(404); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "auditTime", function() { return _internal_operators_auditTime__WEBPACK_IMPORTED_MODULE_1__["auditTime"]; }); -/* harmony import */ var _internal_operators_buffer__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(401); +/* harmony import */ var _internal_operators_buffer__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(405); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "buffer", function() { return _internal_operators_buffer__WEBPACK_IMPORTED_MODULE_2__["buffer"]; }); -/* harmony import */ var _internal_operators_bufferCount__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(402); +/* harmony import */ var _internal_operators_bufferCount__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(406); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "bufferCount", function() { return _internal_operators_bufferCount__WEBPACK_IMPORTED_MODULE_3__["bufferCount"]; }); -/* harmony import */ var _internal_operators_bufferTime__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(403); +/* harmony import */ var _internal_operators_bufferTime__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(407); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "bufferTime", function() { return _internal_operators_bufferTime__WEBPACK_IMPORTED_MODULE_4__["bufferTime"]; }); -/* harmony import */ var _internal_operators_bufferToggle__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(404); +/* harmony import */ var _internal_operators_bufferToggle__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(408); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "bufferToggle", function() { return _internal_operators_bufferToggle__WEBPACK_IMPORTED_MODULE_5__["bufferToggle"]; }); -/* harmony import */ var _internal_operators_bufferWhen__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(405); +/* harmony import */ var _internal_operators_bufferWhen__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(409); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "bufferWhen", function() { return _internal_operators_bufferWhen__WEBPACK_IMPORTED_MODULE_6__["bufferWhen"]; }); -/* harmony import */ var _internal_operators_catchError__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(406); +/* harmony import */ var _internal_operators_catchError__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(410); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "catchError", function() { return _internal_operators_catchError__WEBPACK_IMPORTED_MODULE_7__["catchError"]; }); -/* harmony import */ var _internal_operators_combineAll__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(407); +/* harmony import */ var _internal_operators_combineAll__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(411); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "combineAll", function() { return _internal_operators_combineAll__WEBPACK_IMPORTED_MODULE_8__["combineAll"]; }); -/* harmony import */ var _internal_operators_combineLatest__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(408); +/* harmony import */ var _internal_operators_combineLatest__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(412); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "combineLatest", function() { return _internal_operators_combineLatest__WEBPACK_IMPORTED_MODULE_9__["combineLatest"]; }); -/* harmony import */ var _internal_operators_concat__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(409); +/* harmony import */ var _internal_operators_concat__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(413); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "concat", function() { return _internal_operators_concat__WEBPACK_IMPORTED_MODULE_10__["concat"]; }); /* harmony import */ var _internal_operators_concatAll__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(80); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "concatAll", function() { return _internal_operators_concatAll__WEBPACK_IMPORTED_MODULE_11__["concatAll"]; }); -/* harmony import */ var _internal_operators_concatMap__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(410); +/* harmony import */ var _internal_operators_concatMap__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(414); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "concatMap", function() { return _internal_operators_concatMap__WEBPACK_IMPORTED_MODULE_12__["concatMap"]; }); -/* harmony import */ var _internal_operators_concatMapTo__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(411); +/* harmony import */ var _internal_operators_concatMapTo__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(415); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "concatMapTo", function() { return _internal_operators_concatMapTo__WEBPACK_IMPORTED_MODULE_13__["concatMapTo"]; }); -/* harmony import */ var _internal_operators_count__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(412); +/* harmony import */ var _internal_operators_count__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(416); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "count", function() { return _internal_operators_count__WEBPACK_IMPORTED_MODULE_14__["count"]; }); -/* harmony import */ var _internal_operators_debounce__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(413); +/* harmony import */ var _internal_operators_debounce__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(417); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "debounce", function() { return _internal_operators_debounce__WEBPACK_IMPORTED_MODULE_15__["debounce"]; }); -/* harmony import */ var _internal_operators_debounceTime__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(414); +/* harmony import */ var _internal_operators_debounceTime__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(418); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "debounceTime", function() { return _internal_operators_debounceTime__WEBPACK_IMPORTED_MODULE_16__["debounceTime"]; }); -/* harmony import */ var _internal_operators_defaultIfEmpty__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(415); +/* harmony import */ var _internal_operators_defaultIfEmpty__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(419); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "defaultIfEmpty", function() { return _internal_operators_defaultIfEmpty__WEBPACK_IMPORTED_MODULE_17__["defaultIfEmpty"]; }); -/* harmony import */ var _internal_operators_delay__WEBPACK_IMPORTED_MODULE_18__ = __webpack_require__(416); +/* harmony import */ var _internal_operators_delay__WEBPACK_IMPORTED_MODULE_18__ = __webpack_require__(420); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "delay", function() { return _internal_operators_delay__WEBPACK_IMPORTED_MODULE_18__["delay"]; }); -/* harmony import */ var _internal_operators_delayWhen__WEBPACK_IMPORTED_MODULE_19__ = __webpack_require__(418); +/* harmony import */ var _internal_operators_delayWhen__WEBPACK_IMPORTED_MODULE_19__ = __webpack_require__(422); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "delayWhen", function() { return _internal_operators_delayWhen__WEBPACK_IMPORTED_MODULE_19__["delayWhen"]; }); -/* harmony import */ var _internal_operators_dematerialize__WEBPACK_IMPORTED_MODULE_20__ = __webpack_require__(419); +/* harmony import */ var _internal_operators_dematerialize__WEBPACK_IMPORTED_MODULE_20__ = __webpack_require__(423); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "dematerialize", function() { return _internal_operators_dematerialize__WEBPACK_IMPORTED_MODULE_20__["dematerialize"]; }); -/* harmony import */ var _internal_operators_distinct__WEBPACK_IMPORTED_MODULE_21__ = __webpack_require__(420); +/* harmony import */ var _internal_operators_distinct__WEBPACK_IMPORTED_MODULE_21__ = __webpack_require__(424); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "distinct", function() { return _internal_operators_distinct__WEBPACK_IMPORTED_MODULE_21__["distinct"]; }); -/* harmony import */ var _internal_operators_distinctUntilChanged__WEBPACK_IMPORTED_MODULE_22__ = __webpack_require__(421); +/* harmony import */ var _internal_operators_distinctUntilChanged__WEBPACK_IMPORTED_MODULE_22__ = __webpack_require__(425); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "distinctUntilChanged", function() { return _internal_operators_distinctUntilChanged__WEBPACK_IMPORTED_MODULE_22__["distinctUntilChanged"]; }); -/* harmony import */ var _internal_operators_distinctUntilKeyChanged__WEBPACK_IMPORTED_MODULE_23__ = __webpack_require__(422); +/* harmony import */ var _internal_operators_distinctUntilKeyChanged__WEBPACK_IMPORTED_MODULE_23__ = __webpack_require__(426); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "distinctUntilKeyChanged", function() { return _internal_operators_distinctUntilKeyChanged__WEBPACK_IMPORTED_MODULE_23__["distinctUntilKeyChanged"]; }); -/* harmony import */ var _internal_operators_elementAt__WEBPACK_IMPORTED_MODULE_24__ = __webpack_require__(423); +/* harmony import */ var _internal_operators_elementAt__WEBPACK_IMPORTED_MODULE_24__ = __webpack_require__(427); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "elementAt", function() { return _internal_operators_elementAt__WEBPACK_IMPORTED_MODULE_24__["elementAt"]; }); -/* harmony import */ var _internal_operators_endWith__WEBPACK_IMPORTED_MODULE_25__ = __webpack_require__(426); +/* harmony import */ var _internal_operators_endWith__WEBPACK_IMPORTED_MODULE_25__ = __webpack_require__(430); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "endWith", function() { return _internal_operators_endWith__WEBPACK_IMPORTED_MODULE_25__["endWith"]; }); -/* harmony import */ var _internal_operators_every__WEBPACK_IMPORTED_MODULE_26__ = __webpack_require__(427); +/* harmony import */ var _internal_operators_every__WEBPACK_IMPORTED_MODULE_26__ = __webpack_require__(431); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "every", function() { return _internal_operators_every__WEBPACK_IMPORTED_MODULE_26__["every"]; }); -/* harmony import */ var _internal_operators_exhaust__WEBPACK_IMPORTED_MODULE_27__ = __webpack_require__(428); +/* harmony import */ var _internal_operators_exhaust__WEBPACK_IMPORTED_MODULE_27__ = __webpack_require__(432); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "exhaust", function() { return _internal_operators_exhaust__WEBPACK_IMPORTED_MODULE_27__["exhaust"]; }); -/* harmony import */ var _internal_operators_exhaustMap__WEBPACK_IMPORTED_MODULE_28__ = __webpack_require__(429); +/* harmony import */ var _internal_operators_exhaustMap__WEBPACK_IMPORTED_MODULE_28__ = __webpack_require__(433); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "exhaustMap", function() { return _internal_operators_exhaustMap__WEBPACK_IMPORTED_MODULE_28__["exhaustMap"]; }); -/* harmony import */ var _internal_operators_expand__WEBPACK_IMPORTED_MODULE_29__ = __webpack_require__(430); +/* harmony import */ var _internal_operators_expand__WEBPACK_IMPORTED_MODULE_29__ = __webpack_require__(434); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "expand", function() { return _internal_operators_expand__WEBPACK_IMPORTED_MODULE_29__["expand"]; }); -/* harmony import */ var _internal_operators_filter__WEBPACK_IMPORTED_MODULE_30__ = __webpack_require__(104); +/* harmony import */ var _internal_operators_filter__WEBPACK_IMPORTED_MODULE_30__ = __webpack_require__(105); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "filter", function() { return _internal_operators_filter__WEBPACK_IMPORTED_MODULE_30__["filter"]; }); -/* harmony import */ var _internal_operators_finalize__WEBPACK_IMPORTED_MODULE_31__ = __webpack_require__(431); +/* harmony import */ var _internal_operators_finalize__WEBPACK_IMPORTED_MODULE_31__ = __webpack_require__(435); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "finalize", function() { return _internal_operators_finalize__WEBPACK_IMPORTED_MODULE_31__["finalize"]; }); -/* harmony import */ var _internal_operators_find__WEBPACK_IMPORTED_MODULE_32__ = __webpack_require__(432); +/* harmony import */ var _internal_operators_find__WEBPACK_IMPORTED_MODULE_32__ = __webpack_require__(436); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "find", function() { return _internal_operators_find__WEBPACK_IMPORTED_MODULE_32__["find"]; }); -/* harmony import */ var _internal_operators_findIndex__WEBPACK_IMPORTED_MODULE_33__ = __webpack_require__(433); +/* harmony import */ var _internal_operators_findIndex__WEBPACK_IMPORTED_MODULE_33__ = __webpack_require__(437); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "findIndex", function() { return _internal_operators_findIndex__WEBPACK_IMPORTED_MODULE_33__["findIndex"]; }); -/* harmony import */ var _internal_operators_first__WEBPACK_IMPORTED_MODULE_34__ = __webpack_require__(434); +/* harmony import */ var _internal_operators_first__WEBPACK_IMPORTED_MODULE_34__ = __webpack_require__(438); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "first", function() { return _internal_operators_first__WEBPACK_IMPORTED_MODULE_34__["first"]; }); /* harmony import */ var _internal_operators_groupBy__WEBPACK_IMPORTED_MODULE_35__ = __webpack_require__(31); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "groupBy", function() { return _internal_operators_groupBy__WEBPACK_IMPORTED_MODULE_35__["groupBy"]; }); -/* harmony import */ var _internal_operators_ignoreElements__WEBPACK_IMPORTED_MODULE_36__ = __webpack_require__(435); +/* harmony import */ var _internal_operators_ignoreElements__WEBPACK_IMPORTED_MODULE_36__ = __webpack_require__(439); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "ignoreElements", function() { return _internal_operators_ignoreElements__WEBPACK_IMPORTED_MODULE_36__["ignoreElements"]; }); -/* harmony import */ var _internal_operators_isEmpty__WEBPACK_IMPORTED_MODULE_37__ = __webpack_require__(436); +/* harmony import */ var _internal_operators_isEmpty__WEBPACK_IMPORTED_MODULE_37__ = __webpack_require__(440); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "isEmpty", function() { return _internal_operators_isEmpty__WEBPACK_IMPORTED_MODULE_37__["isEmpty"]; }); -/* harmony import */ var _internal_operators_last__WEBPACK_IMPORTED_MODULE_38__ = __webpack_require__(437); +/* harmony import */ var _internal_operators_last__WEBPACK_IMPORTED_MODULE_38__ = __webpack_require__(441); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "last", function() { return _internal_operators_last__WEBPACK_IMPORTED_MODULE_38__["last"]; }); /* harmony import */ var _internal_operators_map__WEBPACK_IMPORTED_MODULE_39__ = __webpack_require__(66); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "map", function() { return _internal_operators_map__WEBPACK_IMPORTED_MODULE_39__["map"]; }); -/* harmony import */ var _internal_operators_mapTo__WEBPACK_IMPORTED_MODULE_40__ = __webpack_require__(439); +/* harmony import */ var _internal_operators_mapTo__WEBPACK_IMPORTED_MODULE_40__ = __webpack_require__(443); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "mapTo", function() { return _internal_operators_mapTo__WEBPACK_IMPORTED_MODULE_40__["mapTo"]; }); -/* harmony import */ var _internal_operators_materialize__WEBPACK_IMPORTED_MODULE_41__ = __webpack_require__(440); +/* harmony import */ var _internal_operators_materialize__WEBPACK_IMPORTED_MODULE_41__ = __webpack_require__(444); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "materialize", function() { return _internal_operators_materialize__WEBPACK_IMPORTED_MODULE_41__["materialize"]; }); -/* harmony import */ var _internal_operators_max__WEBPACK_IMPORTED_MODULE_42__ = __webpack_require__(441); +/* harmony import */ var _internal_operators_max__WEBPACK_IMPORTED_MODULE_42__ = __webpack_require__(445); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "max", function() { return _internal_operators_max__WEBPACK_IMPORTED_MODULE_42__["max"]; }); -/* harmony import */ var _internal_operators_merge__WEBPACK_IMPORTED_MODULE_43__ = __webpack_require__(444); +/* harmony import */ var _internal_operators_merge__WEBPACK_IMPORTED_MODULE_43__ = __webpack_require__(448); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "merge", function() { return _internal_operators_merge__WEBPACK_IMPORTED_MODULE_43__["merge"]; }); /* harmony import */ var _internal_operators_mergeAll__WEBPACK_IMPORTED_MODULE_44__ = __webpack_require__(81); @@ -51284,177 +51656,177 @@ __webpack_require__.r(__webpack_exports__); /* harmony import */ var _internal_operators_mergeMap__WEBPACK_IMPORTED_MODULE_45__ = __webpack_require__(82); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "mergeMap", function() { return _internal_operators_mergeMap__WEBPACK_IMPORTED_MODULE_45__["mergeMap"]; }); -/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "flatMap", function() { return _internal_operators_mergeMap__WEBPACK_IMPORTED_MODULE_45__["mergeMap"]; }); +/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "flatMap", function() { return _internal_operators_mergeMap__WEBPACK_IMPORTED_MODULE_45__["flatMap"]; }); -/* harmony import */ var _internal_operators_mergeMapTo__WEBPACK_IMPORTED_MODULE_46__ = __webpack_require__(445); +/* harmony import */ var _internal_operators_mergeMapTo__WEBPACK_IMPORTED_MODULE_46__ = __webpack_require__(449); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "mergeMapTo", function() { return _internal_operators_mergeMapTo__WEBPACK_IMPORTED_MODULE_46__["mergeMapTo"]; }); -/* harmony import */ var _internal_operators_mergeScan__WEBPACK_IMPORTED_MODULE_47__ = __webpack_require__(446); +/* harmony import */ var _internal_operators_mergeScan__WEBPACK_IMPORTED_MODULE_47__ = __webpack_require__(450); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "mergeScan", function() { return _internal_operators_mergeScan__WEBPACK_IMPORTED_MODULE_47__["mergeScan"]; }); -/* harmony import */ var _internal_operators_min__WEBPACK_IMPORTED_MODULE_48__ = __webpack_require__(447); +/* harmony import */ var _internal_operators_min__WEBPACK_IMPORTED_MODULE_48__ = __webpack_require__(451); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "min", function() { return _internal_operators_min__WEBPACK_IMPORTED_MODULE_48__["min"]; }); -/* harmony import */ var _internal_operators_multicast__WEBPACK_IMPORTED_MODULE_49__ = __webpack_require__(448); +/* harmony import */ var _internal_operators_multicast__WEBPACK_IMPORTED_MODULE_49__ = __webpack_require__(452); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "multicast", function() { return _internal_operators_multicast__WEBPACK_IMPORTED_MODULE_49__["multicast"]; }); /* harmony import */ var _internal_operators_observeOn__WEBPACK_IMPORTED_MODULE_50__ = __webpack_require__(41); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "observeOn", function() { return _internal_operators_observeOn__WEBPACK_IMPORTED_MODULE_50__["observeOn"]; }); -/* harmony import */ var _internal_operators_onErrorResumeNext__WEBPACK_IMPORTED_MODULE_51__ = __webpack_require__(449); +/* harmony import */ var _internal_operators_onErrorResumeNext__WEBPACK_IMPORTED_MODULE_51__ = __webpack_require__(453); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "onErrorResumeNext", function() { return _internal_operators_onErrorResumeNext__WEBPACK_IMPORTED_MODULE_51__["onErrorResumeNext"]; }); -/* harmony import */ var _internal_operators_pairwise__WEBPACK_IMPORTED_MODULE_52__ = __webpack_require__(450); +/* harmony import */ var _internal_operators_pairwise__WEBPACK_IMPORTED_MODULE_52__ = __webpack_require__(454); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "pairwise", function() { return _internal_operators_pairwise__WEBPACK_IMPORTED_MODULE_52__["pairwise"]; }); -/* harmony import */ var _internal_operators_partition__WEBPACK_IMPORTED_MODULE_53__ = __webpack_require__(451); +/* harmony import */ var _internal_operators_partition__WEBPACK_IMPORTED_MODULE_53__ = __webpack_require__(455); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "partition", function() { return _internal_operators_partition__WEBPACK_IMPORTED_MODULE_53__["partition"]; }); -/* harmony import */ var _internal_operators_pluck__WEBPACK_IMPORTED_MODULE_54__ = __webpack_require__(452); +/* harmony import */ var _internal_operators_pluck__WEBPACK_IMPORTED_MODULE_54__ = __webpack_require__(456); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "pluck", function() { return _internal_operators_pluck__WEBPACK_IMPORTED_MODULE_54__["pluck"]; }); -/* harmony import */ var _internal_operators_publish__WEBPACK_IMPORTED_MODULE_55__ = __webpack_require__(453); +/* harmony import */ var _internal_operators_publish__WEBPACK_IMPORTED_MODULE_55__ = __webpack_require__(457); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "publish", function() { return _internal_operators_publish__WEBPACK_IMPORTED_MODULE_55__["publish"]; }); -/* harmony import */ var _internal_operators_publishBehavior__WEBPACK_IMPORTED_MODULE_56__ = __webpack_require__(454); +/* harmony import */ var _internal_operators_publishBehavior__WEBPACK_IMPORTED_MODULE_56__ = __webpack_require__(458); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "publishBehavior", function() { return _internal_operators_publishBehavior__WEBPACK_IMPORTED_MODULE_56__["publishBehavior"]; }); -/* harmony import */ var _internal_operators_publishLast__WEBPACK_IMPORTED_MODULE_57__ = __webpack_require__(455); +/* harmony import */ var _internal_operators_publishLast__WEBPACK_IMPORTED_MODULE_57__ = __webpack_require__(459); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "publishLast", function() { return _internal_operators_publishLast__WEBPACK_IMPORTED_MODULE_57__["publishLast"]; }); -/* harmony import */ var _internal_operators_publishReplay__WEBPACK_IMPORTED_MODULE_58__ = __webpack_require__(456); +/* harmony import */ var _internal_operators_publishReplay__WEBPACK_IMPORTED_MODULE_58__ = __webpack_require__(460); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "publishReplay", function() { return _internal_operators_publishReplay__WEBPACK_IMPORTED_MODULE_58__["publishReplay"]; }); -/* harmony import */ var _internal_operators_race__WEBPACK_IMPORTED_MODULE_59__ = __webpack_require__(457); +/* harmony import */ var _internal_operators_race__WEBPACK_IMPORTED_MODULE_59__ = __webpack_require__(461); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "race", function() { return _internal_operators_race__WEBPACK_IMPORTED_MODULE_59__["race"]; }); -/* harmony import */ var _internal_operators_reduce__WEBPACK_IMPORTED_MODULE_60__ = __webpack_require__(442); +/* harmony import */ var _internal_operators_reduce__WEBPACK_IMPORTED_MODULE_60__ = __webpack_require__(446); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "reduce", function() { return _internal_operators_reduce__WEBPACK_IMPORTED_MODULE_60__["reduce"]; }); -/* harmony import */ var _internal_operators_repeat__WEBPACK_IMPORTED_MODULE_61__ = __webpack_require__(458); +/* harmony import */ var _internal_operators_repeat__WEBPACK_IMPORTED_MODULE_61__ = __webpack_require__(462); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "repeat", function() { return _internal_operators_repeat__WEBPACK_IMPORTED_MODULE_61__["repeat"]; }); -/* harmony import */ var _internal_operators_repeatWhen__WEBPACK_IMPORTED_MODULE_62__ = __webpack_require__(459); +/* harmony import */ var _internal_operators_repeatWhen__WEBPACK_IMPORTED_MODULE_62__ = __webpack_require__(463); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "repeatWhen", function() { return _internal_operators_repeatWhen__WEBPACK_IMPORTED_MODULE_62__["repeatWhen"]; }); -/* harmony import */ var _internal_operators_retry__WEBPACK_IMPORTED_MODULE_63__ = __webpack_require__(460); +/* harmony import */ var _internal_operators_retry__WEBPACK_IMPORTED_MODULE_63__ = __webpack_require__(464); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "retry", function() { return _internal_operators_retry__WEBPACK_IMPORTED_MODULE_63__["retry"]; }); -/* harmony import */ var _internal_operators_retryWhen__WEBPACK_IMPORTED_MODULE_64__ = __webpack_require__(461); +/* harmony import */ var _internal_operators_retryWhen__WEBPACK_IMPORTED_MODULE_64__ = __webpack_require__(465); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "retryWhen", function() { return _internal_operators_retryWhen__WEBPACK_IMPORTED_MODULE_64__["retryWhen"]; }); /* harmony import */ var _internal_operators_refCount__WEBPACK_IMPORTED_MODULE_65__ = __webpack_require__(30); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "refCount", function() { return _internal_operators_refCount__WEBPACK_IMPORTED_MODULE_65__["refCount"]; }); -/* harmony import */ var _internal_operators_sample__WEBPACK_IMPORTED_MODULE_66__ = __webpack_require__(462); +/* harmony import */ var _internal_operators_sample__WEBPACK_IMPORTED_MODULE_66__ = __webpack_require__(466); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "sample", function() { return _internal_operators_sample__WEBPACK_IMPORTED_MODULE_66__["sample"]; }); -/* harmony import */ var _internal_operators_sampleTime__WEBPACK_IMPORTED_MODULE_67__ = __webpack_require__(463); +/* harmony import */ var _internal_operators_sampleTime__WEBPACK_IMPORTED_MODULE_67__ = __webpack_require__(467); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "sampleTime", function() { return _internal_operators_sampleTime__WEBPACK_IMPORTED_MODULE_67__["sampleTime"]; }); -/* harmony import */ var _internal_operators_scan__WEBPACK_IMPORTED_MODULE_68__ = __webpack_require__(443); +/* harmony import */ var _internal_operators_scan__WEBPACK_IMPORTED_MODULE_68__ = __webpack_require__(447); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "scan", function() { return _internal_operators_scan__WEBPACK_IMPORTED_MODULE_68__["scan"]; }); -/* harmony import */ var _internal_operators_sequenceEqual__WEBPACK_IMPORTED_MODULE_69__ = __webpack_require__(464); +/* harmony import */ var _internal_operators_sequenceEqual__WEBPACK_IMPORTED_MODULE_69__ = __webpack_require__(468); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "sequenceEqual", function() { return _internal_operators_sequenceEqual__WEBPACK_IMPORTED_MODULE_69__["sequenceEqual"]; }); -/* harmony import */ var _internal_operators_share__WEBPACK_IMPORTED_MODULE_70__ = __webpack_require__(465); +/* harmony import */ var _internal_operators_share__WEBPACK_IMPORTED_MODULE_70__ = __webpack_require__(469); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "share", function() { return _internal_operators_share__WEBPACK_IMPORTED_MODULE_70__["share"]; }); -/* harmony import */ var _internal_operators_shareReplay__WEBPACK_IMPORTED_MODULE_71__ = __webpack_require__(466); +/* harmony import */ var _internal_operators_shareReplay__WEBPACK_IMPORTED_MODULE_71__ = __webpack_require__(470); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "shareReplay", function() { return _internal_operators_shareReplay__WEBPACK_IMPORTED_MODULE_71__["shareReplay"]; }); -/* harmony import */ var _internal_operators_single__WEBPACK_IMPORTED_MODULE_72__ = __webpack_require__(467); +/* harmony import */ var _internal_operators_single__WEBPACK_IMPORTED_MODULE_72__ = __webpack_require__(471); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "single", function() { return _internal_operators_single__WEBPACK_IMPORTED_MODULE_72__["single"]; }); -/* harmony import */ var _internal_operators_skip__WEBPACK_IMPORTED_MODULE_73__ = __webpack_require__(468); +/* harmony import */ var _internal_operators_skip__WEBPACK_IMPORTED_MODULE_73__ = __webpack_require__(472); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "skip", function() { return _internal_operators_skip__WEBPACK_IMPORTED_MODULE_73__["skip"]; }); -/* harmony import */ var _internal_operators_skipLast__WEBPACK_IMPORTED_MODULE_74__ = __webpack_require__(469); +/* harmony import */ var _internal_operators_skipLast__WEBPACK_IMPORTED_MODULE_74__ = __webpack_require__(473); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "skipLast", function() { return _internal_operators_skipLast__WEBPACK_IMPORTED_MODULE_74__["skipLast"]; }); -/* harmony import */ var _internal_operators_skipUntil__WEBPACK_IMPORTED_MODULE_75__ = __webpack_require__(470); +/* harmony import */ var _internal_operators_skipUntil__WEBPACK_IMPORTED_MODULE_75__ = __webpack_require__(474); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "skipUntil", function() { return _internal_operators_skipUntil__WEBPACK_IMPORTED_MODULE_75__["skipUntil"]; }); -/* harmony import */ var _internal_operators_skipWhile__WEBPACK_IMPORTED_MODULE_76__ = __webpack_require__(471); +/* harmony import */ var _internal_operators_skipWhile__WEBPACK_IMPORTED_MODULE_76__ = __webpack_require__(475); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "skipWhile", function() { return _internal_operators_skipWhile__WEBPACK_IMPORTED_MODULE_76__["skipWhile"]; }); -/* harmony import */ var _internal_operators_startWith__WEBPACK_IMPORTED_MODULE_77__ = __webpack_require__(472); +/* harmony import */ var _internal_operators_startWith__WEBPACK_IMPORTED_MODULE_77__ = __webpack_require__(476); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "startWith", function() { return _internal_operators_startWith__WEBPACK_IMPORTED_MODULE_77__["startWith"]; }); -/* harmony import */ var _internal_operators_subscribeOn__WEBPACK_IMPORTED_MODULE_78__ = __webpack_require__(473); +/* harmony import */ var _internal_operators_subscribeOn__WEBPACK_IMPORTED_MODULE_78__ = __webpack_require__(477); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "subscribeOn", function() { return _internal_operators_subscribeOn__WEBPACK_IMPORTED_MODULE_78__["subscribeOn"]; }); -/* harmony import */ var _internal_operators_switchAll__WEBPACK_IMPORTED_MODULE_79__ = __webpack_require__(475); +/* harmony import */ var _internal_operators_switchAll__WEBPACK_IMPORTED_MODULE_79__ = __webpack_require__(479); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "switchAll", function() { return _internal_operators_switchAll__WEBPACK_IMPORTED_MODULE_79__["switchAll"]; }); -/* harmony import */ var _internal_operators_switchMap__WEBPACK_IMPORTED_MODULE_80__ = __webpack_require__(476); +/* harmony import */ var _internal_operators_switchMap__WEBPACK_IMPORTED_MODULE_80__ = __webpack_require__(480); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "switchMap", function() { return _internal_operators_switchMap__WEBPACK_IMPORTED_MODULE_80__["switchMap"]; }); -/* harmony import */ var _internal_operators_switchMapTo__WEBPACK_IMPORTED_MODULE_81__ = __webpack_require__(477); +/* harmony import */ var _internal_operators_switchMapTo__WEBPACK_IMPORTED_MODULE_81__ = __webpack_require__(481); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "switchMapTo", function() { return _internal_operators_switchMapTo__WEBPACK_IMPORTED_MODULE_81__["switchMapTo"]; }); -/* harmony import */ var _internal_operators_take__WEBPACK_IMPORTED_MODULE_82__ = __webpack_require__(425); +/* harmony import */ var _internal_operators_take__WEBPACK_IMPORTED_MODULE_82__ = __webpack_require__(429); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "take", function() { return _internal_operators_take__WEBPACK_IMPORTED_MODULE_82__["take"]; }); -/* harmony import */ var _internal_operators_takeLast__WEBPACK_IMPORTED_MODULE_83__ = __webpack_require__(438); +/* harmony import */ var _internal_operators_takeLast__WEBPACK_IMPORTED_MODULE_83__ = __webpack_require__(442); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "takeLast", function() { return _internal_operators_takeLast__WEBPACK_IMPORTED_MODULE_83__["takeLast"]; }); -/* harmony import */ var _internal_operators_takeUntil__WEBPACK_IMPORTED_MODULE_84__ = __webpack_require__(478); +/* harmony import */ var _internal_operators_takeUntil__WEBPACK_IMPORTED_MODULE_84__ = __webpack_require__(482); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "takeUntil", function() { return _internal_operators_takeUntil__WEBPACK_IMPORTED_MODULE_84__["takeUntil"]; }); -/* harmony import */ var _internal_operators_takeWhile__WEBPACK_IMPORTED_MODULE_85__ = __webpack_require__(479); +/* harmony import */ var _internal_operators_takeWhile__WEBPACK_IMPORTED_MODULE_85__ = __webpack_require__(483); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "takeWhile", function() { return _internal_operators_takeWhile__WEBPACK_IMPORTED_MODULE_85__["takeWhile"]; }); -/* harmony import */ var _internal_operators_tap__WEBPACK_IMPORTED_MODULE_86__ = __webpack_require__(480); +/* harmony import */ var _internal_operators_tap__WEBPACK_IMPORTED_MODULE_86__ = __webpack_require__(484); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "tap", function() { return _internal_operators_tap__WEBPACK_IMPORTED_MODULE_86__["tap"]; }); -/* harmony import */ var _internal_operators_throttle__WEBPACK_IMPORTED_MODULE_87__ = __webpack_require__(481); +/* harmony import */ var _internal_operators_throttle__WEBPACK_IMPORTED_MODULE_87__ = __webpack_require__(485); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "throttle", function() { return _internal_operators_throttle__WEBPACK_IMPORTED_MODULE_87__["throttle"]; }); -/* harmony import */ var _internal_operators_throttleTime__WEBPACK_IMPORTED_MODULE_88__ = __webpack_require__(482); +/* harmony import */ var _internal_operators_throttleTime__WEBPACK_IMPORTED_MODULE_88__ = __webpack_require__(486); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "throttleTime", function() { return _internal_operators_throttleTime__WEBPACK_IMPORTED_MODULE_88__["throttleTime"]; }); -/* harmony import */ var _internal_operators_throwIfEmpty__WEBPACK_IMPORTED_MODULE_89__ = __webpack_require__(424); +/* harmony import */ var _internal_operators_throwIfEmpty__WEBPACK_IMPORTED_MODULE_89__ = __webpack_require__(428); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "throwIfEmpty", function() { return _internal_operators_throwIfEmpty__WEBPACK_IMPORTED_MODULE_89__["throwIfEmpty"]; }); -/* harmony import */ var _internal_operators_timeInterval__WEBPACK_IMPORTED_MODULE_90__ = __webpack_require__(483); +/* harmony import */ var _internal_operators_timeInterval__WEBPACK_IMPORTED_MODULE_90__ = __webpack_require__(487); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "timeInterval", function() { return _internal_operators_timeInterval__WEBPACK_IMPORTED_MODULE_90__["timeInterval"]; }); -/* harmony import */ var _internal_operators_timeout__WEBPACK_IMPORTED_MODULE_91__ = __webpack_require__(484); +/* harmony import */ var _internal_operators_timeout__WEBPACK_IMPORTED_MODULE_91__ = __webpack_require__(488); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "timeout", function() { return _internal_operators_timeout__WEBPACK_IMPORTED_MODULE_91__["timeout"]; }); -/* harmony import */ var _internal_operators_timeoutWith__WEBPACK_IMPORTED_MODULE_92__ = __webpack_require__(485); +/* harmony import */ var _internal_operators_timeoutWith__WEBPACK_IMPORTED_MODULE_92__ = __webpack_require__(489); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "timeoutWith", function() { return _internal_operators_timeoutWith__WEBPACK_IMPORTED_MODULE_92__["timeoutWith"]; }); -/* harmony import */ var _internal_operators_timestamp__WEBPACK_IMPORTED_MODULE_93__ = __webpack_require__(486); +/* harmony import */ var _internal_operators_timestamp__WEBPACK_IMPORTED_MODULE_93__ = __webpack_require__(490); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "timestamp", function() { return _internal_operators_timestamp__WEBPACK_IMPORTED_MODULE_93__["timestamp"]; }); -/* harmony import */ var _internal_operators_toArray__WEBPACK_IMPORTED_MODULE_94__ = __webpack_require__(487); +/* harmony import */ var _internal_operators_toArray__WEBPACK_IMPORTED_MODULE_94__ = __webpack_require__(491); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "toArray", function() { return _internal_operators_toArray__WEBPACK_IMPORTED_MODULE_94__["toArray"]; }); -/* harmony import */ var _internal_operators_window__WEBPACK_IMPORTED_MODULE_95__ = __webpack_require__(488); +/* harmony import */ var _internal_operators_window__WEBPACK_IMPORTED_MODULE_95__ = __webpack_require__(492); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "window", function() { return _internal_operators_window__WEBPACK_IMPORTED_MODULE_95__["window"]; }); -/* harmony import */ var _internal_operators_windowCount__WEBPACK_IMPORTED_MODULE_96__ = __webpack_require__(489); +/* harmony import */ var _internal_operators_windowCount__WEBPACK_IMPORTED_MODULE_96__ = __webpack_require__(493); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "windowCount", function() { return _internal_operators_windowCount__WEBPACK_IMPORTED_MODULE_96__["windowCount"]; }); -/* harmony import */ var _internal_operators_windowTime__WEBPACK_IMPORTED_MODULE_97__ = __webpack_require__(490); +/* harmony import */ var _internal_operators_windowTime__WEBPACK_IMPORTED_MODULE_97__ = __webpack_require__(494); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "windowTime", function() { return _internal_operators_windowTime__WEBPACK_IMPORTED_MODULE_97__["windowTime"]; }); -/* harmony import */ var _internal_operators_windowToggle__WEBPACK_IMPORTED_MODULE_98__ = __webpack_require__(491); +/* harmony import */ var _internal_operators_windowToggle__WEBPACK_IMPORTED_MODULE_98__ = __webpack_require__(495); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "windowToggle", function() { return _internal_operators_windowToggle__WEBPACK_IMPORTED_MODULE_98__["windowToggle"]; }); -/* harmony import */ var _internal_operators_windowWhen__WEBPACK_IMPORTED_MODULE_99__ = __webpack_require__(492); +/* harmony import */ var _internal_operators_windowWhen__WEBPACK_IMPORTED_MODULE_99__ = __webpack_require__(496); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "windowWhen", function() { return _internal_operators_windowWhen__WEBPACK_IMPORTED_MODULE_99__["windowWhen"]; }); -/* harmony import */ var _internal_operators_withLatestFrom__WEBPACK_IMPORTED_MODULE_100__ = __webpack_require__(493); +/* harmony import */ var _internal_operators_withLatestFrom__WEBPACK_IMPORTED_MODULE_100__ = __webpack_require__(497); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "withLatestFrom", function() { return _internal_operators_withLatestFrom__WEBPACK_IMPORTED_MODULE_100__["withLatestFrom"]; }); -/* harmony import */ var _internal_operators_zip__WEBPACK_IMPORTED_MODULE_101__ = __webpack_require__(494); +/* harmony import */ var _internal_operators_zip__WEBPACK_IMPORTED_MODULE_101__ = __webpack_require__(498); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "zip", function() { return _internal_operators_zip__WEBPACK_IMPORTED_MODULE_101__["zip"]; }); -/* harmony import */ var _internal_operators_zipAll__WEBPACK_IMPORTED_MODULE_102__ = __webpack_require__(495); +/* harmony import */ var _internal_operators_zipAll__WEBPACK_IMPORTED_MODULE_102__ = __webpack_require__(499); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "zipAll", function() { return _internal_operators_zipAll__WEBPACK_IMPORTED_MODULE_102__["zipAll"]; }); /** PURE_IMPORTS_START PURE_IMPORTS_END */ @@ -51559,24 +51931,21 @@ __webpack_require__.r(__webpack_exports__); - //# sourceMappingURL=index.js.map /***/ }), -/* 399 */ +/* 403 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "audit", function() { return audit; }); /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(12); -/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(69); -/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(70); -/** PURE_IMPORTS_START tslib,_OuterSubscriber,_util_subscribeToResult PURE_IMPORTS_END */ - +/* harmony import */ var _innerSubscribe__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(90); +/** PURE_IMPORTS_START tslib,_innerSubscribe PURE_IMPORTS_END */ function audit(durationSelector) { @@ -51613,7 +51982,7 @@ var AuditSubscriber = /*@__PURE__*/ (function (_super) { catch (err) { return this.destination.error(err); } - var innerSubscription = Object(_util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__["subscribeToResult"])(this, duration); + var innerSubscription = Object(_innerSubscribe__WEBPACK_IMPORTED_MODULE_1__["innerSubscribe"])(duration, new _innerSubscribe__WEBPACK_IMPORTED_MODULE_1__["SimpleInnerSubscriber"](this)); if (!innerSubscription || innerSubscription.closed) { this.clearThrottle(); } @@ -51626,36 +51995,36 @@ var AuditSubscriber = /*@__PURE__*/ (function (_super) { var _a = this, value = _a.value, hasValue = _a.hasValue, throttled = _a.throttled; if (throttled) { this.remove(throttled); - this.throttled = null; + this.throttled = undefined; throttled.unsubscribe(); } if (hasValue) { - this.value = null; + this.value = undefined; this.hasValue = false; this.destination.next(value); } }; - AuditSubscriber.prototype.notifyNext = function (outerValue, innerValue, outerIndex, innerIndex) { + AuditSubscriber.prototype.notifyNext = function () { this.clearThrottle(); }; AuditSubscriber.prototype.notifyComplete = function () { this.clearThrottle(); }; return AuditSubscriber; -}(_OuterSubscriber__WEBPACK_IMPORTED_MODULE_1__["OuterSubscriber"])); +}(_innerSubscribe__WEBPACK_IMPORTED_MODULE_1__["SimpleOuterSubscriber"])); //# sourceMappingURL=audit.js.map /***/ }), -/* 400 */ +/* 404 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "auditTime", function() { return auditTime; }); /* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(55); -/* harmony import */ var _audit__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(399); -/* harmony import */ var _observable_timer__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(107); +/* harmony import */ var _audit__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(403); +/* harmony import */ var _observable_timer__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(108); /** PURE_IMPORTS_START _scheduler_async,_audit,_observable_timer PURE_IMPORTS_END */ @@ -51670,17 +52039,15 @@ function auditTime(duration, scheduler) { /***/ }), -/* 401 */ +/* 405 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "buffer", function() { return buffer; }); /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(12); -/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(69); -/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(70); -/** PURE_IMPORTS_START tslib,_OuterSubscriber,_util_subscribeToResult PURE_IMPORTS_END */ - +/* harmony import */ var _innerSubscribe__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(90); +/** PURE_IMPORTS_START tslib,_innerSubscribe PURE_IMPORTS_END */ function buffer(closingNotifier) { @@ -51702,24 +52069,24 @@ var BufferSubscriber = /*@__PURE__*/ (function (_super) { function BufferSubscriber(destination, closingNotifier) { var _this = _super.call(this, destination) || this; _this.buffer = []; - _this.add(Object(_util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__["subscribeToResult"])(_this, closingNotifier)); + _this.add(Object(_innerSubscribe__WEBPACK_IMPORTED_MODULE_1__["innerSubscribe"])(closingNotifier, new _innerSubscribe__WEBPACK_IMPORTED_MODULE_1__["SimpleInnerSubscriber"](_this))); return _this; } BufferSubscriber.prototype._next = function (value) { this.buffer.push(value); }; - BufferSubscriber.prototype.notifyNext = function (outerValue, innerValue, outerIndex, innerIndex, innerSub) { + BufferSubscriber.prototype.notifyNext = function () { var buffer = this.buffer; this.buffer = []; this.destination.next(buffer); }; return BufferSubscriber; -}(_OuterSubscriber__WEBPACK_IMPORTED_MODULE_1__["OuterSubscriber"])); +}(_innerSubscribe__WEBPACK_IMPORTED_MODULE_1__["SimpleOuterSubscriber"])); //# sourceMappingURL=buffer.js.map /***/ }), -/* 402 */ +/* 406 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -51820,7 +52187,7 @@ var BufferSkipCountSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 403 */ +/* 407 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -51981,7 +52348,7 @@ function dispatchBufferClose(arg) { /***/ }), -/* 404 */ +/* 408 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -52015,7 +52382,6 @@ var BufferToggleSubscriber = /*@__PURE__*/ (function (_super) { tslib__WEBPACK_IMPORTED_MODULE_0__["__extends"](BufferToggleSubscriber, _super); function BufferToggleSubscriber(destination, openings, closingSelector) { var _this = _super.call(this, destination) || this; - _this.openings = openings; _this.closingSelector = closingSelector; _this.contexts = []; _this.add(Object(_util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__["subscribeToResult"])(_this, openings)); @@ -52051,7 +52417,7 @@ var BufferToggleSubscriber = /*@__PURE__*/ (function (_super) { this.contexts = null; _super.prototype._complete.call(this); }; - BufferToggleSubscriber.prototype.notifyNext = function (outerValue, innerValue, outerIndex, innerIndex, innerSub) { + BufferToggleSubscriber.prototype.notifyNext = function (outerValue, innerValue) { outerValue ? this.closeBuffer(outerValue) : this.openBuffer(innerValue); }; BufferToggleSubscriber.prototype.notifyComplete = function (innerSub) { @@ -52101,7 +52467,7 @@ var BufferToggleSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 405 */ +/* 409 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -52109,10 +52475,8 @@ __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "bufferWhen", function() { return bufferWhen; }); /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(12); /* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(17); -/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(69); -/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(70); -/** PURE_IMPORTS_START tslib,_Subscription,_OuterSubscriber,_util_subscribeToResult PURE_IMPORTS_END */ - +/* harmony import */ var _innerSubscribe__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(90); +/** PURE_IMPORTS_START tslib,_Subscription,_innerSubscribe PURE_IMPORTS_END */ @@ -52150,10 +52514,10 @@ var BufferWhenSubscriber = /*@__PURE__*/ (function (_super) { _super.prototype._complete.call(this); }; BufferWhenSubscriber.prototype._unsubscribe = function () { - this.buffer = null; + this.buffer = undefined; this.subscribing = false; }; - BufferWhenSubscriber.prototype.notifyNext = function (outerValue, innerValue, outerIndex, innerIndex, innerSub) { + BufferWhenSubscriber.prototype.notifyNext = function () { this.openBuffer(); }; BufferWhenSubscriber.prototype.notifyComplete = function () { @@ -52187,28 +52551,24 @@ var BufferWhenSubscriber = /*@__PURE__*/ (function (_super) { this.closingSubscription = closingSubscription; this.add(closingSubscription); this.subscribing = true; - closingSubscription.add(Object(_util_subscribeToResult__WEBPACK_IMPORTED_MODULE_3__["subscribeToResult"])(this, closingNotifier)); + closingSubscription.add(Object(_innerSubscribe__WEBPACK_IMPORTED_MODULE_2__["innerSubscribe"])(closingNotifier, new _innerSubscribe__WEBPACK_IMPORTED_MODULE_2__["SimpleInnerSubscriber"](this))); this.subscribing = false; }; return BufferWhenSubscriber; -}(_OuterSubscriber__WEBPACK_IMPORTED_MODULE_2__["OuterSubscriber"])); +}(_innerSubscribe__WEBPACK_IMPORTED_MODULE_2__["SimpleOuterSubscriber"])); //# sourceMappingURL=bufferWhen.js.map /***/ }), -/* 406 */ +/* 410 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "catchError", function() { return catchError; }); /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(12); -/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(69); -/* harmony import */ var _InnerSubscriber__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(71); -/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(70); -/** PURE_IMPORTS_START tslib,_OuterSubscriber,_InnerSubscriber,_util_subscribeToResult PURE_IMPORTS_END */ - - +/* harmony import */ var _innerSubscribe__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(90); +/** PURE_IMPORTS_START tslib,_innerSubscribe PURE_IMPORTS_END */ function catchError(selector) { @@ -52246,21 +52606,21 @@ var CatchSubscriber = /*@__PURE__*/ (function (_super) { return; } this._unsubscribeAndRecycle(); - var innerSubscriber = new _InnerSubscriber__WEBPACK_IMPORTED_MODULE_2__["InnerSubscriber"](this, undefined, undefined); + var innerSubscriber = new _innerSubscribe__WEBPACK_IMPORTED_MODULE_1__["SimpleInnerSubscriber"](this); this.add(innerSubscriber); - var innerSubscription = Object(_util_subscribeToResult__WEBPACK_IMPORTED_MODULE_3__["subscribeToResult"])(this, result, undefined, undefined, innerSubscriber); + var innerSubscription = Object(_innerSubscribe__WEBPACK_IMPORTED_MODULE_1__["innerSubscribe"])(result, innerSubscriber); if (innerSubscription !== innerSubscriber) { this.add(innerSubscription); } } }; return CatchSubscriber; -}(_OuterSubscriber__WEBPACK_IMPORTED_MODULE_1__["OuterSubscriber"])); +}(_innerSubscribe__WEBPACK_IMPORTED_MODULE_1__["SimpleOuterSubscriber"])); //# sourceMappingURL=catchError.js.map /***/ }), -/* 407 */ +/* 411 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -52276,7 +52636,7 @@ function combineAll(project) { /***/ }), -/* 408 */ +/* 412 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -52308,7 +52668,7 @@ function combineLatest() { /***/ }), -/* 409 */ +/* 413 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -52328,7 +52688,7 @@ function concat() { /***/ }), -/* 410 */ +/* 414 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -52344,13 +52704,13 @@ function concatMap(project, resultSelector) { /***/ }), -/* 411 */ +/* 415 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "concatMapTo", function() { return concatMapTo; }); -/* harmony import */ var _concatMap__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(410); +/* harmony import */ var _concatMap__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(414); /** PURE_IMPORTS_START _concatMap PURE_IMPORTS_END */ function concatMapTo(innerObservable, resultSelector) { @@ -52360,7 +52720,7 @@ function concatMapTo(innerObservable, resultSelector) { /***/ }), -/* 412 */ +/* 416 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -52425,17 +52785,15 @@ var CountSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 413 */ +/* 417 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "debounce", function() { return debounce; }); /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(12); -/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(69); -/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(70); -/** PURE_IMPORTS_START tslib,_OuterSubscriber,_util_subscribeToResult PURE_IMPORTS_END */ - +/* harmony import */ var _innerSubscribe__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(90); +/** PURE_IMPORTS_START tslib,_innerSubscribe PURE_IMPORTS_END */ function debounce(durationSelector) { @@ -52456,7 +52814,6 @@ var DebounceSubscriber = /*@__PURE__*/ (function (_super) { var _this = _super.call(this, destination) || this; _this.durationSelector = durationSelector; _this.hasValue = false; - _this.durationSubscription = null; return _this; } DebounceSubscriber.prototype._next = function (value) { @@ -52482,12 +52839,12 @@ var DebounceSubscriber = /*@__PURE__*/ (function (_super) { subscription.unsubscribe(); this.remove(subscription); } - subscription = Object(_util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__["subscribeToResult"])(this, duration); + subscription = Object(_innerSubscribe__WEBPACK_IMPORTED_MODULE_1__["innerSubscribe"])(duration, new _innerSubscribe__WEBPACK_IMPORTED_MODULE_1__["SimpleInnerSubscriber"](this)); if (subscription && !subscription.closed) { this.add(this.durationSubscription = subscription); } }; - DebounceSubscriber.prototype.notifyNext = function (outerValue, innerValue, outerIndex, innerIndex, innerSub) { + DebounceSubscriber.prototype.notifyNext = function () { this.emitValue(); }; DebounceSubscriber.prototype.notifyComplete = function () { @@ -52498,22 +52855,22 @@ var DebounceSubscriber = /*@__PURE__*/ (function (_super) { var value = this.value; var subscription = this.durationSubscription; if (subscription) { - this.durationSubscription = null; + this.durationSubscription = undefined; subscription.unsubscribe(); this.remove(subscription); } - this.value = null; + this.value = undefined; this.hasValue = false; _super.prototype._next.call(this, value); } }; return DebounceSubscriber; -}(_OuterSubscriber__WEBPACK_IMPORTED_MODULE_1__["OuterSubscriber"])); +}(_innerSubscribe__WEBPACK_IMPORTED_MODULE_1__["SimpleOuterSubscriber"])); //# sourceMappingURL=debounce.js.map /***/ }), -/* 414 */ +/* 418 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -52589,7 +52946,7 @@ function dispatchNext(subscriber) { /***/ }), -/* 415 */ +/* 419 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -52639,7 +52996,7 @@ var DefaultIfEmptySubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 416 */ +/* 420 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -52647,7 +53004,7 @@ __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "delay", function() { return delay; }); /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(12); /* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(55); -/* harmony import */ var _util_isDate__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(417); +/* harmony import */ var _util_isDate__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(421); /* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(11); /* harmony import */ var _Notification__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(42); /** PURE_IMPORTS_START tslib,_scheduler_async,_util_isDate,_Subscriber,_Notification PURE_IMPORTS_END */ @@ -52746,7 +53103,7 @@ var DelayMessage = /*@__PURE__*/ (function () { /***/ }), -/* 417 */ +/* 421 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -52760,7 +53117,7 @@ function isDate(value) { /***/ }), -/* 418 */ +/* 422 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -52805,7 +53162,7 @@ var DelayWhenSubscriber = /*@__PURE__*/ (function (_super) { _this.index = 0; return _this; } - DelayWhenSubscriber.prototype.notifyNext = function (outerValue, innerValue, outerIndex, innerIndex, innerSub) { + DelayWhenSubscriber.prototype.notifyNext = function (outerValue, _innerValue, _outerIndex, _innerIndex, innerSub) { this.destination.next(outerValue); this.removeSubscription(innerSub); this.tryComplete(); @@ -52906,7 +53263,7 @@ var SubscriptionDelaySubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 419 */ +/* 423 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -52944,7 +53301,7 @@ var DeMaterializeSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 420 */ +/* 424 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -52952,10 +53309,8 @@ __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "distinct", function() { return distinct; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "DistinctSubscriber", function() { return DistinctSubscriber; }); /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(12); -/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(69); -/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(70); -/** PURE_IMPORTS_START tslib,_OuterSubscriber,_util_subscribeToResult PURE_IMPORTS_END */ - +/* harmony import */ var _innerSubscribe__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(90); +/** PURE_IMPORTS_START tslib,_innerSubscribe PURE_IMPORTS_END */ function distinct(keySelector, flushes) { @@ -52978,14 +53333,14 @@ var DistinctSubscriber = /*@__PURE__*/ (function (_super) { _this.keySelector = keySelector; _this.values = new Set(); if (flushes) { - _this.add(Object(_util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__["subscribeToResult"])(_this, flushes)); + _this.add(Object(_innerSubscribe__WEBPACK_IMPORTED_MODULE_1__["innerSubscribe"])(flushes, new _innerSubscribe__WEBPACK_IMPORTED_MODULE_1__["SimpleInnerSubscriber"](_this))); } return _this; } - DistinctSubscriber.prototype.notifyNext = function (outerValue, innerValue, outerIndex, innerIndex, innerSub) { + DistinctSubscriber.prototype.notifyNext = function () { this.values.clear(); }; - DistinctSubscriber.prototype.notifyError = function (error, innerSub) { + DistinctSubscriber.prototype.notifyError = function (error) { this._error(error); }; DistinctSubscriber.prototype._next = function (value) { @@ -53016,13 +53371,13 @@ var DistinctSubscriber = /*@__PURE__*/ (function (_super) { } }; return DistinctSubscriber; -}(_OuterSubscriber__WEBPACK_IMPORTED_MODULE_1__["OuterSubscriber"])); +}(_innerSubscribe__WEBPACK_IMPORTED_MODULE_1__["SimpleOuterSubscriber"])); //# sourceMappingURL=distinct.js.map /***/ }), -/* 421 */ +/* 425 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -53093,13 +53448,13 @@ var DistinctUntilChangedSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 422 */ +/* 426 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "distinctUntilKeyChanged", function() { return distinctUntilKeyChanged; }); -/* harmony import */ var _distinctUntilChanged__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(421); +/* harmony import */ var _distinctUntilChanged__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(425); /** PURE_IMPORTS_START _distinctUntilChanged PURE_IMPORTS_END */ function distinctUntilKeyChanged(key, compare) { @@ -53109,17 +53464,17 @@ function distinctUntilKeyChanged(key, compare) { /***/ }), -/* 423 */ +/* 427 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "elementAt", function() { return elementAt; }); /* harmony import */ var _util_ArgumentOutOfRangeError__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(62); -/* harmony import */ var _filter__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(104); -/* harmony import */ var _throwIfEmpty__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(424); -/* harmony import */ var _defaultIfEmpty__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(415); -/* harmony import */ var _take__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(425); +/* harmony import */ var _filter__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(105); +/* harmony import */ var _throwIfEmpty__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(428); +/* harmony import */ var _defaultIfEmpty__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(419); +/* harmony import */ var _take__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(429); /** PURE_IMPORTS_START _util_ArgumentOutOfRangeError,_filter,_throwIfEmpty,_defaultIfEmpty,_take PURE_IMPORTS_END */ @@ -53141,7 +53496,7 @@ function elementAt(index, defaultValue) { /***/ }), -/* 424 */ +/* 428 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -53207,7 +53562,7 @@ function defaultErrorFactory() { /***/ }), -/* 425 */ +/* 429 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -53269,7 +53624,7 @@ var TakeSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 426 */ +/* 430 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -53291,7 +53646,7 @@ function endWith() { /***/ }), -/* 427 */ +/* 431 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -53353,17 +53708,15 @@ var EverySubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 428 */ +/* 432 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "exhaust", function() { return exhaust; }); /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(12); -/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(69); -/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(70); -/** PURE_IMPORTS_START tslib,_OuterSubscriber,_util_subscribeToResult PURE_IMPORTS_END */ - +/* harmony import */ var _innerSubscribe__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(90); +/** PURE_IMPORTS_START tslib,_innerSubscribe PURE_IMPORTS_END */ function exhaust() { @@ -53388,7 +53741,7 @@ var SwitchFirstSubscriber = /*@__PURE__*/ (function (_super) { SwitchFirstSubscriber.prototype._next = function (value) { if (!this.hasSubscription) { this.hasSubscription = true; - this.add(Object(_util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__["subscribeToResult"])(this, value)); + this.add(Object(_innerSubscribe__WEBPACK_IMPORTED_MODULE_1__["innerSubscribe"])(value, new _innerSubscribe__WEBPACK_IMPORTED_MODULE_1__["SimpleInnerSubscriber"](this))); } }; SwitchFirstSubscriber.prototype._complete = function () { @@ -53397,41 +53750,36 @@ var SwitchFirstSubscriber = /*@__PURE__*/ (function (_super) { this.destination.complete(); } }; - SwitchFirstSubscriber.prototype.notifyComplete = function (innerSub) { - this.remove(innerSub); + SwitchFirstSubscriber.prototype.notifyComplete = function () { this.hasSubscription = false; if (this.hasCompleted) { this.destination.complete(); } }; return SwitchFirstSubscriber; -}(_OuterSubscriber__WEBPACK_IMPORTED_MODULE_1__["OuterSubscriber"])); +}(_innerSubscribe__WEBPACK_IMPORTED_MODULE_1__["SimpleOuterSubscriber"])); //# sourceMappingURL=exhaust.js.map /***/ }), -/* 429 */ +/* 433 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "exhaustMap", function() { return exhaustMap; }); /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(12); -/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(69); -/* harmony import */ var _InnerSubscriber__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(71); -/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(70); -/* harmony import */ var _map__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(66); -/* harmony import */ var _observable_from__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(83); -/** PURE_IMPORTS_START tslib,_OuterSubscriber,_InnerSubscriber,_util_subscribeToResult,_map,_observable_from PURE_IMPORTS_END */ - - +/* harmony import */ var _map__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(66); +/* harmony import */ var _observable_from__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(83); +/* harmony import */ var _innerSubscribe__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(90); +/** PURE_IMPORTS_START tslib,_map,_observable_from,_innerSubscribe PURE_IMPORTS_END */ function exhaustMap(project, resultSelector) { if (resultSelector) { - return function (source) { return source.pipe(exhaustMap(function (a, i) { return Object(_observable_from__WEBPACK_IMPORTED_MODULE_5__["from"])(project(a, i)).pipe(Object(_map__WEBPACK_IMPORTED_MODULE_4__["map"])(function (b, ii) { return resultSelector(a, b, i, ii); })); })); }; + return function (source) { return source.pipe(exhaustMap(function (a, i) { return Object(_observable_from__WEBPACK_IMPORTED_MODULE_2__["from"])(project(a, i)).pipe(Object(_map__WEBPACK_IMPORTED_MODULE_1__["map"])(function (b, ii) { return resultSelector(a, b, i, ii); })); })); }; } return function (source) { return source.lift(new ExhaustMapOperator(project)); @@ -53472,13 +53820,13 @@ var ExhaustMapSubscriber = /*@__PURE__*/ (function (_super) { return; } this.hasSubscription = true; - this._innerSub(result, value, index); + this._innerSub(result); }; - ExhaustMapSubscriber.prototype._innerSub = function (result, value, index) { - var innerSubscriber = new _InnerSubscriber__WEBPACK_IMPORTED_MODULE_2__["InnerSubscriber"](this, value, index); + ExhaustMapSubscriber.prototype._innerSub = function (result) { + var innerSubscriber = new _innerSubscribe__WEBPACK_IMPORTED_MODULE_3__["SimpleInnerSubscriber"](this); var destination = this.destination; destination.add(innerSubscriber); - var innerSubscription = Object(_util_subscribeToResult__WEBPACK_IMPORTED_MODULE_3__["subscribeToResult"])(this, result, undefined, undefined, innerSubscriber); + var innerSubscription = Object(_innerSubscribe__WEBPACK_IMPORTED_MODULE_3__["innerSubscribe"])(result, innerSubscriber); if (innerSubscription !== innerSubscriber) { destination.add(innerSubscription); } @@ -53490,27 +53838,25 @@ var ExhaustMapSubscriber = /*@__PURE__*/ (function (_super) { } this.unsubscribe(); }; - ExhaustMapSubscriber.prototype.notifyNext = function (outerValue, innerValue, outerIndex, innerIndex, innerSub) { + ExhaustMapSubscriber.prototype.notifyNext = function (innerValue) { this.destination.next(innerValue); }; ExhaustMapSubscriber.prototype.notifyError = function (err) { this.destination.error(err); }; - ExhaustMapSubscriber.prototype.notifyComplete = function (innerSub) { - var destination = this.destination; - destination.remove(innerSub); + ExhaustMapSubscriber.prototype.notifyComplete = function () { this.hasSubscription = false; if (this.hasCompleted) { this.destination.complete(); } }; return ExhaustMapSubscriber; -}(_OuterSubscriber__WEBPACK_IMPORTED_MODULE_1__["OuterSubscriber"])); +}(_innerSubscribe__WEBPACK_IMPORTED_MODULE_3__["SimpleOuterSubscriber"])); //# sourceMappingURL=exhaustMap.js.map /***/ }), -/* 430 */ +/* 434 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -53519,19 +53865,14 @@ __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ExpandOperator", function() { return ExpandOperator; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ExpandSubscriber", function() { return ExpandSubscriber; }); /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(12); -/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(69); -/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(70); -/** PURE_IMPORTS_START tslib,_OuterSubscriber,_util_subscribeToResult PURE_IMPORTS_END */ - +/* harmony import */ var _innerSubscribe__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(90); +/** PURE_IMPORTS_START tslib,_innerSubscribe PURE_IMPORTS_END */ function expand(project, concurrent, scheduler) { if (concurrent === void 0) { concurrent = Number.POSITIVE_INFINITY; } - if (scheduler === void 0) { - scheduler = undefined; - } concurrent = (concurrent || 0) < 1 ? Number.POSITIVE_INFINITY : concurrent; return function (source) { return source.lift(new ExpandOperator(project, concurrent, scheduler)); }; } @@ -53598,7 +53939,7 @@ var ExpandSubscriber = /*@__PURE__*/ (function (_super) { ExpandSubscriber.prototype.subscribeToProjection = function (result, value, index) { this.active++; var destination = this.destination; - destination.add(Object(_util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__["subscribeToResult"])(this, result, value, index)); + destination.add(Object(_innerSubscribe__WEBPACK_IMPORTED_MODULE_1__["innerSubscribe"])(result, new _innerSubscribe__WEBPACK_IMPORTED_MODULE_1__["SimpleInnerSubscriber"](this))); }; ExpandSubscriber.prototype._complete = function () { this.hasCompleted = true; @@ -53607,13 +53948,11 @@ var ExpandSubscriber = /*@__PURE__*/ (function (_super) { } this.unsubscribe(); }; - ExpandSubscriber.prototype.notifyNext = function (outerValue, innerValue, outerIndex, innerIndex, innerSub) { + ExpandSubscriber.prototype.notifyNext = function (innerValue) { this._next(innerValue); }; - ExpandSubscriber.prototype.notifyComplete = function (innerSub) { + ExpandSubscriber.prototype.notifyComplete = function () { var buffer = this.buffer; - var destination = this.destination; - destination.remove(innerSub); this.active--; if (buffer && buffer.length > 0) { this._next(buffer.shift()); @@ -53623,13 +53962,13 @@ var ExpandSubscriber = /*@__PURE__*/ (function (_super) { } }; return ExpandSubscriber; -}(_OuterSubscriber__WEBPACK_IMPORTED_MODULE_1__["OuterSubscriber"])); +}(_innerSubscribe__WEBPACK_IMPORTED_MODULE_1__["SimpleOuterSubscriber"])); //# sourceMappingURL=expand.js.map /***/ }), -/* 431 */ +/* 435 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -53667,7 +54006,7 @@ var FinallySubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 432 */ +/* 436 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -53739,13 +54078,13 @@ var FindValueSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 433 */ +/* 437 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "findIndex", function() { return findIndex; }); -/* harmony import */ var _operators_find__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(432); +/* harmony import */ var _operators_find__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(436); /** PURE_IMPORTS_START _operators_find PURE_IMPORTS_END */ function findIndex(predicate, thisArg) { @@ -53755,17 +54094,17 @@ function findIndex(predicate, thisArg) { /***/ }), -/* 434 */ +/* 438 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "first", function() { return first; }); /* harmony import */ var _util_EmptyError__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(63); -/* harmony import */ var _filter__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(104); -/* harmony import */ var _take__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(425); -/* harmony import */ var _defaultIfEmpty__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(415); -/* harmony import */ var _throwIfEmpty__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(424); +/* harmony import */ var _filter__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(105); +/* harmony import */ var _take__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(429); +/* harmony import */ var _defaultIfEmpty__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(419); +/* harmony import */ var _throwIfEmpty__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(428); /* harmony import */ var _util_identity__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(25); /** PURE_IMPORTS_START _util_EmptyError,_filter,_take,_defaultIfEmpty,_throwIfEmpty,_util_identity PURE_IMPORTS_END */ @@ -53782,7 +54121,7 @@ function first(predicate, defaultValue) { /***/ }), -/* 435 */ +/* 439 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -53819,7 +54158,7 @@ var IgnoreElementsSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 436 */ +/* 440 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -53863,17 +54202,17 @@ var IsEmptySubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 437 */ +/* 441 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "last", function() { return last; }); /* harmony import */ var _util_EmptyError__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(63); -/* harmony import */ var _filter__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(104); -/* harmony import */ var _takeLast__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(438); -/* harmony import */ var _throwIfEmpty__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(424); -/* harmony import */ var _defaultIfEmpty__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(415); +/* harmony import */ var _filter__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(105); +/* harmony import */ var _takeLast__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(442); +/* harmony import */ var _throwIfEmpty__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(428); +/* harmony import */ var _defaultIfEmpty__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(419); /* harmony import */ var _util_identity__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(25); /** PURE_IMPORTS_START _util_EmptyError,_filter,_takeLast,_throwIfEmpty,_defaultIfEmpty,_util_identity PURE_IMPORTS_END */ @@ -53890,7 +54229,7 @@ function last(predicate, defaultValue) { /***/ }), -/* 438 */ +/* 442 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -53967,7 +54306,7 @@ var TakeLastSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 439 */ +/* 443 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -54006,7 +54345,7 @@ var MapToSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 440 */ +/* 444 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -54056,13 +54395,13 @@ var MaterializeSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 441 */ +/* 445 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "max", function() { return max; }); -/* harmony import */ var _reduce__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(442); +/* harmony import */ var _reduce__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(446); /** PURE_IMPORTS_START _reduce PURE_IMPORTS_END */ function max(comparer) { @@ -54075,15 +54414,15 @@ function max(comparer) { /***/ }), -/* 442 */ +/* 446 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "reduce", function() { return reduce; }); -/* harmony import */ var _scan__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(443); -/* harmony import */ var _takeLast__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(438); -/* harmony import */ var _defaultIfEmpty__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(415); +/* harmony import */ var _scan__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(447); +/* harmony import */ var _takeLast__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(442); +/* harmony import */ var _defaultIfEmpty__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(419); /* harmony import */ var _util_pipe__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(24); /** PURE_IMPORTS_START _scan,_takeLast,_defaultIfEmpty,_util_pipe PURE_IMPORTS_END */ @@ -54104,7 +54443,7 @@ function reduce(accumulator, seed) { /***/ }), -/* 443 */ +/* 447 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -54186,13 +54525,13 @@ var ScanSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 444 */ +/* 448 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "merge", function() { return merge; }); -/* harmony import */ var _observable_merge__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(98); +/* harmony import */ var _observable_merge__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(99); /** PURE_IMPORTS_START _observable_merge PURE_IMPORTS_END */ function merge() { @@ -54206,7 +54545,7 @@ function merge() { /***/ }), -/* 445 */ +/* 449 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -54231,7 +54570,7 @@ function mergeMapTo(innerObservable, resultSelector, concurrent) { /***/ }), -/* 446 */ +/* 450 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -54240,12 +54579,8 @@ __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "MergeScanOperator", function() { return MergeScanOperator; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "MergeScanSubscriber", function() { return MergeScanSubscriber; }); /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(12); -/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(70); -/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(69); -/* harmony import */ var _InnerSubscriber__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(71); -/** PURE_IMPORTS_START tslib,_util_subscribeToResult,_OuterSubscriber,_InnerSubscriber PURE_IMPORTS_END */ - - +/* harmony import */ var _innerSubscribe__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(90); +/** PURE_IMPORTS_START tslib,_innerSubscribe PURE_IMPORTS_END */ function mergeScan(accumulator, seed, concurrent) { @@ -54293,17 +54628,17 @@ var MergeScanSubscriber = /*@__PURE__*/ (function (_super) { return destination.error(e); } this.active++; - this._innerSub(ish, value, index); + this._innerSub(ish); } else { this.buffer.push(value); } }; - MergeScanSubscriber.prototype._innerSub = function (ish, value, index) { - var innerSubscriber = new _InnerSubscriber__WEBPACK_IMPORTED_MODULE_3__["InnerSubscriber"](this, value, index); + MergeScanSubscriber.prototype._innerSub = function (ish) { + var innerSubscriber = new _innerSubscribe__WEBPACK_IMPORTED_MODULE_1__["SimpleInnerSubscriber"](this); var destination = this.destination; destination.add(innerSubscriber); - var innerSubscription = Object(_util_subscribeToResult__WEBPACK_IMPORTED_MODULE_1__["subscribeToResult"])(this, ish, undefined, undefined, innerSubscriber); + var innerSubscription = Object(_innerSubscribe__WEBPACK_IMPORTED_MODULE_1__["innerSubscribe"])(ish, innerSubscriber); if (innerSubscription !== innerSubscriber) { destination.add(innerSubscription); } @@ -54318,16 +54653,14 @@ var MergeScanSubscriber = /*@__PURE__*/ (function (_super) { } this.unsubscribe(); }; - MergeScanSubscriber.prototype.notifyNext = function (outerValue, innerValue, outerIndex, innerIndex, innerSub) { + MergeScanSubscriber.prototype.notifyNext = function (innerValue) { var destination = this.destination; this.acc = innerValue; this.hasValue = true; destination.next(innerValue); }; - MergeScanSubscriber.prototype.notifyComplete = function (innerSub) { + MergeScanSubscriber.prototype.notifyComplete = function () { var buffer = this.buffer; - var destination = this.destination; - destination.remove(innerSub); this.active--; if (buffer.length > 0) { this._next(buffer.shift()); @@ -54340,19 +54673,19 @@ var MergeScanSubscriber = /*@__PURE__*/ (function (_super) { } }; return MergeScanSubscriber; -}(_OuterSubscriber__WEBPACK_IMPORTED_MODULE_2__["OuterSubscriber"])); +}(_innerSubscribe__WEBPACK_IMPORTED_MODULE_1__["SimpleOuterSubscriber"])); //# sourceMappingURL=mergeScan.js.map /***/ }), -/* 447 */ +/* 451 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "min", function() { return min; }); -/* harmony import */ var _reduce__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(442); +/* harmony import */ var _reduce__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(446); /** PURE_IMPORTS_START _reduce PURE_IMPORTS_END */ function min(comparer) { @@ -54365,7 +54698,7 @@ function min(comparer) { /***/ }), -/* 448 */ +/* 452 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -54414,7 +54747,7 @@ var MulticastOperator = /*@__PURE__*/ (function () { /***/ }), -/* 449 */ +/* 453 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -54424,12 +54757,8 @@ __webpack_require__.r(__webpack_exports__); /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(12); /* harmony import */ var _observable_from__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(83); /* harmony import */ var _util_isArray__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(18); -/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(69); -/* harmony import */ var _InnerSubscriber__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(71); -/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(70); -/** PURE_IMPORTS_START tslib,_observable_from,_util_isArray,_OuterSubscriber,_InnerSubscriber,_util_subscribeToResult PURE_IMPORTS_END */ - - +/* harmony import */ var _innerSubscribe__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(90); +/** PURE_IMPORTS_START tslib,_observable_from,_util_isArray,_innerSubscribe PURE_IMPORTS_END */ @@ -54449,12 +54778,12 @@ function onErrorResumeNextStatic() { for (var _i = 0; _i < arguments.length; _i++) { nextSources[_i] = arguments[_i]; } - var source = null; + var source = undefined; if (nextSources.length === 1 && Object(_util_isArray__WEBPACK_IMPORTED_MODULE_2__["isArray"])(nextSources[0])) { nextSources = nextSources[0]; } source = nextSources.shift(); - return Object(_observable_from__WEBPACK_IMPORTED_MODULE_1__["from"])(source, null).lift(new OnErrorResumeNextOperator(nextSources)); + return Object(_observable_from__WEBPACK_IMPORTED_MODULE_1__["from"])(source).lift(new OnErrorResumeNextOperator(nextSources)); } var OnErrorResumeNextOperator = /*@__PURE__*/ (function () { function OnErrorResumeNextOperator(nextSources) { @@ -54473,10 +54802,10 @@ var OnErrorResumeNextSubscriber = /*@__PURE__*/ (function (_super) { _this.nextSources = nextSources; return _this; } - OnErrorResumeNextSubscriber.prototype.notifyError = function (error, innerSub) { + OnErrorResumeNextSubscriber.prototype.notifyError = function () { this.subscribeToNextSource(); }; - OnErrorResumeNextSubscriber.prototype.notifyComplete = function (innerSub) { + OnErrorResumeNextSubscriber.prototype.notifyComplete = function () { this.subscribeToNextSource(); }; OnErrorResumeNextSubscriber.prototype._error = function (err) { @@ -54490,10 +54819,10 @@ var OnErrorResumeNextSubscriber = /*@__PURE__*/ (function (_super) { OnErrorResumeNextSubscriber.prototype.subscribeToNextSource = function () { var next = this.nextSources.shift(); if (!!next) { - var innerSubscriber = new _InnerSubscriber__WEBPACK_IMPORTED_MODULE_4__["InnerSubscriber"](this, undefined, undefined); + var innerSubscriber = new _innerSubscribe__WEBPACK_IMPORTED_MODULE_3__["SimpleInnerSubscriber"](this); var destination = this.destination; destination.add(innerSubscriber); - var innerSubscription = Object(_util_subscribeToResult__WEBPACK_IMPORTED_MODULE_5__["subscribeToResult"])(this, next, undefined, undefined, innerSubscriber); + var innerSubscription = Object(_innerSubscribe__WEBPACK_IMPORTED_MODULE_3__["innerSubscribe"])(next, innerSubscriber); if (innerSubscription !== innerSubscriber) { destination.add(innerSubscription); } @@ -54503,12 +54832,12 @@ var OnErrorResumeNextSubscriber = /*@__PURE__*/ (function (_super) { } }; return OnErrorResumeNextSubscriber; -}(_OuterSubscriber__WEBPACK_IMPORTED_MODULE_3__["OuterSubscriber"])); +}(_innerSubscribe__WEBPACK_IMPORTED_MODULE_3__["SimpleOuterSubscriber"])); //# sourceMappingURL=onErrorResumeNext.js.map /***/ }), -/* 450 */ +/* 454 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -54556,14 +54885,14 @@ var PairwiseSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 451 */ +/* 455 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "partition", function() { return partition; }); -/* harmony import */ var _util_not__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(103); -/* harmony import */ var _filter__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(104); +/* harmony import */ var _util_not__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(104); +/* harmony import */ var _filter__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(105); /** PURE_IMPORTS_START _util_not,_filter PURE_IMPORTS_END */ @@ -54579,7 +54908,7 @@ function partition(predicate, thisArg) { /***/ }), -/* 452 */ +/* 456 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -54603,8 +54932,8 @@ function plucker(props, length) { var mapper = function (x) { var currentProp = x; for (var i = 0; i < length; i++) { - var p = currentProp[props[i]]; - if (typeof p !== 'undefined') { + var p = currentProp != null ? currentProp[props[i]] : undefined; + if (p !== void 0) { currentProp = p; } else { @@ -54619,14 +54948,14 @@ function plucker(props, length) { /***/ }), -/* 453 */ +/* 457 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "publish", function() { return publish; }); /* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(27); -/* harmony import */ var _multicast__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(448); +/* harmony import */ var _multicast__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(452); /** PURE_IMPORTS_START _Subject,_multicast PURE_IMPORTS_END */ @@ -54639,14 +54968,14 @@ function publish(selector) { /***/ }), -/* 454 */ +/* 458 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "publishBehavior", function() { return publishBehavior; }); /* harmony import */ var _BehaviorSubject__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(32); -/* harmony import */ var _multicast__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(448); +/* harmony import */ var _multicast__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(452); /** PURE_IMPORTS_START _BehaviorSubject,_multicast PURE_IMPORTS_END */ @@ -54657,14 +54986,14 @@ function publishBehavior(value) { /***/ }), -/* 455 */ +/* 459 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "publishLast", function() { return publishLast; }); /* harmony import */ var _AsyncSubject__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(50); -/* harmony import */ var _multicast__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(448); +/* harmony import */ var _multicast__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(452); /** PURE_IMPORTS_START _AsyncSubject,_multicast PURE_IMPORTS_END */ @@ -54675,14 +55004,14 @@ function publishLast() { /***/ }), -/* 456 */ +/* 460 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "publishReplay", function() { return publishReplay; }); /* harmony import */ var _ReplaySubject__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(33); -/* harmony import */ var _multicast__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(448); +/* harmony import */ var _multicast__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(452); /** PURE_IMPORTS_START _ReplaySubject,_multicast PURE_IMPORTS_END */ @@ -54698,14 +55027,14 @@ function publishReplay(bufferSize, windowTime, selectorOrScheduler, scheduler) { /***/ }), -/* 457 */ +/* 461 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "race", function() { return race; }); /* harmony import */ var _util_isArray__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(18); -/* harmony import */ var _observable_race__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(105); +/* harmony import */ var _observable_race__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(106); /** PURE_IMPORTS_START _util_isArray,_observable_race PURE_IMPORTS_END */ @@ -54725,7 +55054,7 @@ function race() { /***/ }), -/* 458 */ +/* 462 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -54790,7 +55119,7 @@ var RepeatSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 459 */ +/* 463 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -54798,10 +55127,8 @@ __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "repeatWhen", function() { return repeatWhen; }); /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(12); /* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(27); -/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(69); -/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(70); -/** PURE_IMPORTS_START tslib,_Subject,_OuterSubscriber,_util_subscribeToResult PURE_IMPORTS_END */ - +/* harmony import */ var _innerSubscribe__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(90); +/** PURE_IMPORTS_START tslib,_Subject,_innerSubscribe PURE_IMPORTS_END */ @@ -54826,11 +55153,11 @@ var RepeatWhenSubscriber = /*@__PURE__*/ (function (_super) { _this.sourceIsBeingSubscribedTo = true; return _this; } - RepeatWhenSubscriber.prototype.notifyNext = function (outerValue, innerValue, outerIndex, innerIndex, innerSub) { + RepeatWhenSubscriber.prototype.notifyNext = function () { this.sourceIsBeingSubscribedTo = true; this.source.subscribe(this); }; - RepeatWhenSubscriber.prototype.notifyComplete = function (innerSub) { + RepeatWhenSubscriber.prototype.notifyComplete = function () { if (this.sourceIsBeingSubscribedTo === false) { return _super.prototype.complete.call(this); } @@ -54845,20 +55172,20 @@ var RepeatWhenSubscriber = /*@__PURE__*/ (function (_super) { return _super.prototype.complete.call(this); } this._unsubscribeAndRecycle(); - this.notifications.next(); + this.notifications.next(undefined); } }; RepeatWhenSubscriber.prototype._unsubscribe = function () { var _a = this, notifications = _a.notifications, retriesSubscription = _a.retriesSubscription; if (notifications) { notifications.unsubscribe(); - this.notifications = null; + this.notifications = undefined; } if (retriesSubscription) { retriesSubscription.unsubscribe(); - this.retriesSubscription = null; + this.retriesSubscription = undefined; } - this.retries = null; + this.retries = undefined; }; RepeatWhenSubscriber.prototype._unsubscribeAndRecycle = function () { var _unsubscribe = this._unsubscribe; @@ -54878,15 +55205,15 @@ var RepeatWhenSubscriber = /*@__PURE__*/ (function (_super) { return _super.prototype.complete.call(this); } this.retries = retries; - this.retriesSubscription = Object(_util_subscribeToResult__WEBPACK_IMPORTED_MODULE_3__["subscribeToResult"])(this, retries); + this.retriesSubscription = Object(_innerSubscribe__WEBPACK_IMPORTED_MODULE_2__["innerSubscribe"])(retries, new _innerSubscribe__WEBPACK_IMPORTED_MODULE_2__["SimpleInnerSubscriber"](this)); }; return RepeatWhenSubscriber; -}(_OuterSubscriber__WEBPACK_IMPORTED_MODULE_2__["OuterSubscriber"])); +}(_innerSubscribe__WEBPACK_IMPORTED_MODULE_2__["SimpleOuterSubscriber"])); //# sourceMappingURL=repeatWhen.js.map /***/ }), -/* 460 */ +/* 464 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -54939,7 +55266,7 @@ var RetrySubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 461 */ +/* 465 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -54947,10 +55274,8 @@ __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "retryWhen", function() { return retryWhen; }); /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(12); /* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(27); -/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(69); -/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(70); -/** PURE_IMPORTS_START tslib,_Subject,_OuterSubscriber,_util_subscribeToResult PURE_IMPORTS_END */ - +/* harmony import */ var _innerSubscribe__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(90); +/** PURE_IMPORTS_START tslib,_Subject,_innerSubscribe PURE_IMPORTS_END */ @@ -54989,11 +55314,11 @@ var RetryWhenSubscriber = /*@__PURE__*/ (function (_super) { catch (e) { return _super.prototype.error.call(this, e); } - retriesSubscription = Object(_util_subscribeToResult__WEBPACK_IMPORTED_MODULE_3__["subscribeToResult"])(this, retries); + retriesSubscription = Object(_innerSubscribe__WEBPACK_IMPORTED_MODULE_2__["innerSubscribe"])(retries, new _innerSubscribe__WEBPACK_IMPORTED_MODULE_2__["SimpleInnerSubscriber"](this)); } else { - this.errors = null; - this.retriesSubscription = null; + this.errors = undefined; + this.retriesSubscription = undefined; } this._unsubscribeAndRecycle(); this.errors = errors; @@ -55006,15 +55331,15 @@ var RetryWhenSubscriber = /*@__PURE__*/ (function (_super) { var _a = this, errors = _a.errors, retriesSubscription = _a.retriesSubscription; if (errors) { errors.unsubscribe(); - this.errors = null; + this.errors = undefined; } if (retriesSubscription) { retriesSubscription.unsubscribe(); - this.retriesSubscription = null; + this.retriesSubscription = undefined; } - this.retries = null; + this.retries = undefined; }; - RetryWhenSubscriber.prototype.notifyNext = function (outerValue, innerValue, outerIndex, innerIndex, innerSub) { + RetryWhenSubscriber.prototype.notifyNext = function () { var _unsubscribe = this._unsubscribe; this._unsubscribe = null; this._unsubscribeAndRecycle(); @@ -55022,22 +55347,20 @@ var RetryWhenSubscriber = /*@__PURE__*/ (function (_super) { this.source.subscribe(this); }; return RetryWhenSubscriber; -}(_OuterSubscriber__WEBPACK_IMPORTED_MODULE_2__["OuterSubscriber"])); +}(_innerSubscribe__WEBPACK_IMPORTED_MODULE_2__["SimpleOuterSubscriber"])); //# sourceMappingURL=retryWhen.js.map /***/ }), -/* 462 */ +/* 466 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "sample", function() { return sample; }); /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(12); -/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(69); -/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(70); -/** PURE_IMPORTS_START tslib,_OuterSubscriber,_util_subscribeToResult PURE_IMPORTS_END */ - +/* harmony import */ var _innerSubscribe__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(90); +/** PURE_IMPORTS_START tslib,_innerSubscribe PURE_IMPORTS_END */ function sample(notifier) { @@ -55050,7 +55373,7 @@ var SampleOperator = /*@__PURE__*/ (function () { SampleOperator.prototype.call = function (subscriber, source) { var sampleSubscriber = new SampleSubscriber(subscriber); var subscription = source.subscribe(sampleSubscriber); - subscription.add(Object(_util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__["subscribeToResult"])(sampleSubscriber, this.notifier)); + subscription.add(Object(_innerSubscribe__WEBPACK_IMPORTED_MODULE_1__["innerSubscribe"])(this.notifier, new _innerSubscribe__WEBPACK_IMPORTED_MODULE_1__["SimpleInnerSubscriber"](sampleSubscriber))); return subscription; }; return SampleOperator; @@ -55066,7 +55389,7 @@ var SampleSubscriber = /*@__PURE__*/ (function (_super) { this.value = value; this.hasValue = true; }; - SampleSubscriber.prototype.notifyNext = function (outerValue, innerValue, outerIndex, innerIndex, innerSub) { + SampleSubscriber.prototype.notifyNext = function () { this.emitValue(); }; SampleSubscriber.prototype.notifyComplete = function () { @@ -55079,12 +55402,12 @@ var SampleSubscriber = /*@__PURE__*/ (function (_super) { } }; return SampleSubscriber; -}(_OuterSubscriber__WEBPACK_IMPORTED_MODULE_1__["OuterSubscriber"])); +}(_innerSubscribe__WEBPACK_IMPORTED_MODULE_1__["SimpleOuterSubscriber"])); //# sourceMappingURL=sample.js.map /***/ }), -/* 463 */ +/* 467 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -55144,7 +55467,7 @@ function dispatchNotification(state) { /***/ }), -/* 464 */ +/* 468 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -55267,13 +55590,13 @@ var SequenceEqualCompareToSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 465 */ +/* 469 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "share", function() { return share; }); -/* harmony import */ var _multicast__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(448); +/* harmony import */ var _multicast__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(452); /* harmony import */ var _refCount__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(30); /* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(27); /** PURE_IMPORTS_START _multicast,_refCount,_Subject PURE_IMPORTS_END */ @@ -55290,7 +55613,7 @@ function share() { /***/ }), -/* 466 */ +/* 470 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -55323,9 +55646,11 @@ function shareReplayOperator(_a) { var isComplete = false; return function shareReplayOperation(source) { refCount++; + var innerSub; if (!subject || hasError) { hasError = false; subject = new _ReplaySubject__WEBPACK_IMPORTED_MODULE_0__["ReplaySubject"](bufferSize, windowTime, scheduler); + innerSub = subject.subscribe(this); subscription = source.subscribe({ next: function (value) { subject.next(value); }, error: function (err) { @@ -55339,7 +55664,9 @@ function shareReplayOperator(_a) { }, }); } - var innerSub = subject.subscribe(this); + else { + innerSub = subject.subscribe(this); + } this.add(function () { refCount--; innerSub.unsubscribe(); @@ -55355,7 +55682,7 @@ function shareReplayOperator(_a) { /***/ }), -/* 467 */ +/* 471 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -55435,7 +55762,7 @@ var SingleSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 468 */ +/* 472 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -55477,7 +55804,7 @@ var SkipSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 469 */ +/* 473 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -55539,19 +55866,15 @@ var SkipLastSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 470 */ +/* 474 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "skipUntil", function() { return skipUntil; }); /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(12); -/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(69); -/* harmony import */ var _InnerSubscriber__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(71); -/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(70); -/** PURE_IMPORTS_START tslib,_OuterSubscriber,_InnerSubscriber,_util_subscribeToResult PURE_IMPORTS_END */ - - +/* harmony import */ var _innerSubscribe__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(90); +/** PURE_IMPORTS_START tslib,_innerSubscribe PURE_IMPORTS_END */ function skipUntil(notifier) { @@ -55571,10 +55894,10 @@ var SkipUntilSubscriber = /*@__PURE__*/ (function (_super) { function SkipUntilSubscriber(destination, notifier) { var _this = _super.call(this, destination) || this; _this.hasValue = false; - var innerSubscriber = new _InnerSubscriber__WEBPACK_IMPORTED_MODULE_2__["InnerSubscriber"](_this, undefined, undefined); + var innerSubscriber = new _innerSubscribe__WEBPACK_IMPORTED_MODULE_1__["SimpleInnerSubscriber"](_this); _this.add(innerSubscriber); _this.innerSubscription = innerSubscriber; - var innerSubscription = Object(_util_subscribeToResult__WEBPACK_IMPORTED_MODULE_3__["subscribeToResult"])(_this, notifier, undefined, undefined, innerSubscriber); + var innerSubscription = Object(_innerSubscribe__WEBPACK_IMPORTED_MODULE_1__["innerSubscribe"])(notifier, innerSubscriber); if (innerSubscription !== innerSubscriber) { _this.add(innerSubscription); _this.innerSubscription = innerSubscription; @@ -55586,7 +55909,7 @@ var SkipUntilSubscriber = /*@__PURE__*/ (function (_super) { _super.prototype._next.call(this, value); } }; - SkipUntilSubscriber.prototype.notifyNext = function (outerValue, innerValue, outerIndex, innerIndex, innerSub) { + SkipUntilSubscriber.prototype.notifyNext = function () { this.hasValue = true; if (this.innerSubscription) { this.innerSubscription.unsubscribe(); @@ -55595,12 +55918,12 @@ var SkipUntilSubscriber = /*@__PURE__*/ (function (_super) { SkipUntilSubscriber.prototype.notifyComplete = function () { }; return SkipUntilSubscriber; -}(_OuterSubscriber__WEBPACK_IMPORTED_MODULE_1__["OuterSubscriber"])); +}(_innerSubscribe__WEBPACK_IMPORTED_MODULE_1__["SimpleOuterSubscriber"])); //# sourceMappingURL=skipUntil.js.map /***/ }), -/* 471 */ +/* 475 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -55656,7 +55979,7 @@ var SkipWhileSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 472 */ +/* 476 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -55685,13 +56008,13 @@ function startWith() { /***/ }), -/* 473 */ +/* 477 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "subscribeOn", function() { return subscribeOn; }); -/* harmony import */ var _observable_SubscribeOnObservable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(474); +/* harmony import */ var _observable_SubscribeOnObservable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(478); /** PURE_IMPORTS_START _observable_SubscribeOnObservable PURE_IMPORTS_END */ function subscribeOn(scheduler, delay) { @@ -55716,7 +56039,7 @@ var SubscribeOnOperator = /*@__PURE__*/ (function () { /***/ }), -/* 474 */ +/* 478 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -55725,7 +56048,7 @@ __webpack_require__.r(__webpack_exports__); /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(12); /* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(9); /* harmony import */ var _scheduler_asap__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(51); -/* harmony import */ var _util_isNumeric__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(97); +/* harmony import */ var _util_isNumeric__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(98); /** PURE_IMPORTS_START tslib,_Observable,_scheduler_asap,_util_isNumeric PURE_IMPORTS_END */ @@ -55780,13 +56103,13 @@ var SubscribeOnObservable = /*@__PURE__*/ (function (_super) { /***/ }), -/* 475 */ +/* 479 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "switchAll", function() { return switchAll; }); -/* harmony import */ var _switchMap__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(476); +/* harmony import */ var _switchMap__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(480); /* harmony import */ var _util_identity__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(25); /** PURE_IMPORTS_START _switchMap,_util_identity PURE_IMPORTS_END */ @@ -55798,28 +56121,24 @@ function switchAll() { /***/ }), -/* 476 */ +/* 480 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "switchMap", function() { return switchMap; }); /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(12); -/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(69); -/* harmony import */ var _InnerSubscriber__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(71); -/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(70); -/* harmony import */ var _map__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(66); -/* harmony import */ var _observable_from__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(83); -/** PURE_IMPORTS_START tslib,_OuterSubscriber,_InnerSubscriber,_util_subscribeToResult,_map,_observable_from PURE_IMPORTS_END */ - - +/* harmony import */ var _map__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(66); +/* harmony import */ var _observable_from__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(83); +/* harmony import */ var _innerSubscribe__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(90); +/** PURE_IMPORTS_START tslib,_map,_observable_from,_innerSubscribe PURE_IMPORTS_END */ function switchMap(project, resultSelector) { if (typeof resultSelector === 'function') { - return function (source) { return source.pipe(switchMap(function (a, i) { return Object(_observable_from__WEBPACK_IMPORTED_MODULE_5__["from"])(project(a, i)).pipe(Object(_map__WEBPACK_IMPORTED_MODULE_4__["map"])(function (b, ii) { return resultSelector(a, b, i, ii); })); })); }; + return function (source) { return source.pipe(switchMap(function (a, i) { return Object(_observable_from__WEBPACK_IMPORTED_MODULE_2__["from"])(project(a, i)).pipe(Object(_map__WEBPACK_IMPORTED_MODULE_1__["map"])(function (b, ii) { return resultSelector(a, b, i, ii); })); })); }; } return function (source) { return source.lift(new SwitchMapOperator(project)); }; } @@ -55850,17 +56169,17 @@ var SwitchMapSubscriber = /*@__PURE__*/ (function (_super) { this.destination.error(error); return; } - this._innerSub(result, value, index); + this._innerSub(result); }; - SwitchMapSubscriber.prototype._innerSub = function (result, value, index) { + SwitchMapSubscriber.prototype._innerSub = function (result) { var innerSubscription = this.innerSubscription; if (innerSubscription) { innerSubscription.unsubscribe(); } - var innerSubscriber = new _InnerSubscriber__WEBPACK_IMPORTED_MODULE_2__["InnerSubscriber"](this, value, index); + var innerSubscriber = new _innerSubscribe__WEBPACK_IMPORTED_MODULE_3__["SimpleInnerSubscriber"](this); var destination = this.destination; destination.add(innerSubscriber); - this.innerSubscription = Object(_util_subscribeToResult__WEBPACK_IMPORTED_MODULE_3__["subscribeToResult"])(this, result, undefined, undefined, innerSubscriber); + this.innerSubscription = Object(_innerSubscribe__WEBPACK_IMPORTED_MODULE_3__["innerSubscribe"])(result, innerSubscriber); if (this.innerSubscription !== innerSubscriber) { destination.add(this.innerSubscription); } @@ -55873,32 +56192,30 @@ var SwitchMapSubscriber = /*@__PURE__*/ (function (_super) { this.unsubscribe(); }; SwitchMapSubscriber.prototype._unsubscribe = function () { - this.innerSubscription = null; + this.innerSubscription = undefined; }; - SwitchMapSubscriber.prototype.notifyComplete = function (innerSub) { - var destination = this.destination; - destination.remove(innerSub); - this.innerSubscription = null; + SwitchMapSubscriber.prototype.notifyComplete = function () { + this.innerSubscription = undefined; if (this.isStopped) { _super.prototype._complete.call(this); } }; - SwitchMapSubscriber.prototype.notifyNext = function (outerValue, innerValue, outerIndex, innerIndex, innerSub) { + SwitchMapSubscriber.prototype.notifyNext = function (innerValue) { this.destination.next(innerValue); }; return SwitchMapSubscriber; -}(_OuterSubscriber__WEBPACK_IMPORTED_MODULE_1__["OuterSubscriber"])); +}(_innerSubscribe__WEBPACK_IMPORTED_MODULE_3__["SimpleOuterSubscriber"])); //# sourceMappingURL=switchMap.js.map /***/ }), -/* 477 */ +/* 481 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "switchMapTo", function() { return switchMapTo; }); -/* harmony import */ var _switchMap__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(476); +/* harmony import */ var _switchMap__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(480); /** PURE_IMPORTS_START _switchMap PURE_IMPORTS_END */ function switchMapTo(innerObservable, resultSelector) { @@ -55908,17 +56225,15 @@ function switchMapTo(innerObservable, resultSelector) { /***/ }), -/* 478 */ +/* 482 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "takeUntil", function() { return takeUntil; }); /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(12); -/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(69); -/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(70); -/** PURE_IMPORTS_START tslib,_OuterSubscriber,_util_subscribeToResult PURE_IMPORTS_END */ - +/* harmony import */ var _innerSubscribe__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(90); +/** PURE_IMPORTS_START tslib,_innerSubscribe PURE_IMPORTS_END */ function takeUntil(notifier) { @@ -55930,7 +56245,7 @@ var TakeUntilOperator = /*@__PURE__*/ (function () { } TakeUntilOperator.prototype.call = function (subscriber, source) { var takeUntilSubscriber = new TakeUntilSubscriber(subscriber); - var notifierSubscription = Object(_util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__["subscribeToResult"])(takeUntilSubscriber, this.notifier); + var notifierSubscription = Object(_innerSubscribe__WEBPACK_IMPORTED_MODULE_1__["innerSubscribe"])(this.notifier, new _innerSubscribe__WEBPACK_IMPORTED_MODULE_1__["SimpleInnerSubscriber"](takeUntilSubscriber)); if (notifierSubscription && !takeUntilSubscriber.seenValue) { takeUntilSubscriber.add(notifierSubscription); return source.subscribe(takeUntilSubscriber); @@ -55946,19 +56261,19 @@ var TakeUntilSubscriber = /*@__PURE__*/ (function (_super) { _this.seenValue = false; return _this; } - TakeUntilSubscriber.prototype.notifyNext = function (outerValue, innerValue, outerIndex, innerIndex, innerSub) { + TakeUntilSubscriber.prototype.notifyNext = function () { this.seenValue = true; this.complete(); }; TakeUntilSubscriber.prototype.notifyComplete = function () { }; return TakeUntilSubscriber; -}(_OuterSubscriber__WEBPACK_IMPORTED_MODULE_1__["OuterSubscriber"])); +}(_innerSubscribe__WEBPACK_IMPORTED_MODULE_1__["SimpleOuterSubscriber"])); //# sourceMappingURL=takeUntil.js.map /***/ }), -/* 479 */ +/* 483 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -56026,7 +56341,7 @@ var TakeWhileSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 480 */ +/* 484 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -56114,7 +56429,7 @@ var TapSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 481 */ +/* 485 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -56122,10 +56437,8 @@ __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "defaultThrottleConfig", function() { return defaultThrottleConfig; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "throttle", function() { return throttle; }); /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(12); -/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(69); -/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(70); -/** PURE_IMPORTS_START tslib,_OuterSubscriber,_util_subscribeToResult PURE_IMPORTS_END */ - +/* harmony import */ var _innerSubscribe__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(90); +/** PURE_IMPORTS_START tslib,_innerSubscribe PURE_IMPORTS_END */ var defaultThrottleConfig = { @@ -56136,7 +56449,7 @@ function throttle(durationSelector, config) { if (config === void 0) { config = defaultThrottleConfig; } - return function (source) { return source.lift(new ThrottleOperator(durationSelector, config.leading, config.trailing)); }; + return function (source) { return source.lift(new ThrottleOperator(durationSelector, !!config.leading, !!config.trailing)); }; } var ThrottleOperator = /*@__PURE__*/ (function () { function ThrottleOperator(durationSelector, leading, trailing) { @@ -56179,12 +56492,12 @@ var ThrottleSubscriber = /*@__PURE__*/ (function (_super) { this.throttle(_sendValue); } this._hasValue = false; - this._sendValue = null; + this._sendValue = undefined; }; ThrottleSubscriber.prototype.throttle = function (value) { var duration = this.tryDurationSelector(value); if (!!duration) { - this.add(this._throttled = Object(_util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__["subscribeToResult"])(this, duration)); + this.add(this._throttled = Object(_innerSubscribe__WEBPACK_IMPORTED_MODULE_1__["innerSubscribe"])(duration, new _innerSubscribe__WEBPACK_IMPORTED_MODULE_1__["SimpleInnerSubscriber"](this))); } }; ThrottleSubscriber.prototype.tryDurationSelector = function (value) { @@ -56201,24 +56514,24 @@ var ThrottleSubscriber = /*@__PURE__*/ (function (_super) { if (_throttled) { _throttled.unsubscribe(); } - this._throttled = null; + this._throttled = undefined; if (_trailing) { this.send(); } }; - ThrottleSubscriber.prototype.notifyNext = function (outerValue, innerValue, outerIndex, innerIndex, innerSub) { + ThrottleSubscriber.prototype.notifyNext = function () { this.throttlingDone(); }; ThrottleSubscriber.prototype.notifyComplete = function () { this.throttlingDone(); }; return ThrottleSubscriber; -}(_OuterSubscriber__WEBPACK_IMPORTED_MODULE_1__["OuterSubscriber"])); +}(_innerSubscribe__WEBPACK_IMPORTED_MODULE_1__["SimpleOuterSubscriber"])); //# sourceMappingURL=throttle.js.map /***/ }), -/* 482 */ +/* 486 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -56227,7 +56540,7 @@ __webpack_require__.r(__webpack_exports__); /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(12); /* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(11); /* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(55); -/* harmony import */ var _throttle__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(481); +/* harmony import */ var _throttle__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(485); /** PURE_IMPORTS_START tslib,_Subscriber,_scheduler_async,_throttle PURE_IMPORTS_END */ @@ -56316,7 +56629,7 @@ function dispatchNext(arg) { /***/ }), -/* 483 */ +/* 487 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -56324,8 +56637,8 @@ __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "timeInterval", function() { return timeInterval; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "TimeInterval", function() { return TimeInterval; }); /* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(55); -/* harmony import */ var _scan__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(443); -/* harmony import */ var _observable_defer__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(90); +/* harmony import */ var _scan__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(447); +/* harmony import */ var _observable_defer__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(91); /* harmony import */ var _map__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(66); /** PURE_IMPORTS_START _scheduler_async,_scan,_observable_defer,_map PURE_IMPORTS_END */ @@ -56360,7 +56673,7 @@ var TimeInterval = /*@__PURE__*/ (function () { /***/ }), -/* 484 */ +/* 488 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -56368,7 +56681,7 @@ __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "timeout", function() { return timeout; }); /* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(55); /* harmony import */ var _util_TimeoutError__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(64); -/* harmony import */ var _timeoutWith__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(485); +/* harmony import */ var _timeoutWith__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(489); /* harmony import */ var _observable_throwError__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(49); /** PURE_IMPORTS_START _scheduler_async,_util_TimeoutError,_timeoutWith,_observable_throwError PURE_IMPORTS_END */ @@ -56385,7 +56698,7 @@ function timeout(due, scheduler) { /***/ }), -/* 485 */ +/* 489 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -56393,11 +56706,9 @@ __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "timeoutWith", function() { return timeoutWith; }); /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(12); /* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(55); -/* harmony import */ var _util_isDate__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(417); -/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(69); -/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(70); -/** PURE_IMPORTS_START tslib,_scheduler_async,_util_isDate,_OuterSubscriber,_util_subscribeToResult PURE_IMPORTS_END */ - +/* harmony import */ var _util_isDate__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(421); +/* harmony import */ var _innerSubscribe__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(90); +/** PURE_IMPORTS_START tslib,_scheduler_async,_util_isDate,_innerSubscribe PURE_IMPORTS_END */ @@ -56432,14 +56743,13 @@ var TimeoutWithSubscriber = /*@__PURE__*/ (function (_super) { _this.waitFor = waitFor; _this.withObservable = withObservable; _this.scheduler = scheduler; - _this.action = null; _this.scheduleTimeout(); return _this; } TimeoutWithSubscriber.dispatchTimeout = function (subscriber) { var withObservable = subscriber.withObservable; subscriber._unsubscribeAndRecycle(); - subscriber.add(Object(_util_subscribeToResult__WEBPACK_IMPORTED_MODULE_4__["subscribeToResult"])(subscriber, withObservable)); + subscriber.add(Object(_innerSubscribe__WEBPACK_IMPORTED_MODULE_3__["innerSubscribe"])(withObservable, new _innerSubscribe__WEBPACK_IMPORTED_MODULE_3__["SimpleInnerSubscriber"](subscriber))); }; TimeoutWithSubscriber.prototype.scheduleTimeout = function () { var action = this.action; @@ -56457,17 +56767,17 @@ var TimeoutWithSubscriber = /*@__PURE__*/ (function (_super) { _super.prototype._next.call(this, value); }; TimeoutWithSubscriber.prototype._unsubscribe = function () { - this.action = null; + this.action = undefined; this.scheduler = null; this.withObservable = null; }; return TimeoutWithSubscriber; -}(_OuterSubscriber__WEBPACK_IMPORTED_MODULE_3__["OuterSubscriber"])); +}(_innerSubscribe__WEBPACK_IMPORTED_MODULE_3__["SimpleOuterSubscriber"])); //# sourceMappingURL=timeoutWith.js.map /***/ }), -/* 486 */ +/* 490 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -56497,13 +56807,13 @@ var Timestamp = /*@__PURE__*/ (function () { /***/ }), -/* 487 */ +/* 491 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "toArray", function() { return toArray; }); -/* harmony import */ var _reduce__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(442); +/* harmony import */ var _reduce__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(446); /** PURE_IMPORTS_START _reduce PURE_IMPORTS_END */ function toArrayReducer(arr, item, index) { @@ -56520,7 +56830,7 @@ function toArray() { /***/ }), -/* 488 */ +/* 492 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -56528,10 +56838,8 @@ __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "window", function() { return window; }); /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(12); /* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(27); -/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(69); -/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(70); -/** PURE_IMPORTS_START tslib,_Subject,_OuterSubscriber,_util_subscribeToResult PURE_IMPORTS_END */ - +/* harmony import */ var _innerSubscribe__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(90); +/** PURE_IMPORTS_START tslib,_Subject,_innerSubscribe PURE_IMPORTS_END */ @@ -56548,7 +56856,7 @@ var WindowOperator = /*@__PURE__*/ (function () { var windowSubscriber = new WindowSubscriber(subscriber); var sourceSubscription = source.subscribe(windowSubscriber); if (!sourceSubscription.closed) { - windowSubscriber.add(Object(_util_subscribeToResult__WEBPACK_IMPORTED_MODULE_3__["subscribeToResult"])(windowSubscriber, this.windowBoundaries)); + windowSubscriber.add(Object(_innerSubscribe__WEBPACK_IMPORTED_MODULE_2__["innerSubscribe"])(this.windowBoundaries, new _innerSubscribe__WEBPACK_IMPORTED_MODULE_2__["SimpleInnerSubscriber"](windowSubscriber))); } return sourceSubscription; }; @@ -56562,13 +56870,13 @@ var WindowSubscriber = /*@__PURE__*/ (function (_super) { destination.next(_this.window); return _this; } - WindowSubscriber.prototype.notifyNext = function (outerValue, innerValue, outerIndex, innerIndex, innerSub) { + WindowSubscriber.prototype.notifyNext = function () { this.openWindow(); }; - WindowSubscriber.prototype.notifyError = function (error, innerSub) { + WindowSubscriber.prototype.notifyError = function (error) { this._error(error); }; - WindowSubscriber.prototype.notifyComplete = function (innerSub) { + WindowSubscriber.prototype.notifyComplete = function () { this._complete(); }; WindowSubscriber.prototype._next = function (value) { @@ -56595,12 +56903,12 @@ var WindowSubscriber = /*@__PURE__*/ (function (_super) { destination.next(newWindow); }; return WindowSubscriber; -}(_OuterSubscriber__WEBPACK_IMPORTED_MODULE_2__["OuterSubscriber"])); +}(_innerSubscribe__WEBPACK_IMPORTED_MODULE_2__["SimpleOuterSubscriber"])); //# sourceMappingURL=window.js.map /***/ }), -/* 489 */ +/* 493 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -56690,7 +56998,7 @@ var WindowCountSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 490 */ +/* 494 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -56700,7 +57008,7 @@ __webpack_require__.r(__webpack_exports__); /* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(27); /* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(55); /* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(11); -/* harmony import */ var _util_isNumeric__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(97); +/* harmony import */ var _util_isNumeric__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(98); /* harmony import */ var _util_isScheduler__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(45); /** PURE_IMPORTS_START tslib,_Subject,_scheduler_async,_Subscriber,_util_isNumeric,_util_isScheduler PURE_IMPORTS_END */ @@ -56720,13 +57028,13 @@ function windowTime(windowTimeSpan) { scheduler = arguments[2]; } else if (Object(_util_isNumeric__WEBPACK_IMPORTED_MODULE_4__["isNumeric"])(arguments[2])) { - maxWindowSize = arguments[2]; + maxWindowSize = Number(arguments[2]); } if (Object(_util_isScheduler__WEBPACK_IMPORTED_MODULE_5__["isScheduler"])(arguments[1])) { scheduler = arguments[1]; } else if (Object(_util_isNumeric__WEBPACK_IMPORTED_MODULE_4__["isNumeric"])(arguments[1])) { - windowCreationInterval = arguments[1]; + windowCreationInterval = Number(arguments[1]); } return function windowTimeOperatorFunction(source) { return source.lift(new WindowTimeOperator(windowTimeSpan, windowCreationInterval, maxWindowSize, scheduler)); @@ -56860,7 +57168,7 @@ function dispatchWindowClose(state) { /***/ }), -/* 491 */ +/* 495 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -57003,7 +57311,7 @@ var WindowToggleSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 492 */ +/* 496 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -57041,10 +57349,10 @@ var WindowSubscriber = /*@__PURE__*/ (function (_super) { _this.openWindow(); return _this; } - WindowSubscriber.prototype.notifyNext = function (outerValue, innerValue, outerIndex, innerIndex, innerSub) { + WindowSubscriber.prototype.notifyNext = function (_outerValue, _innerValue, _outerIndex, _innerIndex, innerSub) { this.openWindow(innerSub); }; - WindowSubscriber.prototype.notifyError = function (error, innerSub) { + WindowSubscriber.prototype.notifyError = function (error) { this._error(error); }; WindowSubscriber.prototype.notifyComplete = function (innerSub) { @@ -57100,7 +57408,7 @@ var WindowSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 493 */ +/* 497 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -57151,11 +57459,11 @@ var WithLatestFromSubscriber = /*@__PURE__*/ (function (_super) { } for (var i = 0; i < len; i++) { var observable = observables[i]; - _this.add(Object(_util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__["subscribeToResult"])(_this, observable, observable, i)); + _this.add(Object(_util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__["subscribeToResult"])(_this, observable, undefined, i)); } return _this; } - WithLatestFromSubscriber.prototype.notifyNext = function (outerValue, innerValue, outerIndex, innerIndex, innerSub) { + WithLatestFromSubscriber.prototype.notifyNext = function (_outerValue, innerValue, outerIndex) { this.values[outerIndex] = innerValue; var toRespond = this.toRespond; if (toRespond.length > 0) { @@ -57195,13 +57503,13 @@ var WithLatestFromSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 494 */ +/* 498 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "zip", function() { return zip; }); -/* harmony import */ var _observable_zip__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(109); +/* harmony import */ var _observable_zip__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(110); /** PURE_IMPORTS_START _observable_zip PURE_IMPORTS_END */ function zip() { @@ -57217,13 +57525,13 @@ function zip() { /***/ }), -/* 495 */ +/* 499 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "zipAll", function() { return zipAll; }); -/* harmony import */ var _observable_zip__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(109); +/* harmony import */ var _observable_zip__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(110); /** PURE_IMPORTS_START _observable_zip PURE_IMPORTS_END */ function zipAll(project) { @@ -57233,17 +57541,17 @@ function zipAll(project) { /***/ }), -/* 496 */ +/* 500 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "runCommand", function() { return runCommand; }); -/* harmony import */ var _utils_errors__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(162); -/* harmony import */ var _utils_log__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(143); -/* harmony import */ var _utils_projects__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(145); -/* harmony import */ var _utils_projects_tree__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(497); -/* harmony import */ var _utils_kibana__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(498); +/* harmony import */ var _utils_errors__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(163); +/* harmony import */ var _utils_log__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(144); +/* harmony import */ var _utils_projects__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(146); +/* harmony import */ var _utils_projects_tree__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(501); +/* harmony import */ var _utils_kibana__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(502); function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; } function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } @@ -57325,13 +57633,13 @@ function toArray(value) { } /***/ }), -/* 497 */ +/* 501 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "renderProjectsTree", function() { return renderProjectsTree; }); -/* harmony import */ var chalk__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(227); +/* harmony import */ var chalk__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(113); /* harmony import */ var chalk__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(chalk__WEBPACK_IMPORTED_MODULE_0__); /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(4); /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_1__); @@ -57478,7 +57786,7 @@ function addProjectToTree(tree, pathParts, project) { } /***/ }), -/* 498 */ +/* 502 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -57486,12 +57794,13 @@ __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Kibana", function() { return Kibana; }); /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(4); /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_0__); -/* harmony import */ var multimatch__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(499); +/* harmony import */ var multimatch__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(503); /* harmony import */ var multimatch__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(multimatch__WEBPACK_IMPORTED_MODULE_1__); -/* harmony import */ var is_path_inside__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(369); +/* harmony import */ var is_path_inside__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(361); /* harmony import */ var is_path_inside__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(is_path_inside__WEBPACK_IMPORTED_MODULE_2__); -/* harmony import */ var _projects__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(145); -/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(280); +/* harmony import */ var _yarn_lock__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(275); +/* harmony import */ var _projects__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(146); +/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(272); function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; } function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } @@ -57521,6 +57830,7 @@ function _defineProperty(obj, key, value) { if (key in obj) { Object.definePrope + /** * Helper class for dealing with a set of projects as children of * the Kibana project. The kbn/pm is currently implemented to be @@ -57535,7 +57845,7 @@ function _defineProperty(obj, key, value) { if (key in obj) { Object.definePrope class Kibana { static async loadFrom(rootPath) { - return new Kibana(await Object(_projects__WEBPACK_IMPORTED_MODULE_3__["getProjects"])(rootPath, Object(_config__WEBPACK_IMPORTED_MODULE_4__["getProjectPaths"])({ + return new Kibana(await Object(_projects__WEBPACK_IMPORTED_MODULE_4__["getProjects"])(rootPath, Object(_config__WEBPACK_IMPORTED_MODULE_5__["getProjectPaths"])({ rootPath }))); } @@ -57594,7 +57904,7 @@ class Kibana { getProjectAndDeps(name) { const project = this.getProject(name); - return Object(_projects__WEBPACK_IMPORTED_MODULE_3__["includeTransitiveProjects"])([project], this.allWorkspaceProjects); + return Object(_projects__WEBPACK_IMPORTED_MODULE_4__["includeTransitiveProjects"])([project], this.allWorkspaceProjects); } /** filter the projects to just those matching certain paths/include/exclude tags */ @@ -57603,7 +57913,7 @@ class Kibana { const allProjects = this.getAllProjects(); const filteredProjects = new Map(); const pkgJsonPaths = Array.from(allProjects.values()).map(p => p.packageJsonLocation); - const filteredPkgJsonGlobs = Object(_config__WEBPACK_IMPORTED_MODULE_4__["getProjectPaths"])(_objectSpread(_objectSpread({}, options), {}, { + const filteredPkgJsonGlobs = Object(_config__WEBPACK_IMPORTED_MODULE_5__["getProjectPaths"])(_objectSpread(_objectSpread({}, options), {}, { rootPath: this.kibanaProject.path })).map(g => path__WEBPACK_IMPORTED_MODULE_0___default.a.resolve(g, 'package.json')); const matchingPkgJsonPaths = multimatch__WEBPACK_IMPORTED_MODULE_1___default()(pkgJsonPaths, filteredPkgJsonGlobs); @@ -57629,18 +57939,38 @@ class Kibana { return !this.isPartOfRepo(project); } + resolveAllProductionDependencies(yarnLock, log) { + const kibanaDeps = Object(_yarn_lock__WEBPACK_IMPORTED_MODULE_3__["resolveDepsForProject"])({ + project: this.kibanaProject, + yarnLock, + kbn: this, + includeDependentProject: true, + productionDepsOnly: true, + log + }); + const xpackDeps = Object(_yarn_lock__WEBPACK_IMPORTED_MODULE_3__["resolveDepsForProject"])({ + project: this.getProject('x-pack'), + yarnLock, + kbn: this, + includeDependentProject: true, + productionDepsOnly: true, + log + }); + return new Map([...kibanaDeps.entries(), ...xpackDeps.entries()]); + } + } /***/ }), -/* 499 */ +/* 503 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const minimatch = __webpack_require__(149); -const arrayUnion = __webpack_require__(500); -const arrayDiffer = __webpack_require__(501); -const arrify = __webpack_require__(502); +const minimatch = __webpack_require__(150); +const arrayUnion = __webpack_require__(504); +const arrayDiffer = __webpack_require__(505); +const arrify = __webpack_require__(506); module.exports = (list, patterns, options = {}) => { list = arrify(list); @@ -57664,7 +57994,7 @@ module.exports = (list, patterns, options = {}) => { /***/ }), -/* 500 */ +/* 504 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -57676,7 +58006,7 @@ module.exports = (...arguments_) => { /***/ }), -/* 501 */ +/* 505 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -57690,444 +58020,12 @@ const arrayDiffer = (array, ...values) => { module.exports = arrayDiffer; -/***/ }), -/* 502 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -const arrify = value => { - if (value === null || value === undefined) { - return []; - } - - if (Array.isArray(value)) { - return value; - } - - if (typeof value === 'string') { - return [value]; - } - - if (typeof value[Symbol.iterator] === 'function') { - return [...value]; - } - - return [value]; -}; - -module.exports = arrify; - - -/***/ }), -/* 503 */ -/***/ (function(module, __webpack_exports__, __webpack_require__) { - -"use strict"; -__webpack_require__.r(__webpack_exports__); -/* harmony import */ var _build_production_projects__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(504); -/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "buildProductionProjects", function() { return _build_production_projects__WEBPACK_IMPORTED_MODULE_0__["buildProductionProjects"]; }); - -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - - -/***/ }), -/* 504 */ -/***/ (function(module, __webpack_exports__, __webpack_require__) { - -"use strict"; -__webpack_require__.r(__webpack_exports__); -/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "buildProductionProjects", function() { return buildProductionProjects; }); -/* harmony import */ var cpy__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(505); -/* harmony import */ var cpy__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(cpy__WEBPACK_IMPORTED_MODULE_0__); -/* harmony import */ var del__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(288); -/* harmony import */ var del__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(del__WEBPACK_IMPORTED_MODULE_1__); -/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(4); -/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_2__); -/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(280); -/* harmony import */ var _utils_fs__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(130); -/* harmony import */ var _utils_log__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(143); -/* harmony import */ var _utils_package_json__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(164); -/* harmony import */ var _utils_projects__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(145); -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - - - - - - - - -async function buildProductionProjects({ - kibanaRoot, - buildRoot, - onlyOSS -}) { - const projects = await getProductionProjects(kibanaRoot, onlyOSS); - const projectGraph = Object(_utils_projects__WEBPACK_IMPORTED_MODULE_7__["buildProjectGraph"])(projects); - const batchedProjects = Object(_utils_projects__WEBPACK_IMPORTED_MODULE_7__["topologicallyBatchProjects"])(projects, projectGraph); - const projectNames = [...projects.values()].map(project => project.name); - _utils_log__WEBPACK_IMPORTED_MODULE_5__["log"].info(`Preparing production build for [${projectNames.join(', ')}]`); - - for (const batch of batchedProjects) { - for (const project of batch) { - await deleteTarget(project); - await buildProject(project); - await copyToBuild(project, kibanaRoot, buildRoot); - } - } -} -/** - * Returns the subset of projects that should be built into the production - * bundle. As we copy these into Kibana's `node_modules` during the build step, - * and let Kibana's build process be responsible for installing dependencies, - * we only include Kibana's transitive _production_ dependencies. If onlyOSS - * is supplied, we omit projects with build.oss in their package.json set to false. - */ - -async function getProductionProjects(rootPath, onlyOSS) { - const projectPaths = Object(_config__WEBPACK_IMPORTED_MODULE_3__["getProjectPaths"])({ - rootPath - }); - const projects = await Object(_utils_projects__WEBPACK_IMPORTED_MODULE_7__["getProjects"])(rootPath, projectPaths); - const projectsSubset = [projects.get('kibana')]; - - if (projects.has('x-pack')) { - projectsSubset.push(projects.get('x-pack')); - } - - const productionProjects = Object(_utils_projects__WEBPACK_IMPORTED_MODULE_7__["includeTransitiveProjects"])(projectsSubset, projects, { - onlyProductionDependencies: true - }); // We remove Kibana, as we're already building Kibana - - productionProjects.delete('kibana'); - - if (onlyOSS) { - productionProjects.forEach(project => { - if (project.getBuildConfig().oss === false) { - productionProjects.delete(project.json.name); - } - }); - } - - return productionProjects; -} - -async function deleteTarget(project) { - const targetDir = project.targetLocation; - - if (await Object(_utils_fs__WEBPACK_IMPORTED_MODULE_4__["isDirectory"])(targetDir)) { - await del__WEBPACK_IMPORTED_MODULE_1___default()(targetDir, { - force: true - }); - } -} - -async function buildProject(project) { - if (project.hasScript('build')) { - await project.runScript('build'); - } -} -/** - * Copy all the project's files from its "intermediate build directory" and - * into the build. The intermediate directory can either be the root of the - * project or some other location defined in the project's `package.json`. - * - * When copying all the files into the build, we exclude `node_modules` because - * we want the Kibana build to be responsible for actually installing all - * dependencies. The primary reason for allowing the Kibana build process to - * manage dependencies is that it will "dedupe" them, so we don't include - * unnecessary copies of dependencies. - */ - - -async function copyToBuild(project, kibanaRoot, buildRoot) { - // We want the package to have the same relative location within the build - const relativeProjectPath = Object(path__WEBPACK_IMPORTED_MODULE_2__["relative"])(kibanaRoot, project.path); - const buildProjectPath = Object(path__WEBPACK_IMPORTED_MODULE_2__["resolve"])(buildRoot, relativeProjectPath); - await cpy__WEBPACK_IMPORTED_MODULE_0___default()(['**/*', '!node_modules/**'], buildProjectPath, { - cwd: project.getIntermediateBuildDirectory(), - dot: true, - nodir: true, - parents: true - }); // If a project is using an intermediate build directory, we special-case our - // handling of `package.json`, as the project build process might have copied - // (a potentially modified) `package.json` into the intermediate build - // directory already. If so, we want to use that `package.json` as the basis - // for creating the production-ready `package.json`. If it's not present in - // the intermediate build, we fall back to using the project's already defined - // `package.json`. - - const packageJson = (await Object(_utils_fs__WEBPACK_IMPORTED_MODULE_4__["isFile"])(Object(path__WEBPACK_IMPORTED_MODULE_2__["join"])(buildProjectPath, 'package.json'))) ? await Object(_utils_package_json__WEBPACK_IMPORTED_MODULE_6__["readPackageJson"])(buildProjectPath) : project.json; - await Object(_utils_package_json__WEBPACK_IMPORTED_MODULE_6__["writePackageJson"])(buildProjectPath, packageJson); -} - -/***/ }), -/* 505 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - -const EventEmitter = __webpack_require__(155); -const path = __webpack_require__(4); -const os = __webpack_require__(120); -const pAll = __webpack_require__(506); -const arrify = __webpack_require__(508); -const globby = __webpack_require__(509); -const isGlob = __webpack_require__(719); -const cpFile = __webpack_require__(720); -const junk = __webpack_require__(732); -const CpyError = __webpack_require__(733); - -const defaultOptions = { - ignoreJunk: true -}; - -const preprocessSourcePath = (source, options) => options.cwd ? path.resolve(options.cwd, source) : source; - -const preprocessDestinationPath = (source, destination, options) => { - let basename = path.basename(source); - const dirname = path.dirname(source); - - if (typeof options.rename === 'string') { - basename = options.rename; - } else if (typeof options.rename === 'function') { - basename = options.rename(basename); - } - - if (options.cwd) { - destination = path.resolve(options.cwd, destination); - } - - if (options.parents) { - return path.join(destination, dirname, basename); - } - - return path.join(destination, basename); -}; - -module.exports = (source, destination, { - concurrency = (os.cpus().length || 1) * 2, - ...options -} = {}) => { - const progressEmitter = new EventEmitter(); - - options = { - ...defaultOptions, - ...options - }; - - const promise = (async () => { - source = arrify(source); - - if (source.length === 0 || !destination) { - throw new CpyError('`source` and `destination` required'); - } - - const copyStatus = new Map(); - let completedFiles = 0; - let completedSize = 0; - - let files; - try { - files = await globby(source, options); - - if (options.ignoreJunk) { - files = files.filter(file => junk.not(path.basename(file))); - } - } catch (error) { - throw new CpyError(`Cannot glob \`${source}\`: ${error.message}`, error); - } - - const sourcePaths = source.filter(value => !isGlob(value)); - - if (files.length === 0 || (sourcePaths.length > 0 && !sourcePaths.every(value => files.includes(value)))) { - throw new CpyError(`Cannot copy \`${source}\`: the file doesn't exist`); - } - - const fileProgressHandler = event => { - const fileStatus = copyStatus.get(event.src) || {written: 0, percent: 0}; - - if (fileStatus.written !== event.written || fileStatus.percent !== event.percent) { - completedSize -= fileStatus.written; - completedSize += event.written; - - if (event.percent === 1 && fileStatus.percent !== 1) { - completedFiles++; - } - - copyStatus.set(event.src, { - written: event.written, - percent: event.percent - }); - - progressEmitter.emit('progress', { - totalFiles: files.length, - percent: completedFiles / files.length, - completedFiles, - completedSize - }); - } - }; - - return pAll(files.map(sourcePath => { - return async () => { - const from = preprocessSourcePath(sourcePath, options); - const to = preprocessDestinationPath(sourcePath, destination, options); - - try { - await cpFile(from, to, options).on('progress', fileProgressHandler); - } catch (error) { - throw new CpyError(`Cannot copy from \`${from}\` to \`${to}\`: ${error.message}`, error); - } - - return to; - }; - }), {concurrency}); - })(); - - promise.on = (...arguments_) => { - progressEmitter.on(...arguments_); - return promise; - }; - - return promise; -}; - - /***/ }), /* 506 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const pMap = __webpack_require__(507); - -module.exports = (iterable, options) => pMap(iterable, element => element(), options); -// TODO: Remove this for the next major release -module.exports.default = module.exports; - - -/***/ }), -/* 507 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -const pMap = (iterable, mapper, options) => new Promise((resolve, reject) => { - options = Object.assign({ - concurrency: Infinity - }, options); - - if (typeof mapper !== 'function') { - throw new TypeError('Mapper function is required'); - } - - const {concurrency} = options; - - if (!(typeof concurrency === 'number' && concurrency >= 1)) { - throw new TypeError(`Expected \`concurrency\` to be a number from 1 and up, got \`${concurrency}\` (${typeof concurrency})`); - } - - const ret = []; - const iterator = iterable[Symbol.iterator](); - let isRejected = false; - let isIterableDone = false; - let resolvingCount = 0; - let currentIndex = 0; - - const next = () => { - if (isRejected) { - return; - } - - const nextItem = iterator.next(); - const i = currentIndex; - currentIndex++; - - if (nextItem.done) { - isIterableDone = true; - - if (resolvingCount === 0) { - resolve(ret); - } - - return; - } - - resolvingCount++; - - Promise.resolve(nextItem.value) - .then(element => mapper(element, i)) - .then( - value => { - ret[i] = value; - resolvingCount--; - next(); - }, - error => { - isRejected = true; - reject(error); - } - ); - }; - - for (let i = 0; i < concurrency; i++) { - next(); - - if (isIterableDone) { - break; - } - } -}); - -module.exports = pMap; -// TODO: Remove this for the next major release -module.exports.default = pMap; - - -/***/ }), -/* 508 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - const arrify = value => { if (value === null || value === undefined) { @@ -58152,18 +58050,450 @@ const arrify = value => { module.exports = arrify; +/***/ }), +/* 507 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony import */ var _build_production_projects__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(508); +/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "buildProductionProjects", function() { return _build_production_projects__WEBPACK_IMPORTED_MODULE_0__["buildProductionProjects"]; }); + +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + + +/***/ }), +/* 508 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "buildProductionProjects", function() { return buildProductionProjects; }); +/* harmony import */ var cpy__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(509); +/* harmony import */ var cpy__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(cpy__WEBPACK_IMPORTED_MODULE_0__); +/* harmony import */ var del__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(281); +/* harmony import */ var del__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(del__WEBPACK_IMPORTED_MODULE_1__); +/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(4); +/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_2__); +/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(272); +/* harmony import */ var _utils_fs__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(131); +/* harmony import */ var _utils_log__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(144); +/* harmony import */ var _utils_package_json__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(165); +/* harmony import */ var _utils_projects__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(146); +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + + + + + + + + +async function buildProductionProjects({ + kibanaRoot, + buildRoot, + onlyOSS +}) { + const projects = await getProductionProjects(kibanaRoot, onlyOSS); + const projectGraph = Object(_utils_projects__WEBPACK_IMPORTED_MODULE_7__["buildProjectGraph"])(projects); + const batchedProjects = Object(_utils_projects__WEBPACK_IMPORTED_MODULE_7__["topologicallyBatchProjects"])(projects, projectGraph); + const projectNames = [...projects.values()].map(project => project.name); + _utils_log__WEBPACK_IMPORTED_MODULE_5__["log"].info(`Preparing production build for [${projectNames.join(', ')}]`); + + for (const batch of batchedProjects) { + for (const project of batch) { + await deleteTarget(project); + await buildProject(project); + await copyToBuild(project, kibanaRoot, buildRoot); + } + } +} +/** + * Returns the subset of projects that should be built into the production + * bundle. As we copy these into Kibana's `node_modules` during the build step, + * and let Kibana's build process be responsible for installing dependencies, + * we only include Kibana's transitive _production_ dependencies. If onlyOSS + * is supplied, we omit projects with build.oss in their package.json set to false. + */ + +async function getProductionProjects(rootPath, onlyOSS) { + const projectPaths = Object(_config__WEBPACK_IMPORTED_MODULE_3__["getProjectPaths"])({ + rootPath + }); + const projects = await Object(_utils_projects__WEBPACK_IMPORTED_MODULE_7__["getProjects"])(rootPath, projectPaths); + const projectsSubset = [projects.get('kibana')]; + + if (projects.has('x-pack')) { + projectsSubset.push(projects.get('x-pack')); + } + + const productionProjects = Object(_utils_projects__WEBPACK_IMPORTED_MODULE_7__["includeTransitiveProjects"])(projectsSubset, projects, { + onlyProductionDependencies: true + }); // We remove Kibana, as we're already building Kibana + + productionProjects.delete('kibana'); + + if (onlyOSS) { + productionProjects.forEach(project => { + if (project.getBuildConfig().oss === false) { + productionProjects.delete(project.json.name); + } + }); + } + + return productionProjects; +} + +async function deleteTarget(project) { + const targetDir = project.targetLocation; + + if (await Object(_utils_fs__WEBPACK_IMPORTED_MODULE_4__["isDirectory"])(targetDir)) { + await del__WEBPACK_IMPORTED_MODULE_1___default()(targetDir, { + force: true + }); + } +} + +async function buildProject(project) { + if (project.hasScript('build')) { + await project.runScript('build'); + } +} +/** + * Copy all the project's files from its "intermediate build directory" and + * into the build. The intermediate directory can either be the root of the + * project or some other location defined in the project's `package.json`. + * + * When copying all the files into the build, we exclude `node_modules` because + * we want the Kibana build to be responsible for actually installing all + * dependencies. The primary reason for allowing the Kibana build process to + * manage dependencies is that it will "dedupe" them, so we don't include + * unnecessary copies of dependencies. + */ + + +async function copyToBuild(project, kibanaRoot, buildRoot) { + // We want the package to have the same relative location within the build + const relativeProjectPath = Object(path__WEBPACK_IMPORTED_MODULE_2__["relative"])(kibanaRoot, project.path); + const buildProjectPath = Object(path__WEBPACK_IMPORTED_MODULE_2__["resolve"])(buildRoot, relativeProjectPath); + await cpy__WEBPACK_IMPORTED_MODULE_0___default()(['**/*', '!node_modules/**'], buildProjectPath, { + cwd: project.getIntermediateBuildDirectory(), + dot: true, + nodir: true, + parents: true + }); // If a project is using an intermediate build directory, we special-case our + // handling of `package.json`, as the project build process might have copied + // (a potentially modified) `package.json` into the intermediate build + // directory already. If so, we want to use that `package.json` as the basis + // for creating the production-ready `package.json`. If it's not present in + // the intermediate build, we fall back to using the project's already defined + // `package.json`. + + const packageJson = (await Object(_utils_fs__WEBPACK_IMPORTED_MODULE_4__["isFile"])(Object(path__WEBPACK_IMPORTED_MODULE_2__["join"])(buildProjectPath, 'package.json'))) ? await Object(_utils_package_json__WEBPACK_IMPORTED_MODULE_6__["readPackageJson"])(buildProjectPath) : project.json; + await Object(_utils_package_json__WEBPACK_IMPORTED_MODULE_6__["writePackageJson"])(buildProjectPath, packageJson); +} + /***/ }), /* 509 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const fs = __webpack_require__(133); -const arrayUnion = __webpack_require__(510); -const glob = __webpack_require__(146); -const fastGlob = __webpack_require__(512); -const dirGlob = __webpack_require__(712); -const gitignore = __webpack_require__(715); +const EventEmitter = __webpack_require__(156); +const path = __webpack_require__(4); +const os = __webpack_require__(121); +const pAll = __webpack_require__(510); +const arrify = __webpack_require__(512); +const globby = __webpack_require__(513); +const isGlob = __webpack_require__(294); +const cpFile = __webpack_require__(713); +const junk = __webpack_require__(723); +const CpyError = __webpack_require__(724); + +const defaultOptions = { + ignoreJunk: true +}; + +const preprocessSourcePath = (source, options) => options.cwd ? path.resolve(options.cwd, source) : source; + +const preprocessDestinationPath = (source, destination, options) => { + let basename = path.basename(source); + const dirname = path.dirname(source); + + if (typeof options.rename === 'string') { + basename = options.rename; + } else if (typeof options.rename === 'function') { + basename = options.rename(basename); + } + + if (options.cwd) { + destination = path.resolve(options.cwd, destination); + } + + if (options.parents) { + return path.join(destination, dirname, basename); + } + + return path.join(destination, basename); +}; + +module.exports = (source, destination, { + concurrency = (os.cpus().length || 1) * 2, + ...options +} = {}) => { + const progressEmitter = new EventEmitter(); + + options = { + ...defaultOptions, + ...options + }; + + const promise = (async () => { + source = arrify(source); + + if (source.length === 0 || !destination) { + throw new CpyError('`source` and `destination` required'); + } + + const copyStatus = new Map(); + let completedFiles = 0; + let completedSize = 0; + + let files; + try { + files = await globby(source, options); + + if (options.ignoreJunk) { + files = files.filter(file => junk.not(path.basename(file))); + } + } catch (error) { + throw new CpyError(`Cannot glob \`${source}\`: ${error.message}`, error); + } + + const sourcePaths = source.filter(value => !isGlob(value)); + + if (files.length === 0 || (sourcePaths.length > 0 && !sourcePaths.every(value => files.includes(value)))) { + throw new CpyError(`Cannot copy \`${source}\`: the file doesn't exist`); + } + + const fileProgressHandler = event => { + const fileStatus = copyStatus.get(event.src) || {written: 0, percent: 0}; + + if (fileStatus.written !== event.written || fileStatus.percent !== event.percent) { + completedSize -= fileStatus.written; + completedSize += event.written; + + if (event.percent === 1 && fileStatus.percent !== 1) { + completedFiles++; + } + + copyStatus.set(event.src, { + written: event.written, + percent: event.percent + }); + + progressEmitter.emit('progress', { + totalFiles: files.length, + percent: completedFiles / files.length, + completedFiles, + completedSize + }); + } + }; + + return pAll(files.map(sourcePath => { + return async () => { + const from = preprocessSourcePath(sourcePath, options); + const to = preprocessDestinationPath(sourcePath, destination, options); + + try { + await cpFile(from, to, options).on('progress', fileProgressHandler); + } catch (error) { + throw new CpyError(`Cannot copy from \`${from}\` to \`${to}\`: ${error.message}`, error); + } + + return to; + }; + }), {concurrency}); + })(); + + promise.on = (...arguments_) => { + progressEmitter.on(...arguments_); + return promise; + }; + + return promise; +}; + + +/***/ }), +/* 510 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +const pMap = __webpack_require__(511); + +module.exports = (iterable, options) => pMap(iterable, element => element(), options); +// TODO: Remove this for the next major release +module.exports.default = module.exports; + + +/***/ }), +/* 511 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +const pMap = (iterable, mapper, options) => new Promise((resolve, reject) => { + options = Object.assign({ + concurrency: Infinity + }, options); + + if (typeof mapper !== 'function') { + throw new TypeError('Mapper function is required'); + } + + const {concurrency} = options; + + if (!(typeof concurrency === 'number' && concurrency >= 1)) { + throw new TypeError(`Expected \`concurrency\` to be a number from 1 and up, got \`${concurrency}\` (${typeof concurrency})`); + } + + const ret = []; + const iterator = iterable[Symbol.iterator](); + let isRejected = false; + let isIterableDone = false; + let resolvingCount = 0; + let currentIndex = 0; + + const next = () => { + if (isRejected) { + return; + } + + const nextItem = iterator.next(); + const i = currentIndex; + currentIndex++; + + if (nextItem.done) { + isIterableDone = true; + + if (resolvingCount === 0) { + resolve(ret); + } + + return; + } + + resolvingCount++; + + Promise.resolve(nextItem.value) + .then(element => mapper(element, i)) + .then( + value => { + ret[i] = value; + resolvingCount--; + next(); + }, + error => { + isRejected = true; + reject(error); + } + ); + }; + + for (let i = 0; i < concurrency; i++) { + next(); + + if (isIterableDone) { + break; + } + } +}); + +module.exports = pMap; +// TODO: Remove this for the next major release +module.exports.default = pMap; + + +/***/ }), +/* 512 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +const arrify = value => { + if (value === null || value === undefined) { + return []; + } + + if (Array.isArray(value)) { + return value; + } + + if (typeof value === 'string') { + return [value]; + } + + if (typeof value[Symbol.iterator] === 'function') { + return [...value]; + } + + return [value]; +}; + +module.exports = arrify; + + +/***/ }), +/* 513 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +const fs = __webpack_require__(134); +const arrayUnion = __webpack_require__(514); +const glob = __webpack_require__(147); +const fastGlob = __webpack_require__(516); +const dirGlob = __webpack_require__(706); +const gitignore = __webpack_require__(709); const DEFAULT_FILTER = () => false; @@ -58308,12 +58638,12 @@ module.exports.gitignore = gitignore; /***/ }), -/* 510 */ +/* 514 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var arrayUniq = __webpack_require__(511); +var arrayUniq = __webpack_require__(515); module.exports = function () { return arrayUniq([].concat.apply([], arguments)); @@ -58321,7 +58651,7 @@ module.exports = function () { /***/ }), -/* 511 */ +/* 515 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -58390,10 +58720,10 @@ if ('Set' in global) { /***/ }), -/* 512 */ +/* 516 */ /***/ (function(module, exports, __webpack_require__) { -const pkg = __webpack_require__(513); +const pkg = __webpack_require__(517); module.exports = pkg.async; module.exports.default = pkg.async; @@ -58406,19 +58736,19 @@ module.exports.generateTasks = pkg.generateTasks; /***/ }), -/* 513 */ +/* 517 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -var optionsManager = __webpack_require__(514); -var taskManager = __webpack_require__(515); -var reader_async_1 = __webpack_require__(683); -var reader_stream_1 = __webpack_require__(707); -var reader_sync_1 = __webpack_require__(708); -var arrayUtils = __webpack_require__(710); -var streamUtils = __webpack_require__(711); +var optionsManager = __webpack_require__(518); +var taskManager = __webpack_require__(519); +var reader_async_1 = __webpack_require__(677); +var reader_stream_1 = __webpack_require__(701); +var reader_sync_1 = __webpack_require__(702); +var arrayUtils = __webpack_require__(704); +var streamUtils = __webpack_require__(705); /** * Synchronous API. */ @@ -58484,7 +58814,7 @@ function isString(source) { /***/ }), -/* 514 */ +/* 518 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -58522,13 +58852,13 @@ exports.prepare = prepare; /***/ }), -/* 515 */ +/* 519 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -var patternUtils = __webpack_require__(516); +var patternUtils = __webpack_require__(520); /** * Generate tasks based on parent directory of each pattern. */ @@ -58619,16 +58949,16 @@ exports.convertPatternGroupToTask = convertPatternGroupToTask; /***/ }), -/* 516 */ +/* 520 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var path = __webpack_require__(4); -var globParent = __webpack_require__(517); -var isGlob = __webpack_require__(520); -var micromatch = __webpack_require__(521); +var globParent = __webpack_require__(521); +var isGlob = __webpack_require__(294); +var micromatch = __webpack_require__(524); var GLOBSTAR = '**'; /** * Return true for static pattern. @@ -58774,16 +59104,16 @@ exports.matchAny = matchAny; /***/ }), -/* 517 */ +/* 521 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var path = __webpack_require__(4); -var isglob = __webpack_require__(518); -var pathDirname = __webpack_require__(519); -var isWin32 = __webpack_require__(120).platform() === 'win32'; +var isglob = __webpack_require__(522); +var pathDirname = __webpack_require__(523); +var isWin32 = __webpack_require__(121).platform() === 'win32'; module.exports = function globParent(str) { // flip windows path separators @@ -58805,7 +59135,7 @@ module.exports = function globParent(str) { /***/ }), -/* 518 */ +/* 522 */ /***/ (function(module, exports, __webpack_require__) { /*! @@ -58815,7 +59145,7 @@ module.exports = function globParent(str) { * Licensed under the MIT License. */ -var isExtglob = __webpack_require__(302); +var isExtglob = __webpack_require__(295); module.exports = function isGlob(str) { if (typeof str !== 'string' || str === '') { @@ -58836,14 +59166,14 @@ module.exports = function isGlob(str) { /***/ }), -/* 519 */ +/* 523 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var path = __webpack_require__(4); -var inspect = __webpack_require__(111).inspect; +var inspect = __webpack_require__(112).inspect; function assertPath(path) { if (typeof path !== 'string') { @@ -58986,59 +59316,7 @@ module.exports.win32 = win32; /***/ }), -/* 520 */ -/***/ (function(module, exports, __webpack_require__) { - -/*! - * is-glob - * - * Copyright (c) 2014-2017, Jon Schlinkert. - * Released under the MIT License. - */ - -var isExtglob = __webpack_require__(302); -var chars = { '{': '}', '(': ')', '[': ']'}; - -module.exports = function isGlob(str, options) { - if (typeof str !== 'string' || str === '') { - return false; - } - - if (isExtglob(str)) { - return true; - } - - var regex = /\\(.)|(^!|\*|[\].+)]\?|\[[^\\\]]+\]|\{[^\\}]+\}|\(\?[:!=][^\\)]+\)|\([^|]+\|[^\\)]+\))/; - var match; - - // optionally relax regex - if (options && options.strict === false) { - regex = /\\(.)|(^!|[*?{}()[\]]|\(\?)/; - } - - while ((match = regex.exec(str))) { - if (match[2]) return true; - var idx = match.index + match[0].length; - - // if an open bracket/brace/paren is escaped, - // set the index to the next closing character - var open = match[1]; - var close = open ? chars[open] : null; - if (open && close) { - var n = str.indexOf(close, idx); - if (n !== -1) { - idx = n + 1; - } - } - - str = str.slice(idx); - } - return false; -}; - - -/***/ }), -/* 521 */ +/* 524 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -59048,19 +59326,19 @@ module.exports = function isGlob(str, options) { * Module dependencies */ -var util = __webpack_require__(111); -var braces = __webpack_require__(522); -var toRegex = __webpack_require__(635); -var extend = __webpack_require__(643); +var util = __webpack_require__(112); +var braces = __webpack_require__(525); +var toRegex = __webpack_require__(526); +var extend = __webpack_require__(638); /** * Local dependencies */ -var compilers = __webpack_require__(646); -var parsers = __webpack_require__(679); -var cache = __webpack_require__(680); -var utils = __webpack_require__(681); +var compilers = __webpack_require__(640); +var parsers = __webpack_require__(672); +var cache = __webpack_require__(673); +var utils = __webpack_require__(674); var MAX_LENGTH = 1024 * 64; /** @@ -59922,7 +60200,7 @@ module.exports = micromatch; /***/ }), -/* 522 */ +/* 525 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -59932,18 +60210,18 @@ module.exports = micromatch; * Module dependencies */ -var toRegex = __webpack_require__(523); -var unique = __webpack_require__(537); -var extend = __webpack_require__(532); +var toRegex = __webpack_require__(526); +var unique = __webpack_require__(548); +var extend = __webpack_require__(549); /** * Local dependencies */ -var compilers = __webpack_require__(538); -var parsers = __webpack_require__(555); -var Braces = __webpack_require__(565); -var utils = __webpack_require__(539); +var compilers = __webpack_require__(551); +var parsers = __webpack_require__(564); +var Braces = __webpack_require__(568); +var utils = __webpack_require__(552); var MAX_LENGTH = 1024 * 64; var cache = {}; @@ -60247,15 +60525,16 @@ module.exports = braces; /***/ }), -/* 523 */ +/* 526 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var define = __webpack_require__(524); -var extend = __webpack_require__(532); -var not = __webpack_require__(534); +var safe = __webpack_require__(527); +var define = __webpack_require__(533); +var extend = __webpack_require__(541); +var not = __webpack_require__(545); var MAX_LENGTH = 1024 * 64; /** @@ -60339,10 +60618,16 @@ function makeRe(pattern, options) { if (opts.negate || typeof opts.strictNegate === 'boolean') { pattern = not.create(pattern, opts); } + var str = open + '(?:' + pattern + ')' + close; regex = new RegExp(str, flags); + + if (opts.safe === true && safe(regex) === false) { + throw new Error('potentially unsafe regular expression: ' + regex.source); + } + } catch (err) { - if (opts.strictErrors === true) { + if (opts.strictErrors === true || opts.safe === true) { err.key = key; err.pattern = pattern; err.originalOptions = options; @@ -60358,18 +60643,18 @@ function makeRe(pattern, options) { } if (opts.cache !== false) { - cacheRegex(regex, key, pattern, opts); + memoize(regex, key, pattern, opts); } return regex; } /** - * Cache generated regex. This can result in dramatic speed improvements + * Memoize generated regex. This can result in dramatic speed improvements * and simplify debugging by adding options and pattern to the regex. It can be * disabled by passing setting `options.cache` to false. */ -function cacheRegex(regex, key, pattern, options) { +function memoize(regex, key, pattern, options) { define(regex, 'cached', true); define(regex, 'pattern', pattern); define(regex, 'options', options); @@ -60402,631 +60687,560 @@ module.exports.makeRe = makeRe; /***/ }), -/* 524 */ +/* 527 */ /***/ (function(module, exports, __webpack_require__) { -"use strict"; -/*! - * define-property - * - * Copyright (c) 2015, Jon Schlinkert. - * Licensed under the MIT License. - */ - - - -var isDescriptor = __webpack_require__(525); - -module.exports = function defineProperty(obj, prop, val) { - if (typeof obj !== 'object' && typeof obj !== 'function') { - throw new TypeError('expected an object or function.'); - } - - if (typeof prop !== 'string') { - throw new TypeError('expected `prop` to be a string.'); - } - - if (isDescriptor(val) && ('set' in val || 'get' in val)) { - return Object.defineProperty(obj, prop, val); - } +var parse = __webpack_require__(528); +var types = parse.types; - return Object.defineProperty(obj, prop, { - configurable: true, - enumerable: false, - writable: true, - value: val - }); +module.exports = function (re, opts) { + if (!opts) opts = {}; + var replimit = opts.limit === undefined ? 25 : opts.limit; + + if (isRegExp(re)) re = re.source; + else if (typeof re !== 'string') re = String(re); + + try { re = parse(re) } + catch (err) { return false } + + var reps = 0; + return (function walk (node, starHeight) { + if (node.type === types.REPETITION) { + starHeight ++; + reps ++; + if (starHeight > 1) return false; + if (reps > replimit) return false; + } + + if (node.options) { + for (var i = 0, len = node.options.length; i < len; i++) { + var ok = walk({ stack: node.options[i] }, starHeight); + if (!ok) return false; + } + } + var stack = node.stack || (node.value && node.value.stack); + if (!stack) return true; + + for (var i = 0; i < stack.length; i++) { + var ok = walk(stack[i], starHeight); + if (!ok) return false; + } + + return true; + })(re, 0); }; +function isRegExp (x) { + return {}.toString.call(x) === '[object RegExp]'; +} + /***/ }), -/* 525 */ +/* 528 */ /***/ (function(module, exports, __webpack_require__) { -"use strict"; -/*! - * is-descriptor - * - * Copyright (c) 2015-2017, Jon Schlinkert. - * Released under the MIT License. - */ - +var util = __webpack_require__(529); +var types = __webpack_require__(530); +var sets = __webpack_require__(531); +var positions = __webpack_require__(532); -var typeOf = __webpack_require__(526); -var isAccessor = __webpack_require__(527); -var isData = __webpack_require__(530); - -module.exports = function isDescriptor(obj, key) { - if (typeOf(obj) !== 'object') { - return false; - } - if ('get' in obj) { - return isAccessor(obj, key); - } - return isData(obj, key); -}; +module.exports = function(regexpStr) { + var i = 0, l, c, + start = { type: types.ROOT, stack: []}, + // Keep track of last clause/group and stack. + lastGroup = start, + last = start.stack, + groupStack = []; -/***/ }), -/* 526 */ -/***/ (function(module, exports) { -var toString = Object.prototype.toString; + var repeatErr = function(i) { + util.error(regexpStr, 'Nothing to repeat at column ' + (i - 1)); + }; -/** - * Get the native `typeof` a value. - * - * @param {*} `val` - * @return {*} Native javascript type - */ + // Decode a few escaped characters. + var str = util.strToChars(regexpStr); + l = str.length; -module.exports = function kindOf(val) { - var type = typeof val; + // Iterate through each character in string. + while (i < l) { + c = str[i++]; - // primitivies - if (type === 'undefined') { - return 'undefined'; - } - if (val === null) { - return 'null'; - } - if (val === true || val === false || val instanceof Boolean) { - return 'boolean'; - } - if (type === 'string' || val instanceof String) { - return 'string'; - } - if (type === 'number' || val instanceof Number) { - return 'number'; - } + switch (c) { + // Handle escaped characters, inclues a few sets. + case '\\': + c = str[i++]; - // functions - if (type === 'function' || val instanceof Function) { - if (typeof val.constructor.name !== 'undefined' && val.constructor.name.slice(0, 9) === 'Generator') { - return 'generatorfunction'; - } - return 'function'; - } + switch (c) { + case 'b': + last.push(positions.wordBoundary()); + break; - // array - if (typeof Array.isArray !== 'undefined' && Array.isArray(val)) { - return 'array'; - } + case 'B': + last.push(positions.nonWordBoundary()); + break; - // check for instances of RegExp and Date before calling `toString` - if (val instanceof RegExp) { - return 'regexp'; - } - if (val instanceof Date) { - return 'date'; - } + case 'w': + last.push(sets.words()); + break; - // other objects - type = toString.call(val); + case 'W': + last.push(sets.notWords()); + break; - if (type === '[object RegExp]') { - return 'regexp'; - } - if (type === '[object Date]') { - return 'date'; - } - if (type === '[object Arguments]') { - return 'arguments'; - } - if (type === '[object Error]') { - return 'error'; - } - if (type === '[object Promise]') { - return 'promise'; - } + case 'd': + last.push(sets.ints()); + break; - // buffer - if (isBuffer(val)) { - return 'buffer'; - } + case 'D': + last.push(sets.notInts()); + break; - // es6: Map, WeakMap, Set, WeakSet - if (type === '[object Set]') { - return 'set'; - } - if (type === '[object WeakSet]') { - return 'weakset'; - } - if (type === '[object Map]') { - return 'map'; - } - if (type === '[object WeakMap]') { - return 'weakmap'; - } - if (type === '[object Symbol]') { - return 'symbol'; - } - - if (type === '[object Map Iterator]') { - return 'mapiterator'; - } - if (type === '[object Set Iterator]') { - return 'setiterator'; - } - if (type === '[object String Iterator]') { - return 'stringiterator'; - } - if (type === '[object Array Iterator]') { - return 'arrayiterator'; - } - - // typed arrays - if (type === '[object Int8Array]') { - return 'int8array'; - } - if (type === '[object Uint8Array]') { - return 'uint8array'; - } - if (type === '[object Uint8ClampedArray]') { - return 'uint8clampedarray'; - } - if (type === '[object Int16Array]') { - return 'int16array'; - } - if (type === '[object Uint16Array]') { - return 'uint16array'; - } - if (type === '[object Int32Array]') { - return 'int32array'; - } - if (type === '[object Uint32Array]') { - return 'uint32array'; - } - if (type === '[object Float32Array]') { - return 'float32array'; - } - if (type === '[object Float64Array]') { - return 'float64array'; - } + case 's': + last.push(sets.whitespace()); + break; - // must be a plain object - return 'object'; -}; + case 'S': + last.push(sets.notWhitespace()); + break; -/** - * If you need to support Safari 5-7 (8-10 yr-old browser), - * take a look at https://github.com/feross/is-buffer - */ + default: + // Check if c is integer. + // In which case it's a reference. + if (/\d/.test(c)) { + last.push({ type: types.REFERENCE, value: parseInt(c, 10) }); -function isBuffer(val) { - return val.constructor - && typeof val.constructor.isBuffer === 'function' - && val.constructor.isBuffer(val); -} + // Escaped character. + } else { + last.push({ type: types.CHAR, value: c.charCodeAt(0) }); + } + } + break; -/***/ }), -/* 527 */ -/***/ (function(module, exports, __webpack_require__) { -"use strict"; -/*! - * is-accessor-descriptor - * - * Copyright (c) 2015, Jon Schlinkert. - * Licensed under the MIT License. - */ + // Positionals. + case '^': + last.push(positions.begin()); + break; + case '$': + last.push(positions.end()); + break; -var typeOf = __webpack_require__(528); + // Handle custom sets. + case '[': + // Check if this class is 'anti' i.e. [^abc]. + var not; + if (str[i] === '^') { + not = true; + i++; + } else { + not = false; + } -// accessor descriptor properties -var accessor = { - get: 'function', - set: 'function', - configurable: 'boolean', - enumerable: 'boolean' -}; + // Get all the characters in class. + var classTokens = util.tokenizeClass(str.slice(i), regexpStr); -function isAccessorDescriptor(obj, prop) { - if (typeof prop === 'string') { - var val = Object.getOwnPropertyDescriptor(obj, prop); - return typeof val !== 'undefined'; - } + // Increase index by length of class. + i += classTokens[1]; + last.push({ + type: types.SET, + set: classTokens[0], + not: not, + }); - if (typeOf(obj) !== 'object') { - return false; - } + break; - if (has(obj, 'value') || has(obj, 'writable')) { - return false; - } - if (!has(obj, 'get') || typeof obj.get !== 'function') { - return false; - } + // Class of any character except \n. + case '.': + last.push(sets.anyChar()); + break; - // tldr: it's valid to have "set" be undefined - // "set" might be undefined if `Object.getOwnPropertyDescriptor` - // was used to get the value, and only `get` was defined by the user - if (has(obj, 'set') && typeof obj[key] !== 'function' && typeof obj[key] !== 'undefined') { - return false; - } - for (var key in obj) { - if (!accessor.hasOwnProperty(key)) { - continue; - } + // Push group onto stack. + case '(': + // Create group. + var group = { + type: types.GROUP, + stack: [], + remember: true, + }; - if (typeOf(obj[key]) === accessor[key]) { - continue; - } + c = str[i]; - if (typeof obj[key] !== 'undefined') { - return false; - } - } - return true; -} + // If if this is a special kind of group. + if (c === '?') { + c = str[i + 1]; + i += 2; -function has(obj, key) { - return {}.hasOwnProperty.call(obj, key); -} + // Match if followed by. + if (c === '=') { + group.followedBy = true; -/** - * Expose `isAccessorDescriptor` - */ + // Match if not followed by. + } else if (c === '!') { + group.notFollowedBy = true; -module.exports = isAccessorDescriptor; + } else if (c !== ':') { + util.error(regexpStr, + 'Invalid group, character \'' + c + + '\' after \'?\' at column ' + (i - 1)); + } + group.remember = false; + } -/***/ }), -/* 528 */ -/***/ (function(module, exports, __webpack_require__) { + // Insert subgroup into current group stack. + last.push(group); -var isBuffer = __webpack_require__(529); -var toString = Object.prototype.toString; + // Remember the current group for when the group closes. + groupStack.push(lastGroup); -/** - * Get the native `typeof` a value. - * - * @param {*} `val` - * @return {*} Native javascript type - */ + // Make this new group the current group. + lastGroup = group; + last = group.stack; + break; -module.exports = function kindOf(val) { - // primitivies - if (typeof val === 'undefined') { - return 'undefined'; - } - if (val === null) { - return 'null'; - } - if (val === true || val === false || val instanceof Boolean) { - return 'boolean'; - } - if (typeof val === 'string' || val instanceof String) { - return 'string'; - } - if (typeof val === 'number' || val instanceof Number) { - return 'number'; - } - // functions - if (typeof val === 'function' || val instanceof Function) { - return 'function'; - } + // Pop group out of stack. + case ')': + if (groupStack.length === 0) { + util.error(regexpStr, 'Unmatched ) at column ' + (i - 1)); + } + lastGroup = groupStack.pop(); - // array - if (typeof Array.isArray !== 'undefined' && Array.isArray(val)) { - return 'array'; - } + // Check if this group has a PIPE. + // To get back the correct last stack. + last = lastGroup.options ? + lastGroup.options[lastGroup.options.length - 1] : lastGroup.stack; + break; - // check for instances of RegExp and Date before calling `toString` - if (val instanceof RegExp) { - return 'regexp'; - } - if (val instanceof Date) { - return 'date'; - } - // other objects - var type = toString.call(val); + // Use pipe character to give more choices. + case '|': + // Create array where options are if this is the first PIPE + // in this clause. + if (!lastGroup.options) { + lastGroup.options = [lastGroup.stack]; + delete lastGroup.stack; + } - if (type === '[object RegExp]') { - return 'regexp'; - } - if (type === '[object Date]') { - return 'date'; - } - if (type === '[object Arguments]') { - return 'arguments'; - } - if (type === '[object Error]') { - return 'error'; - } + // Create a new stack and add to options for rest of clause. + var stack = []; + lastGroup.options.push(stack); + last = stack; + break; - // buffer - if (isBuffer(val)) { - return 'buffer'; - } - // es6: Map, WeakMap, Set, WeakSet - if (type === '[object Set]') { - return 'set'; - } - if (type === '[object WeakSet]') { - return 'weakset'; - } - if (type === '[object Map]') { - return 'map'; - } - if (type === '[object WeakMap]') { - return 'weakmap'; - } - if (type === '[object Symbol]') { - return 'symbol'; - } + // Repetition. + // For every repetition, remove last element from last stack + // then insert back a RANGE object. + // This design is chosen because there could be more than + // one repetition symbols in a regex i.e. `a?+{2,3}`. + case '{': + var rs = /^(\d+)(,(\d+)?)?\}/.exec(str.slice(i)), min, max; + if (rs !== null) { + if (last.length === 0) { + repeatErr(i); + } + min = parseInt(rs[1], 10); + max = rs[2] ? rs[3] ? parseInt(rs[3], 10) : Infinity : min; + i += rs[0].length; + + last.push({ + type: types.REPETITION, + min: min, + max: max, + value: last.pop(), + }); + } else { + last.push({ + type: types.CHAR, + value: 123, + }); + } + break; + + case '?': + if (last.length === 0) { + repeatErr(i); + } + last.push({ + type: types.REPETITION, + min: 0, + max: 1, + value: last.pop(), + }); + break; + + case '+': + if (last.length === 0) { + repeatErr(i); + } + last.push({ + type: types.REPETITION, + min: 1, + max: Infinity, + value: last.pop(), + }); + break; + + case '*': + if (last.length === 0) { + repeatErr(i); + } + last.push({ + type: types.REPETITION, + min: 0, + max: Infinity, + value: last.pop(), + }); + break; + + + // Default is a character that is not `\[](){}?+*^$`. + default: + last.push({ + type: types.CHAR, + value: c.charCodeAt(0), + }); + } - // typed arrays - if (type === '[object Int8Array]') { - return 'int8array'; - } - if (type === '[object Uint8Array]') { - return 'uint8array'; - } - if (type === '[object Uint8ClampedArray]') { - return 'uint8clampedarray'; - } - if (type === '[object Int16Array]') { - return 'int16array'; - } - if (type === '[object Uint16Array]') { - return 'uint16array'; - } - if (type === '[object Int32Array]') { - return 'int32array'; - } - if (type === '[object Uint32Array]') { - return 'uint32array'; - } - if (type === '[object Float32Array]') { - return 'float32array'; } - if (type === '[object Float64Array]') { - return 'float64array'; + + // Check if any groups have not been closed. + if (groupStack.length !== 0) { + util.error(regexpStr, 'Unterminated group'); } - // must be a plain object - return 'object'; + return start; }; +module.exports.types = types; + /***/ }), /* 529 */ -/***/ (function(module, exports) { +/***/ (function(module, exports, __webpack_require__) { -/*! - * Determine if an object is a Buffer +var types = __webpack_require__(530); +var sets = __webpack_require__(531); + + +// All of these are private and only used by randexp. +// It's assumed that they will always be called with the correct input. + +var CTRL = '@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^ ?'; +var SLSH = { '0': 0, 't': 9, 'n': 10, 'v': 11, 'f': 12, 'r': 13 }; + +/** + * Finds character representations in str and convert all to + * their respective characters * - * @author Feross Aboukhadijeh - * @license MIT + * @param {String} str + * @return {String} */ +exports.strToChars = function(str) { + /* jshint maxlen: false */ + var chars_regex = /(\[\\b\])|(\\)?\\(?:u([A-F0-9]{4})|x([A-F0-9]{2})|(0?[0-7]{2})|c([@A-Z\[\\\]\^?])|([0tnvfr]))/g; + str = str.replace(chars_regex, function(s, b, lbs, a16, b16, c8, dctrl, eslsh) { + if (lbs) { + return s; + } -// The _isBuffer check is for Safari 5-7 support, because it's missing -// Object.prototype.constructor. Remove this eventually -module.exports = function (obj) { - return obj != null && (isBuffer(obj) || isSlowBuffer(obj) || !!obj._isBuffer) -} + var code = b ? 8 : + a16 ? parseInt(a16, 16) : + b16 ? parseInt(b16, 16) : + c8 ? parseInt(c8, 8) : + dctrl ? CTRL.indexOf(dctrl) : + SLSH[eslsh]; -function isBuffer (obj) { - return !!obj.constructor && typeof obj.constructor.isBuffer === 'function' && obj.constructor.isBuffer(obj) -} + var c = String.fromCharCode(code); -// For Node v0.10 support. Remove this eventually. -function isSlowBuffer (obj) { - return typeof obj.readFloatLE === 'function' && typeof obj.slice === 'function' && isBuffer(obj.slice(0, 0)) -} + // Escape special regex characters. + if (/[\[\]{}\^$.|?*+()]/.test(c)) { + c = '\\' + c; + } + return c; + }); -/***/ }), -/* 530 */ -/***/ (function(module, exports, __webpack_require__) { + return str; +}; -"use strict"; -/*! - * is-data-descriptor + +/** + * turns class into tokens + * reads str until it encounters a ] not preceeded by a \ * - * Copyright (c) 2015, Jon Schlinkert. - * Licensed under the MIT License. + * @param {String} str + * @param {String} regexpStr + * @return {Array., Number>} */ +exports.tokenizeClass = function(str, regexpStr) { + /* jshint maxlen: false */ + var tokens = []; + var regexp = /\\(?:(w)|(d)|(s)|(W)|(D)|(S))|((?:(?:\\)(.)|([^\]\\]))-(?:\\)?([^\]]))|(\])|(?:\\)?(.)/g; + var rs, c; + while ((rs = regexp.exec(str)) != null) { + if (rs[1]) { + tokens.push(sets.words()); -var typeOf = __webpack_require__(531); - -// data descriptor properties -var data = { - configurable: 'boolean', - enumerable: 'boolean', - writable: 'boolean' -}; + } else if (rs[2]) { + tokens.push(sets.ints()); -function isDataDescriptor(obj, prop) { - if (typeOf(obj) !== 'object') { - return false; - } + } else if (rs[3]) { + tokens.push(sets.whitespace()); - if (typeof prop === 'string') { - var val = Object.getOwnPropertyDescriptor(obj, prop); - return typeof val !== 'undefined'; - } + } else if (rs[4]) { + tokens.push(sets.notWords()); - if (!('value' in obj) && !('writable' in obj)) { - return false; - } + } else if (rs[5]) { + tokens.push(sets.notInts()); - for (var key in obj) { - if (key === 'value') continue; + } else if (rs[6]) { + tokens.push(sets.notWhitespace()); - if (!data.hasOwnProperty(key)) { - continue; - } + } else if (rs[7]) { + tokens.push({ + type: types.RANGE, + from: (rs[8] || rs[9]).charCodeAt(0), + to: rs[10].charCodeAt(0), + }); - if (typeOf(obj[key]) === data[key]) { - continue; - } + } else if (c = rs[12]) { + tokens.push({ + type: types.CHAR, + value: c.charCodeAt(0), + }); - if (typeof obj[key] !== 'undefined') { - return false; + } else { + return [tokens, regexp.lastIndex]; } } - return true; -} + + exports.error(regexpStr, 'Unterminated character class'); +}; + /** - * Expose `isDataDescriptor` + * Shortcut to throw errors. + * + * @param {String} regexp + * @param {String} msg */ +exports.error = function(regexp, msg) { + throw new SyntaxError('Invalid regular expression: /' + regexp + '/: ' + msg); +}; -module.exports = isDataDescriptor; + +/***/ }), +/* 530 */ +/***/ (function(module, exports) { + +module.exports = { + ROOT : 0, + GROUP : 1, + POSITION : 2, + SET : 3, + RANGE : 4, + REPETITION : 5, + REFERENCE : 6, + CHAR : 7, +}; /***/ }), /* 531 */ /***/ (function(module, exports, __webpack_require__) { -var isBuffer = __webpack_require__(529); -var toString = Object.prototype.toString; +var types = __webpack_require__(530); -/** - * Get the native `typeof` a value. - * - * @param {*} `val` - * @return {*} Native javascript type - */ +var INTS = function() { + return [{ type: types.RANGE , from: 48, to: 57 }]; +}; -module.exports = function kindOf(val) { - // primitivies - if (typeof val === 'undefined') { - return 'undefined'; - } - if (val === null) { - return 'null'; - } - if (val === true || val === false || val instanceof Boolean) { - return 'boolean'; - } - if (typeof val === 'string' || val instanceof String) { - return 'string'; - } - if (typeof val === 'number' || val instanceof Number) { - return 'number'; - } +var WORDS = function() { + return [ + { type: types.CHAR, value: 95 }, + { type: types.RANGE, from: 97, to: 122 }, + { type: types.RANGE, from: 65, to: 90 } + ].concat(INTS()); +}; - // functions - if (typeof val === 'function' || val instanceof Function) { - return 'function'; - } +var WHITESPACE = function() { + return [ + { type: types.CHAR, value: 9 }, + { type: types.CHAR, value: 10 }, + { type: types.CHAR, value: 11 }, + { type: types.CHAR, value: 12 }, + { type: types.CHAR, value: 13 }, + { type: types.CHAR, value: 32 }, + { type: types.CHAR, value: 160 }, + { type: types.CHAR, value: 5760 }, + { type: types.CHAR, value: 6158 }, + { type: types.CHAR, value: 8192 }, + { type: types.CHAR, value: 8193 }, + { type: types.CHAR, value: 8194 }, + { type: types.CHAR, value: 8195 }, + { type: types.CHAR, value: 8196 }, + { type: types.CHAR, value: 8197 }, + { type: types.CHAR, value: 8198 }, + { type: types.CHAR, value: 8199 }, + { type: types.CHAR, value: 8200 }, + { type: types.CHAR, value: 8201 }, + { type: types.CHAR, value: 8202 }, + { type: types.CHAR, value: 8232 }, + { type: types.CHAR, value: 8233 }, + { type: types.CHAR, value: 8239 }, + { type: types.CHAR, value: 8287 }, + { type: types.CHAR, value: 12288 }, + { type: types.CHAR, value: 65279 } + ]; +}; - // array - if (typeof Array.isArray !== 'undefined' && Array.isArray(val)) { - return 'array'; - } +var NOTANYCHAR = function() { + return [ + { type: types.CHAR, value: 10 }, + { type: types.CHAR, value: 13 }, + { type: types.CHAR, value: 8232 }, + { type: types.CHAR, value: 8233 }, + ]; +}; - // check for instances of RegExp and Date before calling `toString` - if (val instanceof RegExp) { - return 'regexp'; - } - if (val instanceof Date) { - return 'date'; - } +// Predefined class objects. +exports.words = function() { + return { type: types.SET, set: WORDS(), not: false }; +}; - // other objects - var type = toString.call(val); +exports.notWords = function() { + return { type: types.SET, set: WORDS(), not: true }; +}; - if (type === '[object RegExp]') { - return 'regexp'; - } - if (type === '[object Date]') { - return 'date'; - } - if (type === '[object Arguments]') { - return 'arguments'; - } - if (type === '[object Error]') { - return 'error'; - } +exports.ints = function() { + return { type: types.SET, set: INTS(), not: false }; +}; - // buffer - if (isBuffer(val)) { - return 'buffer'; - } +exports.notInts = function() { + return { type: types.SET, set: INTS(), not: true }; +}; - // es6: Map, WeakMap, Set, WeakSet - if (type === '[object Set]') { - return 'set'; - } - if (type === '[object WeakSet]') { - return 'weakset'; - } - if (type === '[object Map]') { - return 'map'; - } - if (type === '[object WeakMap]') { - return 'weakmap'; - } - if (type === '[object Symbol]') { - return 'symbol'; - } +exports.whitespace = function() { + return { type: types.SET, set: WHITESPACE(), not: false }; +}; - // typed arrays - if (type === '[object Int8Array]') { - return 'int8array'; - } - if (type === '[object Uint8Array]') { - return 'uint8array'; - } - if (type === '[object Uint8ClampedArray]') { - return 'uint8clampedarray'; - } - if (type === '[object Int16Array]') { - return 'int16array'; - } - if (type === '[object Uint16Array]') { - return 'uint16array'; - } - if (type === '[object Int32Array]') { - return 'int32array'; - } - if (type === '[object Uint32Array]') { - return 'uint32array'; - } - if (type === '[object Float32Array]') { - return 'float32array'; - } - if (type === '[object Float64Array]') { - return 'float64array'; - } +exports.notWhitespace = function() { + return { type: types.SET, set: WHITESPACE(), not: true }; +}; - // must be a plain object - return 'object'; +exports.anyChar = function() { + return { type: types.SET, set: NOTANYCHAR(), not: true }; }; @@ -61034,40 +61248,23 @@ module.exports = function kindOf(val) { /* 532 */ /***/ (function(module, exports, __webpack_require__) { -"use strict"; - +var types = __webpack_require__(530); -var isObject = __webpack_require__(533); - -module.exports = function extend(o/*, objects*/) { - if (!isObject(o)) { o = {}; } - - var len = arguments.length; - for (var i = 1; i < len; i++) { - var obj = arguments[i]; - - if (isObject(obj)) { - assign(o, obj); - } - } - return o; +exports.wordBoundary = function() { + return { type: types.POSITION, value: 'b' }; }; -function assign(a, b) { - for (var key in b) { - if (hasOwn(b, key)) { - a[key] = b[key]; - } - } -} +exports.nonWordBoundary = function() { + return { type: types.POSITION, value: 'B' }; +}; -/** - * Returns true if the given `key` is an own property of `obj`. - */ +exports.begin = function() { + return { type: types.POSITION, value: '^' }; +}; -function hasOwn(obj, key) { - return Object.prototype.hasOwnProperty.call(obj, key); -} +exports.end = function() { + return { type: types.POSITION, value: '$' }; +}; /***/ }), @@ -61076,1029 +61273,897 @@ function hasOwn(obj, key) { "use strict"; /*! - * is-extendable + * define-property * - * Copyright (c) 2015, Jon Schlinkert. - * Licensed under the MIT License. + * Copyright (c) 2015-2018, Jon Schlinkert. + * Released under the MIT License. */ -module.exports = function isExtendable(val) { - return typeof val !== 'undefined' && val !== null - && (typeof val === 'object' || typeof val === 'function'); -}; - - -/***/ }), -/* 534 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; +var isobject = __webpack_require__(534); +var isDescriptor = __webpack_require__(535); +var define = (typeof Reflect !== 'undefined' && Reflect.defineProperty) + ? Reflect.defineProperty + : Object.defineProperty; +module.exports = function defineProperty(obj, key, val) { + if (!isobject(obj) && typeof obj !== 'function' && !Array.isArray(obj)) { + throw new TypeError('expected an object, function, or array'); + } -var extend = __webpack_require__(535); + if (typeof key !== 'string') { + throw new TypeError('expected "key" to be a string'); + } -/** - * The main export is a function that takes a `pattern` string and an `options` object. - * - * ```js - & var not = require('regex-not'); - & console.log(not('foo')); - & //=> /^(?:(?!^(?:foo)$).)*$/ - * ``` + if (isDescriptor(val)) { + define(obj, key, val); + return obj; + } + + define(obj, key, { + configurable: true, + enumerable: false, + writable: true, + value: val + }); + + return obj; +}; + + +/***/ }), +/* 534 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +/*! + * isobject * - * @param {String} `pattern` - * @param {Object} `options` - * @return {RegExp} Converts the given `pattern` to a regex using the specified `options`. - * @api public + * Copyright (c) 2014-2017, Jon Schlinkert. + * Released under the MIT License. */ -function toRegex(pattern, options) { - return new RegExp(toRegex.create(pattern, options)); -} -/** - * Create a regex-compatible string from the given `pattern` and `options`. + +module.exports = function isObject(val) { + return val != null && typeof val === 'object' && Array.isArray(val) === false; +}; + + +/***/ }), +/* 535 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +/*! + * is-descriptor * - * ```js - & var not = require('regex-not'); - & console.log(not.create('foo')); - & //=> '^(?:(?!^(?:foo)$).)*$' - * ``` - * @param {String} `pattern` - * @param {Object} `options` - * @return {String} - * @api public + * Copyright (c) 2015-2017, Jon Schlinkert. + * Released under the MIT License. */ -toRegex.create = function(pattern, options) { - if (typeof pattern !== 'string') { - throw new TypeError('expected a string'); - } - var opts = extend({}, options); - if (opts && opts.contains === true) { - opts.strictNegate = false; - } - var open = opts.strictOpen !== false ? '^' : ''; - var close = opts.strictClose !== false ? '$' : ''; - var endChar = opts.endChar ? opts.endChar : '+'; - var str = pattern; +var typeOf = __webpack_require__(536); +var isAccessor = __webpack_require__(537); +var isData = __webpack_require__(539); - if (opts && opts.strictNegate === false) { - str = '(?:(?!(?:' + pattern + ')).)' + endChar; - } else { - str = '(?:(?!^(?:' + pattern + ')$).)' + endChar; +module.exports = function isDescriptor(obj, key) { + if (typeOf(obj) !== 'object') { + return false; } - - return open + str + close; + if ('get' in obj) { + return isAccessor(obj, key); + } + return isData(obj, key); }; -/** - * Expose `toRegex` - */ -module.exports = toRegex; +/***/ }), +/* 536 */ +/***/ (function(module, exports) { +var toString = Object.prototype.toString; -/***/ }), -/* 535 */ -/***/ (function(module, exports, __webpack_require__) { +module.exports = function kindOf(val) { + if (val === void 0) return 'undefined'; + if (val === null) return 'null'; -"use strict"; + var type = typeof val; + if (type === 'boolean') return 'boolean'; + if (type === 'string') return 'string'; + if (type === 'number') return 'number'; + if (type === 'symbol') return 'symbol'; + if (type === 'function') { + return isGeneratorFn(val) ? 'generatorfunction' : 'function'; + } + if (isArray(val)) return 'array'; + if (isBuffer(val)) return 'buffer'; + if (isArguments(val)) return 'arguments'; + if (isDate(val)) return 'date'; + if (isError(val)) return 'error'; + if (isRegexp(val)) return 'regexp'; -var isObject = __webpack_require__(536); + switch (ctorName(val)) { + case 'Symbol': return 'symbol'; + case 'Promise': return 'promise'; -module.exports = function extend(o/*, objects*/) { - if (!isObject(o)) { o = {}; } + // Set, Map, WeakSet, WeakMap + case 'WeakMap': return 'weakmap'; + case 'WeakSet': return 'weakset'; + case 'Map': return 'map'; + case 'Set': return 'set'; - var len = arguments.length; - for (var i = 1; i < len; i++) { - var obj = arguments[i]; + // 8-bit typed arrays + case 'Int8Array': return 'int8array'; + case 'Uint8Array': return 'uint8array'; + case 'Uint8ClampedArray': return 'uint8clampedarray'; - if (isObject(obj)) { - assign(o, obj); - } + // 16-bit typed arrays + case 'Int16Array': return 'int16array'; + case 'Uint16Array': return 'uint16array'; + + // 32-bit typed arrays + case 'Int32Array': return 'int32array'; + case 'Uint32Array': return 'uint32array'; + case 'Float32Array': return 'float32array'; + case 'Float64Array': return 'float64array'; } - return o; + + if (isGeneratorObj(val)) { + return 'generator'; + } + + // Non-plain objects + type = toString.call(val); + switch (type) { + case '[object Object]': return 'object'; + // iterators + case '[object Map Iterator]': return 'mapiterator'; + case '[object Set Iterator]': return 'setiterator'; + case '[object String Iterator]': return 'stringiterator'; + case '[object Array Iterator]': return 'arrayiterator'; + } + + // other + return type.slice(8, -1).toLowerCase().replace(/\s/g, ''); }; -function assign(a, b) { - for (var key in b) { - if (hasOwn(b, key)) { - a[key] = b[key]; +function ctorName(val) { + return typeof val.constructor === 'function' ? val.constructor.name : null; +} + +function isArray(val) { + if (Array.isArray) return Array.isArray(val); + return val instanceof Array; +} + +function isError(val) { + return val instanceof Error || (typeof val.message === 'string' && val.constructor && typeof val.constructor.stackTraceLimit === 'number'); +} + +function isDate(val) { + if (val instanceof Date) return true; + return typeof val.toDateString === 'function' + && typeof val.getDate === 'function' + && typeof val.setDate === 'function'; +} + +function isRegexp(val) { + if (val instanceof RegExp) return true; + return typeof val.flags === 'string' + && typeof val.ignoreCase === 'boolean' + && typeof val.multiline === 'boolean' + && typeof val.global === 'boolean'; +} + +function isGeneratorFn(name, val) { + return ctorName(name) === 'GeneratorFunction'; +} + +function isGeneratorObj(val) { + return typeof val.throw === 'function' + && typeof val.return === 'function' + && typeof val.next === 'function'; +} + +function isArguments(val) { + try { + if (typeof val.length === 'number' && typeof val.callee === 'function') { + return true; + } + } catch (err) { + if (err.message.indexOf('callee') !== -1) { + return true; } } + return false; } /** - * Returns true if the given `key` is an own property of `obj`. + * If you need to support Safari 5-7 (8-10 yr-old browser), + * take a look at https://github.com/feross/is-buffer */ -function hasOwn(obj, key) { - return Object.prototype.hasOwnProperty.call(obj, key); +function isBuffer(val) { + if (val.constructor && typeof val.constructor.isBuffer === 'function') { + return val.constructor.isBuffer(val); + } + return false; } /***/ }), -/* 536 */ +/* 537 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; /*! - * is-extendable + * is-accessor-descriptor * - * Copyright (c) 2015, Jon Schlinkert. - * Licensed under the MIT License. + * Copyright (c) 2015-2017, Jon Schlinkert. + * Released under the MIT License. */ -module.exports = function isExtendable(val) { - return typeof val !== 'undefined' && val !== null - && (typeof val === 'object' || typeof val === 'function'); -}; - +var typeOf = __webpack_require__(538); -/***/ }), -/* 537 */ -/***/ (function(module, exports, __webpack_require__) { +// accessor descriptor properties +var accessor = { + get: 'function', + set: 'function', + configurable: 'boolean', + enumerable: 'boolean' +}; -"use strict"; -/*! - * array-unique - * - * Copyright (c) 2014-2015, Jon Schlinkert. - * Licensed under the MIT License. - */ +function isAccessorDescriptor(obj, prop) { + if (typeof prop === 'string') { + var val = Object.getOwnPropertyDescriptor(obj, prop); + return typeof val !== 'undefined'; + } + if (typeOf(obj) !== 'object') { + return false; + } + if (has(obj, 'value') || has(obj, 'writable')) { + return false; + } -module.exports = function unique(arr) { - if (!Array.isArray(arr)) { - throw new TypeError('array-unique expects an array.'); + if (!has(obj, 'get') || typeof obj.get !== 'function') { + return false; } - var len = arr.length; - var i = -1; + // tldr: it's valid to have "set" be undefined + // "set" might be undefined if `Object.getOwnPropertyDescriptor` + // was used to get the value, and only `get` was defined by the user + if (has(obj, 'set') && typeof obj[key] !== 'function' && typeof obj[key] !== 'undefined') { + return false; + } - while (i++ < len) { - var j = i + 1; + for (var key in obj) { + if (!accessor.hasOwnProperty(key)) { + continue; + } - for (; j < arr.length; ++j) { - if (arr[i] === arr[j]) { - arr.splice(j--, 1); - } + if (typeOf(obj[key]) === accessor[key]) { + continue; } - } - return arr; -}; -module.exports.immutable = function uniqueImmutable(arr) { - if (!Array.isArray(arr)) { - throw new TypeError('array-unique expects an array.'); + if (typeof obj[key] !== 'undefined') { + return false; + } } + return true; +} - var arrLen = arr.length; - var newArr = new Array(arrLen); +function has(obj, key) { + return {}.hasOwnProperty.call(obj, key); +} - for (var i = 0; i < arrLen; i++) { - newArr[i] = arr[i]; - } +/** + * Expose `isAccessorDescriptor` + */ - return module.exports(newArr); -}; +module.exports = isAccessorDescriptor; /***/ }), /* 538 */ -/***/ (function(module, exports, __webpack_require__) { +/***/ (function(module, exports) { -"use strict"; +var toString = Object.prototype.toString; +module.exports = function kindOf(val) { + if (val === void 0) return 'undefined'; + if (val === null) return 'null'; -var utils = __webpack_require__(539); + var type = typeof val; + if (type === 'boolean') return 'boolean'; + if (type === 'string') return 'string'; + if (type === 'number') return 'number'; + if (type === 'symbol') return 'symbol'; + if (type === 'function') { + return isGeneratorFn(val) ? 'generatorfunction' : 'function'; + } -module.exports = function(braces, options) { - braces.compiler + if (isArray(val)) return 'array'; + if (isBuffer(val)) return 'buffer'; + if (isArguments(val)) return 'arguments'; + if (isDate(val)) return 'date'; + if (isError(val)) return 'error'; + if (isRegexp(val)) return 'regexp'; - /** - * bos - */ + switch (ctorName(val)) { + case 'Symbol': return 'symbol'; + case 'Promise': return 'promise'; - .set('bos', function() { - if (this.output) return; - this.ast.queue = isEscaped(this.ast) ? [this.ast.val] : []; - this.ast.count = 1; - }) + // Set, Map, WeakSet, WeakMap + case 'WeakMap': return 'weakmap'; + case 'WeakSet': return 'weakset'; + case 'Map': return 'map'; + case 'Set': return 'set'; - /** - * Square brackets - */ + // 8-bit typed arrays + case 'Int8Array': return 'int8array'; + case 'Uint8Array': return 'uint8array'; + case 'Uint8ClampedArray': return 'uint8clampedarray'; - .set('bracket', function(node) { - var close = node.close; - var open = !node.escaped ? '[' : '\\['; - var negated = node.negated; - var inner = node.inner; + // 16-bit typed arrays + case 'Int16Array': return 'int16array'; + case 'Uint16Array': return 'uint16array'; - inner = inner.replace(/\\(?=[\\\w]|$)/g, '\\\\'); - if (inner === ']-') { - inner = '\\]\\-'; - } + // 32-bit typed arrays + case 'Int32Array': return 'int32array'; + case 'Uint32Array': return 'uint32array'; + case 'Float32Array': return 'float32array'; + case 'Float64Array': return 'float64array'; + } - if (negated && inner.indexOf('.') === -1) { - inner += '.'; - } - if (negated && inner.indexOf('/') === -1) { - inner += '/'; - } + if (isGeneratorObj(val)) { + return 'generator'; + } - var val = open + negated + inner + close; - var queue = node.parent.queue; - var last = utils.arrayify(queue.pop()); + // Non-plain objects + type = toString.call(val); + switch (type) { + case '[object Object]': return 'object'; + // iterators + case '[object Map Iterator]': return 'mapiterator'; + case '[object Set Iterator]': return 'setiterator'; + case '[object String Iterator]': return 'stringiterator'; + case '[object Array Iterator]': return 'arrayiterator'; + } - queue.push(utils.join(last, val)); - queue.push.apply(queue, []); - }) + // other + return type.slice(8, -1).toLowerCase().replace(/\s/g, ''); +}; - /** - * Brace - */ +function ctorName(val) { + return typeof val.constructor === 'function' ? val.constructor.name : null; +} - .set('brace', function(node) { - node.queue = isEscaped(node) ? [node.val] : []; - node.count = 1; - return this.mapVisit(node.nodes); - }) +function isArray(val) { + if (Array.isArray) return Array.isArray(val); + return val instanceof Array; +} - /** - * Open - */ +function isError(val) { + return val instanceof Error || (typeof val.message === 'string' && val.constructor && typeof val.constructor.stackTraceLimit === 'number'); +} - .set('brace.open', function(node) { - node.parent.open = node.val; - }) +function isDate(val) { + if (val instanceof Date) return true; + return typeof val.toDateString === 'function' + && typeof val.getDate === 'function' + && typeof val.setDate === 'function'; +} - /** - * Inner - */ +function isRegexp(val) { + if (val instanceof RegExp) return true; + return typeof val.flags === 'string' + && typeof val.ignoreCase === 'boolean' + && typeof val.multiline === 'boolean' + && typeof val.global === 'boolean'; +} - .set('text', function(node) { - var queue = node.parent.queue; - var escaped = node.escaped; - var segs = [node.val]; +function isGeneratorFn(name, val) { + return ctorName(name) === 'GeneratorFunction'; +} - if (node.optimize === false) { - options = utils.extend({}, options, {optimize: false}); - } +function isGeneratorObj(val) { + return typeof val.throw === 'function' + && typeof val.return === 'function' + && typeof val.next === 'function'; +} - if (node.multiplier > 1) { - node.parent.count *= node.multiplier; - } +function isArguments(val) { + try { + if (typeof val.length === 'number' && typeof val.callee === 'function') { + return true; + } + } catch (err) { + if (err.message.indexOf('callee') !== -1) { + return true; + } + } + return false; +} - if (options.quantifiers === true && utils.isQuantifier(node.val)) { - escaped = true; +/** + * If you need to support Safari 5-7 (8-10 yr-old browser), + * take a look at https://github.com/feross/is-buffer + */ - } else if (node.val.length > 1) { - if (isType(node.parent, 'brace') && !isEscaped(node)) { - var expanded = utils.expand(node.val, options); - segs = expanded.segs; +function isBuffer(val) { + if (val.constructor && typeof val.constructor.isBuffer === 'function') { + return val.constructor.isBuffer(val); + } + return false; +} - if (expanded.isOptimized) { - node.parent.isOptimized = true; - } - // if nothing was expanded, we probably have a literal brace - if (!segs.length) { - var val = (expanded.val || node.val); - if (options.unescape !== false) { - // unescape unexpanded brace sequence/set separators - val = val.replace(/\\([,.])/g, '$1'); - // strip quotes - val = val.replace(/["'`]/g, ''); - } +/***/ }), +/* 539 */ +/***/ (function(module, exports, __webpack_require__) { - segs = [val]; - escaped = true; - } - } +"use strict"; +/*! + * is-data-descriptor + * + * Copyright (c) 2015-2017, Jon Schlinkert. + * Released under the MIT License. + */ - } else if (node.val === ',') { - if (options.expand) { - node.parent.queue.push(['']); - segs = ['']; - } else { - segs = ['|']; - } - } else { - escaped = true; - } - if (escaped && isType(node.parent, 'brace')) { - if (node.parent.nodes.length <= 4 && node.parent.count === 1) { - node.parent.escaped = true; - } else if (node.parent.length <= 3) { - node.parent.escaped = true; - } - } - if (!hasQueue(node.parent)) { - node.parent.queue = segs; - return; - } +var typeOf = __webpack_require__(540); - var last = utils.arrayify(queue.pop()); - if (node.parent.count > 1 && options.expand) { - last = multiply(last, node.parent.count); - node.parent.count = 1; - } +module.exports = function isDataDescriptor(obj, prop) { + // data descriptor properties + var data = { + configurable: 'boolean', + enumerable: 'boolean', + writable: 'boolean' + }; - queue.push(utils.join(utils.flatten(last), segs.shift())); - queue.push.apply(queue, segs); - }) + if (typeOf(obj) !== 'object') { + return false; + } - /** - * Close - */ + if (typeof prop === 'string') { + var val = Object.getOwnPropertyDescriptor(obj, prop); + return typeof val !== 'undefined'; + } - .set('brace.close', function(node) { - var queue = node.parent.queue; - var prev = node.parent.parent; - var last = prev.queue.pop(); - var open = node.parent.open; - var close = node.val; + if (!('value' in obj) && !('writable' in obj)) { + return false; + } - if (open && close && isOptimized(node, options)) { - open = '('; - close = ')'; - } + for (var key in obj) { + if (key === 'value') continue; - // if a close brace exists, and the previous segment is one character - // don't wrap the result in braces or parens - var ele = utils.last(queue); - if (node.parent.count > 1 && options.expand) { - ele = multiply(queue.pop(), node.parent.count); - node.parent.count = 1; - queue.push(ele); - } + if (!data.hasOwnProperty(key)) { + continue; + } - if (close && typeof ele === 'string' && ele.length === 1) { - open = ''; - close = ''; - } + if (typeOf(obj[key]) === data[key]) { + continue; + } - if ((isLiteralBrace(node, options) || noInner(node)) && !node.parent.hasEmpty) { - queue.push(utils.join(open, queue.pop() || '')); - queue = utils.flatten(utils.join(queue, close)); - } + if (typeof obj[key] !== 'undefined') { + return false; + } + } + return true; +}; - if (typeof last === 'undefined') { - prev.queue = [queue]; - } else { - prev.queue.push(utils.flatten(utils.join(last, queue))); - } - }) - /** - * eos - */ +/***/ }), +/* 540 */ +/***/ (function(module, exports) { - .set('eos', function(node) { - if (this.input) return; +var toString = Object.prototype.toString; - if (options.optimize !== false) { - this.output = utils.last(utils.flatten(this.ast.queue)); - } else if (Array.isArray(utils.last(this.ast.queue))) { - this.output = utils.flatten(this.ast.queue.pop()); - } else { - this.output = utils.flatten(this.ast.queue); - } +module.exports = function kindOf(val) { + if (val === void 0) return 'undefined'; + if (val === null) return 'null'; - if (node.parent.count > 1 && options.expand) { - this.output = multiply(this.output, node.parent.count); - } + var type = typeof val; + if (type === 'boolean') return 'boolean'; + if (type === 'string') return 'string'; + if (type === 'number') return 'number'; + if (type === 'symbol') return 'symbol'; + if (type === 'function') { + return isGeneratorFn(val) ? 'generatorfunction' : 'function'; + } - this.output = utils.arrayify(this.output); - this.ast.queue = []; - }); + if (isArray(val)) return 'array'; + if (isBuffer(val)) return 'buffer'; + if (isArguments(val)) return 'arguments'; + if (isDate(val)) return 'date'; + if (isError(val)) return 'error'; + if (isRegexp(val)) return 'regexp'; -}; + switch (ctorName(val)) { + case 'Symbol': return 'symbol'; + case 'Promise': return 'promise'; -/** - * Multiply the segments in the current brace level - */ + // Set, Map, WeakSet, WeakMap + case 'WeakMap': return 'weakmap'; + case 'WeakSet': return 'weakset'; + case 'Map': return 'map'; + case 'Set': return 'set'; -function multiply(queue, n, options) { - return utils.flatten(utils.repeat(utils.arrayify(queue), n)); -} + // 8-bit typed arrays + case 'Int8Array': return 'int8array'; + case 'Uint8Array': return 'uint8array'; + case 'Uint8ClampedArray': return 'uint8clampedarray'; -/** - * Return true if `node` is escaped - */ + // 16-bit typed arrays + case 'Int16Array': return 'int16array'; + case 'Uint16Array': return 'uint16array'; -function isEscaped(node) { - return node.escaped === true; -} + // 32-bit typed arrays + case 'Int32Array': return 'int32array'; + case 'Uint32Array': return 'uint32array'; + case 'Float32Array': return 'float32array'; + case 'Float64Array': return 'float64array'; + } -/** - * Returns true if regex parens should be used for sets. If the parent `type` - * is not `brace`, then we're on a root node, which means we should never - * expand segments and open/close braces should be `{}` (since this indicates - * a brace is missing from the set) - */ + if (isGeneratorObj(val)) { + return 'generator'; + } -function isOptimized(node, options) { - if (node.parent.isOptimized) return true; - return isType(node.parent, 'brace') - && !isEscaped(node.parent) - && options.expand !== true; + // Non-plain objects + type = toString.call(val); + switch (type) { + case '[object Object]': return 'object'; + // iterators + case '[object Map Iterator]': return 'mapiterator'; + case '[object Set Iterator]': return 'setiterator'; + case '[object String Iterator]': return 'stringiterator'; + case '[object Array Iterator]': return 'arrayiterator'; + } + + // other + return type.slice(8, -1).toLowerCase().replace(/\s/g, ''); +}; + +function ctorName(val) { + return typeof val.constructor === 'function' ? val.constructor.name : null; } -/** - * Returns true if the value in `node` should be wrapped in a literal brace. - * @return {Boolean} - */ +function isArray(val) { + if (Array.isArray) return Array.isArray(val); + return val instanceof Array; +} -function isLiteralBrace(node, options) { - return isEscaped(node.parent) || options.optimize !== false; +function isError(val) { + return val instanceof Error || (typeof val.message === 'string' && val.constructor && typeof val.constructor.stackTraceLimit === 'number'); } -/** - * Returns true if the given `node` does not have an inner value. - * @return {Boolean} - */ +function isDate(val) { + if (val instanceof Date) return true; + return typeof val.toDateString === 'function' + && typeof val.getDate === 'function' + && typeof val.setDate === 'function'; +} -function noInner(node, type) { - if (node.parent.queue.length === 1) { - return true; - } - var nodes = node.parent.nodes; - return nodes.length === 3 - && isType(nodes[0], 'brace.open') - && !isType(nodes[1], 'text') - && isType(nodes[2], 'brace.close'); +function isRegexp(val) { + if (val instanceof RegExp) return true; + return typeof val.flags === 'string' + && typeof val.ignoreCase === 'boolean' + && typeof val.multiline === 'boolean' + && typeof val.global === 'boolean'; } -/** - * Returns true if the given `node` is the given `type` - * @return {Boolean} - */ +function isGeneratorFn(name, val) { + return ctorName(name) === 'GeneratorFunction'; +} -function isType(node, type) { - return typeof node !== 'undefined' && node.type === type; +function isGeneratorObj(val) { + return typeof val.throw === 'function' + && typeof val.return === 'function' + && typeof val.next === 'function'; +} + +function isArguments(val) { + try { + if (typeof val.length === 'number' && typeof val.callee === 'function') { + return true; + } + } catch (err) { + if (err.message.indexOf('callee') !== -1) { + return true; + } + } + return false; } /** - * Returns true if the given `node` has a non-empty queue. - * @return {Boolean} + * If you need to support Safari 5-7 (8-10 yr-old browser), + * take a look at https://github.com/feross/is-buffer */ -function hasQueue(node) { - return Array.isArray(node.queue) && node.queue.length; +function isBuffer(val) { + if (val.constructor && typeof val.constructor.isBuffer === 'function') { + return val.constructor.isBuffer(val); + } + return false; } /***/ }), -/* 539 */ +/* 541 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var splitString = __webpack_require__(540); -var utils = module.exports; +var isExtendable = __webpack_require__(542); +var assignSymbols = __webpack_require__(544); -/** - * Module dependencies - */ +module.exports = Object.assign || function(obj/*, objects*/) { + if (obj === null || typeof obj === 'undefined') { + throw new TypeError('Cannot convert undefined or null to object'); + } + if (!isObject(obj)) { + obj = {}; + } + for (var i = 1; i < arguments.length; i++) { + var val = arguments[i]; + if (isString(val)) { + val = toObject(val); + } + if (isObject(val)) { + assign(obj, val); + assignSymbols(obj, val); + } + } + return obj; +}; -utils.extend = __webpack_require__(532); -utils.flatten = __webpack_require__(546); -utils.isObject = __webpack_require__(544); -utils.fillRange = __webpack_require__(547); -utils.repeat = __webpack_require__(554); -utils.unique = __webpack_require__(537); +function assign(a, b) { + for (var key in b) { + if (hasOwn(b, key)) { + a[key] = b[key]; + } + } +} -utils.define = function(obj, key, val) { - Object.defineProperty(obj, key, { - writable: true, - configurable: true, - enumerable: false, - value: val - }); -}; +function isString(val) { + return (val && typeof val === 'string'); +} -/** - * Returns true if the given string contains only empty brace sets. - */ +function toObject(str) { + var obj = {}; + for (var i in str) { + obj[i] = str[i]; + } + return obj; +} -utils.isEmptySets = function(str) { - return /^(?:\{,\})+$/.test(str); -}; +function isObject(val) { + return (val && typeof val === 'object') || isExtendable(val); +} /** - * Returns true if the given string contains only empty brace sets. + * Returns true if the given `key` is an own property of `obj`. */ -utils.isQuotedString = function(str) { - var open = str.charAt(0); - if (open === '\'' || open === '"' || open === '`') { - return str.slice(-1) === open; - } - return false; -}; +function hasOwn(obj, key) { + return Object.prototype.hasOwnProperty.call(obj, key); +} -/** - * Create the key to use for memoization. The unique key is generated - * by iterating over the options and concatenating key-value pairs - * to the pattern string. - */ +function isEnum(obj, key) { + return Object.prototype.propertyIsEnumerable.call(obj, key); +} -utils.createKey = function(pattern, options) { - var id = pattern; - if (typeof options === 'undefined') { - return id; - } - var keys = Object.keys(options); - for (var i = 0; i < keys.length; i++) { - var key = keys[i]; - id += ';' + key + '=' + String(options[key]); - } - return id; -}; -/** - * Normalize options +/***/ }), +/* 542 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +/*! + * is-extendable + * + * Copyright (c) 2015-2017, Jon Schlinkert. + * Released under the MIT License. */ -utils.createOptions = function(options) { - var opts = utils.extend.apply(null, arguments); - if (typeof opts.expand === 'boolean') { - opts.optimize = !opts.expand; - } - if (typeof opts.optimize === 'boolean') { - opts.expand = !opts.optimize; - } - if (opts.optimize === true) { - opts.makeRe = true; - } - return opts; + + +var isPlainObject = __webpack_require__(543); + +module.exports = function isExtendable(val) { + return isPlainObject(val) || typeof val === 'function' || Array.isArray(val); }; -/** - * Join patterns in `a` to patterns in `b` + +/***/ }), +/* 543 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +/*! + * is-plain-object + * + * Copyright (c) 2014-2017, Jon Schlinkert. + * Released under the MIT License. */ -utils.join = function(a, b, options) { - options = options || {}; - a = utils.arrayify(a); - b = utils.arrayify(b); - if (!a.length) return b; - if (!b.length) return a; - var len = a.length; - var idx = -1; - var arr = []; +var isObject = __webpack_require__(534); - while (++idx < len) { - var val = a[idx]; - if (Array.isArray(val)) { - for (var i = 0; i < val.length; i++) { - val[i] = utils.join(val[i], b, options); - } - arr.push(val); - continue; - } +function isObjectObject(o) { + return isObject(o) === true + && Object.prototype.toString.call(o) === '[object Object]'; +} - for (var j = 0; j < b.length; j++) { - var bval = b[j]; +module.exports = function isPlainObject(o) { + var ctor,prot; - if (Array.isArray(bval)) { - arr.push(utils.join(val, bval, options)); - } else { - arr.push(val + bval); - } - } - } - return arr; -}; + if (isObjectObject(o) === false) return false; -/** - * Split the given string on `,` if not escaped. - */ + // If has modified constructor + ctor = o.constructor; + if (typeof ctor !== 'function') return false; -utils.split = function(str, options) { - var opts = utils.extend({sep: ','}, options); - if (typeof opts.keepQuotes !== 'boolean') { - opts.keepQuotes = true; - } - if (opts.unescape === false) { - opts.keepEscaping = true; + // If has modified prototype + prot = ctor.prototype; + if (isObjectObject(prot) === false) return false; + + // If constructor does not have an Object-specific method + if (prot.hasOwnProperty('isPrototypeOf') === false) { + return false; } - return splitString(str, opts, utils.escapeBrackets(opts)); + + // Most likely a plain Object + return true; }; -/** - * Expand ranges or sets in the given `pattern`. + +/***/ }), +/* 544 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +/*! + * assign-symbols * - * @param {String} `str` - * @param {Object} `options` - * @return {Object} + * Copyright (c) 2015, Jon Schlinkert. + * Licensed under the MIT License. */ -utils.expand = function(str, options) { - var opts = utils.extend({rangeLimit: 10000}, options); - var segs = utils.split(str, opts); - var tok = { segs: segs }; - if (utils.isQuotedString(str)) { - return tok; - } - if (opts.rangeLimit === true) { - opts.rangeLimit = 10000; +module.exports = function(receiver, objects) { + if (receiver === null || typeof receiver === 'undefined') { + throw new TypeError('expected first argument to be an object.'); } - if (segs.length > 1) { - if (opts.optimize === false) { - tok.val = segs[0]; - return tok; - } + if (typeof objects === 'undefined' || typeof Symbol === 'undefined') { + return receiver; + } - tok.segs = utils.stringifyArray(tok.segs); - } else if (segs.length === 1) { - var arr = str.split('..'); - - if (arr.length === 1) { - tok.val = tok.segs[tok.segs.length - 1] || tok.val || str; - tok.segs = []; - return tok; - } - - if (arr.length === 2 && arr[0] === arr[1]) { - tok.escaped = true; - tok.val = arr[0]; - tok.segs = []; - return tok; - } - - if (arr.length > 1) { - if (opts.optimize !== false) { - opts.optimize = true; - delete opts.expand; - } - - if (opts.optimize !== true) { - var min = Math.min(arr[0], arr[1]); - var max = Math.max(arr[0], arr[1]); - var step = arr[2] || 1; - - if (opts.rangeLimit !== false && ((max - min) / step >= opts.rangeLimit)) { - throw new RangeError('expanded array length exceeds range limit. Use options.rangeLimit to increase or disable the limit.'); - } - } - - arr.push(opts); - tok.segs = utils.fillRange.apply(null, arr); - - if (!tok.segs.length) { - tok.escaped = true; - tok.val = str; - return tok; - } - - if (opts.optimize === true) { - tok.segs = utils.stringifyArray(tok.segs); - } - - if (tok.segs === '') { - tok.val = str; - } else { - tok.val = tok.segs[0]; - } - return tok; - } - } else { - tok.val = str; + if (typeof Object.getOwnPropertySymbols !== 'function') { + return receiver; } - return tok; -}; - -/** - * Ensure commas inside brackets and parens are not split. - * @param {Object} `tok` Token from the `split-string` module - * @return {undefined} - */ - -utils.escapeBrackets = function(options) { - return function(tok) { - if (tok.escaped && tok.val === 'b') { - tok.val = '\\b'; - return; - } - - if (tok.val !== '(' && tok.val !== '[') return; - var opts = utils.extend({}, options); - var brackets = []; - var parens = []; - var stack = []; - var val = tok.val; - var str = tok.str; - var i = tok.idx - 1; - - while (++i < str.length) { - var ch = str[i]; - - if (ch === '\\') { - val += (opts.keepEscaping === false ? '' : ch) + str[++i]; - continue; - } - if (ch === '(') { - parens.push(ch); - stack.push(ch); - } + var isEnumerable = Object.prototype.propertyIsEnumerable; + var target = Object(receiver); + var len = arguments.length, i = 0; - if (ch === '[') { - brackets.push(ch); - stack.push(ch); - } + while (++i < len) { + var provider = Object(arguments[i]); + var names = Object.getOwnPropertySymbols(provider); - if (ch === ')') { - parens.pop(); - stack.pop(); - if (!stack.length) { - val += ch; - break; - } - } + for (var j = 0; j < names.length; j++) { + var key = names[j]; - if (ch === ']') { - brackets.pop(); - stack.pop(); - if (!stack.length) { - val += ch; - break; - } + if (isEnumerable.call(provider, key)) { + target[key] = provider[key]; } - val += ch; } - - tok.split = false; - tok.val = val.slice(1); - tok.idx = i; - }; + } + return target; }; -/** - * Returns true if the given string looks like a regex quantifier - * @return {Boolean} - */ - -utils.isQuantifier = function(str) { - return /^(?:[0-9]?,[0-9]|[0-9],)$/.test(str); -}; -/** - * Cast `val` to an array. - * @param {*} `val` - */ +/***/ }), +/* 545 */ +/***/ (function(module, exports, __webpack_require__) { -utils.stringifyArray = function(arr) { - return [utils.arrayify(arr).join('|')]; -}; +"use strict"; -/** - * Cast `val` to an array. - * @param {*} `val` - */ -utils.arrayify = function(arr) { - if (typeof arr === 'undefined') { - return []; - } - if (typeof arr === 'string') { - return [arr]; - } - return arr; -}; +var extend = __webpack_require__(546); +var safe = __webpack_require__(527); /** - * Returns true if the given `str` is a non-empty string - * @return {Boolean} + * The main export is a function that takes a `pattern` string and an `options` object. + * + * ```js + & var not = require('regex-not'); + & console.log(not('foo')); + & //=> /^(?:(?!^(?:foo)$).)*$/ + * ``` + * + * @param {String} `pattern` + * @param {Object} `options` + * @return {RegExp} Converts the given `pattern` to a regex using the specified `options`. + * @api public */ -utils.isString = function(str) { - return str != null && typeof str === 'string'; -}; +function toRegex(pattern, options) { + return new RegExp(toRegex.create(pattern, options)); +} /** - * Get the last element from `array` - * @param {Array} `array` - * @return {*} - */ - -utils.last = function(arr, n) { - return arr[arr.length - (n || 1)]; -}; - -utils.escapeRegex = function(str) { - return str.replace(/\\?([!^*?()[\]{}+?/])/g, '\\$1'); -}; - - -/***/ }), -/* 540 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; -/*! - * split-string + * Create a regex-compatible string from the given `pattern` and `options`. * - * Copyright (c) 2015-2017, Jon Schlinkert. - * Released under the MIT License. + * ```js + & var not = require('regex-not'); + & console.log(not.create('foo')); + & //=> '^(?:(?!^(?:foo)$).)*$' + * ``` + * @param {String} `pattern` + * @param {Object} `options` + * @return {String} + * @api public */ - - -var extend = __webpack_require__(541); - -module.exports = function(str, options, fn) { - if (typeof str !== 'string') { +toRegex.create = function(pattern, options) { + if (typeof pattern !== 'string') { throw new TypeError('expected a string'); } - if (typeof options === 'function') { - fn = options; - options = null; - } - - // allow separator to be defined as a string - if (typeof options === 'string') { - options = { sep: options }; - } - - var opts = extend({sep: '.'}, options); - var quotes = opts.quotes || ['"', "'", '`']; - var brackets; - - if (opts.brackets === true) { - brackets = { - '<': '>', - '(': ')', - '[': ']', - '{': '}' - }; - } else if (opts.brackets) { - brackets = opts.brackets; + var opts = extend({}, options); + if (opts.contains === true) { + opts.strictNegate = false; } - var tokens = []; - var stack = []; - var arr = ['']; - var sep = opts.sep; - var len = str.length; - var idx = -1; - var closeIdx; + var open = opts.strictOpen !== false ? '^' : ''; + var close = opts.strictClose !== false ? '$' : ''; + var endChar = opts.endChar ? opts.endChar : '+'; + var str = pattern; - function expected() { - if (brackets && stack.length) { - return brackets[stack[stack.length - 1]]; - } + if (opts.strictNegate === false) { + str = '(?:(?!(?:' + pattern + ')).)' + endChar; + } else { + str = '(?:(?!^(?:' + pattern + ')$).)' + endChar; } - while (++idx < len) { - var ch = str[idx]; - var next = str[idx + 1]; - var tok = { val: ch, idx: idx, arr: arr, str: str }; - tokens.push(tok); - - if (ch === '\\') { - tok.val = keepEscaping(opts, str, idx) === true ? (ch + next) : next; - tok.escaped = true; - if (typeof fn === 'function') { - fn(tok); - } - arr[arr.length - 1] += tok.val; - idx++; - continue; - } - - if (brackets && brackets[ch]) { - stack.push(ch); - var e = expected(); - var i = idx + 1; - - if (str.indexOf(e, i + 1) !== -1) { - while (stack.length && i < len) { - var s = str[++i]; - if (s === '\\') { - s++; - continue; - } - - if (quotes.indexOf(s) !== -1) { - i = getClosingQuote(str, s, i + 1); - continue; - } - - e = expected(); - if (stack.length && str.indexOf(e, i + 1) === -1) { - break; - } - - if (brackets[s]) { - stack.push(s); - continue; - } - - if (e === s) { - stack.pop(); - } - } - } - - closeIdx = i; - if (closeIdx === -1) { - arr[arr.length - 1] += ch; - continue; - } - - ch = str.slice(idx, closeIdx + 1); - tok.val = ch; - tok.idx = idx = closeIdx; - } - - if (quotes.indexOf(ch) !== -1) { - closeIdx = getClosingQuote(str, ch, idx + 1); - if (closeIdx === -1) { - arr[arr.length - 1] += ch; - continue; - } - - if (keepQuotes(ch, opts) === true) { - ch = str.slice(idx, closeIdx + 1); - } else { - ch = str.slice(idx + 1, closeIdx); - } - - tok.val = ch; - tok.idx = idx = closeIdx; - } - - if (typeof fn === 'function') { - fn(tok, tokens); - ch = tok.val; - idx = tok.idx; - } - - if (tok.val === sep && tok.split !== false) { - arr.push(''); - continue; - } - - arr[arr.length - 1] += tok.val; + var res = open + str + close; + if (opts.safe === true && safe(res) === false) { + throw new Error('potentially unsafe regular expression: ' + res); } - return arr; + return res; }; -function getClosingQuote(str, ch, i, brackets) { - var idx = str.indexOf(ch, i); - if (str.charAt(idx - 1) === '\\') { - return getClosingQuote(str, ch, idx + 1); - } - return idx; -} - -function keepQuotes(ch, opts) { - if (opts.keepDoubleQuotes === true && ch === '"') return true; - if (opts.keepSingleQuotes === true && ch === "'") return true; - return opts.keepQuotes; -} +/** + * Expose `toRegex` + */ -function keepEscaping(opts, str, idx) { - if (typeof opts.keepEscaping === 'function') { - return opts.keepEscaping(str, idx); - } - return opts.keepEscaping === true || str[idx + 1] === '\\'; -} +module.exports = toRegex; /***/ }), -/* 541 */ +/* 546 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var isExtendable = __webpack_require__(542); -var assignSymbols = __webpack_require__(545); +var isExtendable = __webpack_require__(547); +var assignSymbols = __webpack_require__(544); module.exports = Object.assign || function(obj/*, objects*/) { if (obj === null || typeof obj === 'undefined') { @@ -62158,7 +62223,7 @@ function isEnum(obj, key) { /***/ }), -/* 542 */ +/* 547 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -62179,75 +62244,102 @@ module.exports = function isExtendable(val) { /***/ }), -/* 543 */ +/* 548 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; /*! - * is-plain-object + * array-unique * - * Copyright (c) 2014-2017, Jon Schlinkert. - * Released under the MIT License. + * Copyright (c) 2014-2015, Jon Schlinkert. + * Licensed under the MIT License. */ -var isObject = __webpack_require__(544); +module.exports = function unique(arr) { + if (!Array.isArray(arr)) { + throw new TypeError('array-unique expects an array.'); + } -function isObjectObject(o) { - return isObject(o) === true - && Object.prototype.toString.call(o) === '[object Object]'; -} + var len = arr.length; + var i = -1; -module.exports = function isPlainObject(o) { - var ctor,prot; + while (i++ < len) { + var j = i + 1; - if (isObjectObject(o) === false) return false; + for (; j < arr.length; ++j) { + if (arr[i] === arr[j]) { + arr.splice(j--, 1); + } + } + } + return arr; +}; - // If has modified constructor - ctor = o.constructor; - if (typeof ctor !== 'function') return false; +module.exports.immutable = function uniqueImmutable(arr) { + if (!Array.isArray(arr)) { + throw new TypeError('array-unique expects an array.'); + } - // If has modified prototype - prot = ctor.prototype; - if (isObjectObject(prot) === false) return false; + var arrLen = arr.length; + var newArr = new Array(arrLen); - // If constructor does not have an Object-specific method - if (prot.hasOwnProperty('isPrototypeOf') === false) { - return false; + for (var i = 0; i < arrLen; i++) { + newArr[i] = arr[i]; } - // Most likely a plain Object - return true; + return module.exports(newArr); }; /***/ }), -/* 544 */ +/* 549 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -/*! - * isobject - * - * Copyright (c) 2014-2017, Jon Schlinkert. - * Released under the MIT License. - */ +var isObject = __webpack_require__(550); -module.exports = function isObject(val) { - return val != null && typeof val === 'object' && Array.isArray(val) === false; +module.exports = function extend(o/*, objects*/) { + if (!isObject(o)) { o = {}; } + + var len = arguments.length; + for (var i = 1; i < len; i++) { + var obj = arguments[i]; + + if (isObject(obj)) { + assign(o, obj); + } + } + return o; }; +function assign(a, b) { + for (var key in b) { + if (hasOwn(b, key)) { + a[key] = b[key]; + } + } +} + +/** + * Returns true if the given `key` is an own property of `obj`. + */ + +function hasOwn(obj, key) { + return Object.prototype.hasOwnProperty.call(obj, key); +} + /***/ }), -/* 545 */ +/* 550 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; /*! - * assign-symbols + * is-extendable * * Copyright (c) 2015, Jon Schlinkert. * Licensed under the MIT License. @@ -62255,569 +62347,649 @@ module.exports = function isObject(val) { -module.exports = function(receiver, objects) { - if (receiver === null || typeof receiver === 'undefined') { - throw new TypeError('expected first argument to be an object.'); - } +module.exports = function isExtendable(val) { + return typeof val !== 'undefined' && val !== null + && (typeof val === 'object' || typeof val === 'function'); +}; - if (typeof objects === 'undefined' || typeof Symbol === 'undefined') { - return receiver; - } - if (typeof Object.getOwnPropertySymbols !== 'function') { - return receiver; - } +/***/ }), +/* 551 */ +/***/ (function(module, exports, __webpack_require__) { - var isEnumerable = Object.prototype.propertyIsEnumerable; - var target = Object(receiver); - var len = arguments.length, i = 0; +"use strict"; - while (++i < len) { - var provider = Object(arguments[i]); - var names = Object.getOwnPropertySymbols(provider); - for (var j = 0; j < names.length; j++) { - var key = names[j]; +var utils = __webpack_require__(552); - if (isEnumerable.call(provider, key)) { - target[key] = provider[key]; +module.exports = function(braces, options) { + braces.compiler + + /** + * bos + */ + + .set('bos', function() { + if (this.output) return; + this.ast.queue = isEscaped(this.ast) ? [this.ast.val] : []; + this.ast.count = 1; + }) + + /** + * Square brackets + */ + + .set('bracket', function(node) { + var close = node.close; + var open = !node.escaped ? '[' : '\\['; + var negated = node.negated; + var inner = node.inner; + + inner = inner.replace(/\\(?=[\\\w]|$)/g, '\\\\'); + if (inner === ']-') { + inner = '\\]\\-'; } - } - } - return target; -}; + if (negated && inner.indexOf('.') === -1) { + inner += '.'; + } + if (negated && inner.indexOf('/') === -1) { + inner += '/'; + } -/***/ }), -/* 546 */ -/***/ (function(module, exports, __webpack_require__) { + var val = open + negated + inner + close; + var queue = node.parent.queue; + var last = utils.arrayify(queue.pop()); -"use strict"; -/*! - * arr-flatten - * - * Copyright (c) 2014-2017, Jon Schlinkert. - * Released under the MIT License. - */ + queue.push(utils.join(last, val)); + queue.push.apply(queue, []); + }) + /** + * Brace + */ + .set('brace', function(node) { + node.queue = isEscaped(node) ? [node.val] : []; + node.count = 1; + return this.mapVisit(node.nodes); + }) -module.exports = function (arr) { - return flat(arr, []); -}; + /** + * Open + */ -function flat(arr, res) { - var i = 0, cur; - var len = arr.length; - for (; i < len; i++) { - cur = arr[i]; - Array.isArray(cur) ? flat(cur, res) : res.push(cur); - } - return res; -} + .set('brace.open', function(node) { + node.parent.open = node.val; + }) + /** + * Inner + */ -/***/ }), -/* 547 */ -/***/ (function(module, exports, __webpack_require__) { + .set('text', function(node) { + var queue = node.parent.queue; + var escaped = node.escaped; + var segs = [node.val]; -"use strict"; -/*! - * fill-range - * - * Copyright (c) 2014-2015, 2017, Jon Schlinkert. - * Released under the MIT License. - */ + if (node.optimize === false) { + options = utils.extend({}, options, {optimize: false}); + } + if (node.multiplier > 1) { + node.parent.count *= node.multiplier; + } + if (options.quantifiers === true && utils.isQuantifier(node.val)) { + escaped = true; -var util = __webpack_require__(111); -var isNumber = __webpack_require__(548); -var extend = __webpack_require__(550); -var repeat = __webpack_require__(552); -var toRegex = __webpack_require__(553); + } else if (node.val.length > 1) { + if (isType(node.parent, 'brace') && !isEscaped(node)) { + var expanded = utils.expand(node.val, options); + segs = expanded.segs; -/** - * Return a range of numbers or letters. - * - * @param {String} `start` Start of the range - * @param {String} `stop` End of the range - * @param {String} `step` Increment or decrement to use. - * @param {Function} `fn` Custom function to modify each element in the range. - * @return {Array} - */ + if (expanded.isOptimized) { + node.parent.isOptimized = true; + } -function fillRange(start, stop, step, options) { - if (typeof start === 'undefined') { - return []; - } + // if nothing was expanded, we probably have a literal brace + if (!segs.length) { + var val = (expanded.val || node.val); + if (options.unescape !== false) { + // unescape unexpanded brace sequence/set separators + val = val.replace(/\\([,.])/g, '$1'); + // strip quotes + val = val.replace(/["'`]/g, ''); + } - if (typeof stop === 'undefined' || start === stop) { - // special case, for handling negative zero - var isString = typeof start === 'string'; - if (isNumber(start) && !toNumber(start)) { - return [isString ? '0' : 0]; - } - return [start]; - } + segs = [val]; + escaped = true; + } + } - if (typeof step !== 'number' && typeof step !== 'string') { - options = step; - step = undefined; - } + } else if (node.val === ',') { + if (options.expand) { + node.parent.queue.push(['']); + segs = ['']; + } else { + segs = ['|']; + } + } else { + escaped = true; + } - if (typeof options === 'function') { - options = { transform: options }; - } + if (escaped && isType(node.parent, 'brace')) { + if (node.parent.nodes.length <= 4 && node.parent.count === 1) { + node.parent.escaped = true; + } else if (node.parent.length <= 3) { + node.parent.escaped = true; + } + } - var opts = extend({step: step}, options); - if (opts.step && !isValidNumber(opts.step)) { - if (opts.strictRanges === true) { - throw new TypeError('expected options.step to be a number'); - } - return []; - } + if (!hasQueue(node.parent)) { + node.parent.queue = segs; + return; + } - opts.isNumber = isValidNumber(start) && isValidNumber(stop); - if (!opts.isNumber && !isValid(start, stop)) { - if (opts.strictRanges === true) { - throw new RangeError('invalid range arguments: ' + util.inspect([start, stop])); - } - return []; - } + var last = utils.arrayify(queue.pop()); + if (node.parent.count > 1 && options.expand) { + last = multiply(last, node.parent.count); + node.parent.count = 1; + } - opts.isPadded = isPadded(start) || isPadded(stop); - opts.toString = opts.stringify - || typeof opts.step === 'string' - || typeof start === 'string' - || typeof stop === 'string' - || !opts.isNumber; + queue.push(utils.join(utils.flatten(last), segs.shift())); + queue.push.apply(queue, segs); + }) - if (opts.isPadded) { - opts.maxLength = Math.max(String(start).length, String(stop).length); - } + /** + * Close + */ - // support legacy minimatch/fill-range options - if (typeof opts.optimize === 'boolean') opts.toRegex = opts.optimize; - if (typeof opts.makeRe === 'boolean') opts.toRegex = opts.makeRe; - return expand(start, stop, opts); -} + .set('brace.close', function(node) { + var queue = node.parent.queue; + var prev = node.parent.parent; + var last = prev.queue.pop(); + var open = node.parent.open; + var close = node.val; -function expand(start, stop, options) { - var a = options.isNumber ? toNumber(start) : start.charCodeAt(0); - var b = options.isNumber ? toNumber(stop) : stop.charCodeAt(0); + if (open && close && isOptimized(node, options)) { + open = '('; + close = ')'; + } - var step = Math.abs(toNumber(options.step)) || 1; - if (options.toRegex && step === 1) { - return toRange(a, b, start, stop, options); - } + // if a close brace exists, and the previous segment is one character + // don't wrap the result in braces or parens + var ele = utils.last(queue); + if (node.parent.count > 1 && options.expand) { + ele = multiply(queue.pop(), node.parent.count); + node.parent.count = 1; + queue.push(ele); + } - var zero = {greater: [], lesser: []}; - var asc = a < b; - var arr = new Array(Math.round((asc ? b - a : a - b) / step)); - var idx = 0; + if (close && typeof ele === 'string' && ele.length === 1) { + open = ''; + close = ''; + } - while (asc ? a <= b : a >= b) { - var val = options.isNumber ? a : String.fromCharCode(a); - if (options.toRegex && (val >= 0 || !options.isNumber)) { - zero.greater.push(val); - } else { - zero.lesser.push(Math.abs(val)); - } + if ((isLiteralBrace(node, options) || noInner(node)) && !node.parent.hasEmpty) { + queue.push(utils.join(open, queue.pop() || '')); + queue = utils.flatten(utils.join(queue, close)); + } - if (options.isPadded) { - val = zeros(val, options); - } + if (typeof last === 'undefined') { + prev.queue = [queue]; + } else { + prev.queue.push(utils.flatten(utils.join(last, queue))); + } + }) - if (options.toString) { - val = String(val); - } + /** + * eos + */ - if (typeof options.transform === 'function') { - arr[idx++] = options.transform(val, a, b, step, idx, arr, options); - } else { - arr[idx++] = val; - } + .set('eos', function(node) { + if (this.input) return; - if (asc) { - a += step; - } else { - a -= step; - } - } + if (options.optimize !== false) { + this.output = utils.last(utils.flatten(this.ast.queue)); + } else if (Array.isArray(utils.last(this.ast.queue))) { + this.output = utils.flatten(this.ast.queue.pop()); + } else { + this.output = utils.flatten(this.ast.queue); + } - if (options.toRegex === true) { - return toSequence(arr, zero, options); - } - return arr; -} + if (node.parent.count > 1 && options.expand) { + this.output = multiply(this.output, node.parent.count); + } -function toRange(a, b, start, stop, options) { - if (options.isPadded) { - return toRegex(start, stop, options); - } + this.output = utils.arrayify(this.output); + this.ast.queue = []; + }); - if (options.isNumber) { - return toRegex(Math.min(a, b), Math.max(a, b), options); - } +}; - var start = String.fromCharCode(Math.min(a, b)); - var stop = String.fromCharCode(Math.max(a, b)); - return '[' + start + '-' + stop + ']'; +/** + * Multiply the segments in the current brace level + */ + +function multiply(queue, n, options) { + return utils.flatten(utils.repeat(utils.arrayify(queue), n)); } -function toSequence(arr, zeros, options) { - var greater = '', lesser = ''; - if (zeros.greater.length) { - greater = zeros.greater.join('|'); - } - if (zeros.lesser.length) { - lesser = '-(' + zeros.lesser.join('|') + ')'; - } - var res = greater && lesser - ? greater + '|' + lesser - : greater || lesser; +/** + * Return true if `node` is escaped + */ - if (options.capture) { - return '(' + res + ')'; - } - return res; +function isEscaped(node) { + return node.escaped === true; } -function zeros(val, options) { - if (options.isPadded) { - var str = String(val); - var len = str.length; - var dash = ''; - if (str.charAt(0) === '-') { - dash = '-'; - str = str.slice(1); - } - var diff = options.maxLength - len; - var pad = repeat('0', diff); - val = (dash + pad + str); - } - if (options.stringify) { - return String(val); - } - return val; -} +/** + * Returns true if regex parens should be used for sets. If the parent `type` + * is not `brace`, then we're on a root node, which means we should never + * expand segments and open/close braces should be `{}` (since this indicates + * a brace is missing from the set) + */ -function toNumber(val) { - return Number(val) || 0; +function isOptimized(node, options) { + if (node.parent.isOptimized) return true; + return isType(node.parent, 'brace') + && !isEscaped(node.parent) + && options.expand !== true; } -function isPadded(str) { - return /^-?0\d/.test(str); -} +/** + * Returns true if the value in `node` should be wrapped in a literal brace. + * @return {Boolean} + */ -function isValid(min, max) { - return (isValidNumber(min) || isValidLetter(min)) - && (isValidNumber(max) || isValidLetter(max)); +function isLiteralBrace(node, options) { + return isEscaped(node.parent) || options.optimize !== false; } -function isValidLetter(ch) { - return typeof ch === 'string' && ch.length === 1 && /^\w+$/.test(ch); +/** + * Returns true if the given `node` does not have an inner value. + * @return {Boolean} + */ + +function noInner(node, type) { + if (node.parent.queue.length === 1) { + return true; + } + var nodes = node.parent.nodes; + return nodes.length === 3 + && isType(nodes[0], 'brace.open') + && !isType(nodes[1], 'text') + && isType(nodes[2], 'brace.close'); } -function isValidNumber(n) { - return isNumber(n) && !/\./.test(n); +/** + * Returns true if the given `node` is the given `type` + * @return {Boolean} + */ + +function isType(node, type) { + return typeof node !== 'undefined' && node.type === type; } /** - * Expose `fillRange` - * @type {Function} + * Returns true if the given `node` has a non-empty queue. + * @return {Boolean} */ -module.exports = fillRange; +function hasQueue(node) { + return Array.isArray(node.queue) && node.queue.length; +} /***/ }), -/* 548 */ +/* 552 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -/*! - * is-number - * - * Copyright (c) 2014-2015, Jon Schlinkert. - * Licensed under the MIT License. - */ - -var typeOf = __webpack_require__(549); +var splitString = __webpack_require__(553); +var utils = module.exports; -module.exports = function isNumber(num) { - var type = typeOf(num); +/** + * Module dependencies + */ - if (type === 'string') { - if (!num.trim()) return false; - } else if (type !== 'number') { - return false; - } +utils.extend = __webpack_require__(549); +utils.flatten = __webpack_require__(556); +utils.isObject = __webpack_require__(534); +utils.fillRange = __webpack_require__(557); +utils.repeat = __webpack_require__(563); +utils.unique = __webpack_require__(548); - return (num - num + 1) >= 0; +utils.define = function(obj, key, val) { + Object.defineProperty(obj, key, { + writable: true, + configurable: true, + enumerable: false, + value: val + }); }; +/** + * Returns true if the given string contains only empty brace sets. + */ -/***/ }), -/* 549 */ -/***/ (function(module, exports, __webpack_require__) { +utils.isEmptySets = function(str) { + return /^(?:\{,\})+$/.test(str); +}; -var isBuffer = __webpack_require__(529); -var toString = Object.prototype.toString; +/** + * Returns true if the given string contains only empty brace sets. + */ + +utils.isQuotedString = function(str) { + var open = str.charAt(0); + if (open === '\'' || open === '"' || open === '`') { + return str.slice(-1) === open; + } + return false; +}; /** - * Get the native `typeof` a value. - * - * @param {*} `val` - * @return {*} Native javascript type + * Create the key to use for memoization. The unique key is generated + * by iterating over the options and concatenating key-value pairs + * to the pattern string. */ -module.exports = function kindOf(val) { - // primitivies - if (typeof val === 'undefined') { - return 'undefined'; +utils.createKey = function(pattern, options) { + var id = pattern; + if (typeof options === 'undefined') { + return id; } - if (val === null) { - return 'null'; + var keys = Object.keys(options); + for (var i = 0; i < keys.length; i++) { + var key = keys[i]; + id += ';' + key + '=' + String(options[key]); } - if (val === true || val === false || val instanceof Boolean) { - return 'boolean'; + return id; +}; + +/** + * Normalize options + */ + +utils.createOptions = function(options) { + var opts = utils.extend.apply(null, arguments); + if (typeof opts.expand === 'boolean') { + opts.optimize = !opts.expand; } - if (typeof val === 'string' || val instanceof String) { - return 'string'; + if (typeof opts.optimize === 'boolean') { + opts.expand = !opts.optimize; } - if (typeof val === 'number' || val instanceof Number) { - return 'number'; + if (opts.optimize === true) { + opts.makeRe = true; } + return opts; +}; - // functions - if (typeof val === 'function' || val instanceof Function) { - return 'function'; - } +/** + * Join patterns in `a` to patterns in `b` + */ - // array - if (typeof Array.isArray !== 'undefined' && Array.isArray(val)) { - return 'array'; - } +utils.join = function(a, b, options) { + options = options || {}; + a = utils.arrayify(a); + b = utils.arrayify(b); - // check for instances of RegExp and Date before calling `toString` - if (val instanceof RegExp) { - return 'regexp'; - } - if (val instanceof Date) { - return 'date'; - } + if (!a.length) return b; + if (!b.length) return a; - // other objects - var type = toString.call(val); + var len = a.length; + var idx = -1; + var arr = []; - if (type === '[object RegExp]') { - return 'regexp'; - } - if (type === '[object Date]') { - return 'date'; - } - if (type === '[object Arguments]') { - return 'arguments'; - } - if (type === '[object Error]') { - return 'error'; - } + while (++idx < len) { + var val = a[idx]; + if (Array.isArray(val)) { + for (var i = 0; i < val.length; i++) { + val[i] = utils.join(val[i], b, options); + } + arr.push(val); + continue; + } - // buffer - if (isBuffer(val)) { - return 'buffer'; - } + for (var j = 0; j < b.length; j++) { + var bval = b[j]; - // es6: Map, WeakMap, Set, WeakSet - if (type === '[object Set]') { - return 'set'; - } - if (type === '[object WeakSet]') { - return 'weakset'; - } - if (type === '[object Map]') { - return 'map'; - } - if (type === '[object WeakMap]') { - return 'weakmap'; - } - if (type === '[object Symbol]') { - return 'symbol'; + if (Array.isArray(bval)) { + arr.push(utils.join(val, bval, options)); + } else { + arr.push(val + bval); + } + } } + return arr; +}; - // typed arrays - if (type === '[object Int8Array]') { - return 'int8array'; - } - if (type === '[object Uint8Array]') { - return 'uint8array'; - } - if (type === '[object Uint8ClampedArray]') { - return 'uint8clampedarray'; - } - if (type === '[object Int16Array]') { - return 'int16array'; - } - if (type === '[object Uint16Array]') { - return 'uint16array'; - } - if (type === '[object Int32Array]') { - return 'int32array'; +/** + * Split the given string on `,` if not escaped. + */ + +utils.split = function(str, options) { + var opts = utils.extend({sep: ','}, options); + if (typeof opts.keepQuotes !== 'boolean') { + opts.keepQuotes = true; } - if (type === '[object Uint32Array]') { - return 'uint32array'; + if (opts.unescape === false) { + opts.keepEscaping = true; } - if (type === '[object Float32Array]') { - return 'float32array'; + return splitString(str, opts, utils.escapeBrackets(opts)); +}; + +/** + * Expand ranges or sets in the given `pattern`. + * + * @param {String} `str` + * @param {Object} `options` + * @return {Object} + */ + +utils.expand = function(str, options) { + var opts = utils.extend({rangeLimit: 10000}, options); + var segs = utils.split(str, opts); + var tok = { segs: segs }; + + if (utils.isQuotedString(str)) { + return tok; } - if (type === '[object Float64Array]') { - return 'float64array'; + + if (opts.rangeLimit === true) { + opts.rangeLimit = 10000; } - // must be a plain object - return 'object'; -}; + if (segs.length > 1) { + if (opts.optimize === false) { + tok.val = segs[0]; + return tok; + } + tok.segs = utils.stringifyArray(tok.segs); + } else if (segs.length === 1) { + var arr = str.split('..'); -/***/ }), -/* 550 */ -/***/ (function(module, exports, __webpack_require__) { + if (arr.length === 1) { + tok.val = tok.segs[tok.segs.length - 1] || tok.val || str; + tok.segs = []; + return tok; + } -"use strict"; + if (arr.length === 2 && arr[0] === arr[1]) { + tok.escaped = true; + tok.val = arr[0]; + tok.segs = []; + return tok; + } + if (arr.length > 1) { + if (opts.optimize !== false) { + opts.optimize = true; + delete opts.expand; + } -var isObject = __webpack_require__(551); + if (opts.optimize !== true) { + var min = Math.min(arr[0], arr[1]); + var max = Math.max(arr[0], arr[1]); + var step = arr[2] || 1; -module.exports = function extend(o/*, objects*/) { - if (!isObject(o)) { o = {}; } + if (opts.rangeLimit !== false && ((max - min) / step >= opts.rangeLimit)) { + throw new RangeError('expanded array length exceeds range limit. Use options.rangeLimit to increase or disable the limit.'); + } + } - var len = arguments.length; - for (var i = 1; i < len; i++) { - var obj = arguments[i]; + arr.push(opts); + tok.segs = utils.fillRange.apply(null, arr); - if (isObject(obj)) { - assign(o, obj); - } - } - return o; -}; + if (!tok.segs.length) { + tok.escaped = true; + tok.val = str; + return tok; + } -function assign(a, b) { - for (var key in b) { - if (hasOwn(b, key)) { - a[key] = b[key]; + if (opts.optimize === true) { + tok.segs = utils.stringifyArray(tok.segs); + } + + if (tok.segs === '') { + tok.val = str; + } else { + tok.val = tok.segs[0]; + } + return tok; } + } else { + tok.val = str; } -} + return tok; +}; /** - * Returns true if the given `key` is an own property of `obj`. + * Ensure commas inside brackets and parens are not split. + * @param {Object} `tok` Token from the `split-string` module + * @return {undefined} */ -function hasOwn(obj, key) { - return Object.prototype.hasOwnProperty.call(obj, key); -} - - -/***/ }), -/* 551 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; -/*! - * is-extendable - * - * Copyright (c) 2015, Jon Schlinkert. - * Licensed under the MIT License. - */ +utils.escapeBrackets = function(options) { + return function(tok) { + if (tok.escaped && tok.val === 'b') { + tok.val = '\\b'; + return; + } + if (tok.val !== '(' && tok.val !== '[') return; + var opts = utils.extend({}, options); + var brackets = []; + var parens = []; + var stack = []; + var val = tok.val; + var str = tok.str; + var i = tok.idx - 1; + while (++i < str.length) { + var ch = str[i]; -module.exports = function isExtendable(val) { - return typeof val !== 'undefined' && val !== null - && (typeof val === 'object' || typeof val === 'function'); -}; + if (ch === '\\') { + val += (opts.keepEscaping === false ? '' : ch) + str[++i]; + continue; + } + if (ch === '(') { + parens.push(ch); + stack.push(ch); + } -/***/ }), -/* 552 */ -/***/ (function(module, exports, __webpack_require__) { + if (ch === '[') { + brackets.push(ch); + stack.push(ch); + } -"use strict"; -/*! - * repeat-string - * - * Copyright (c) 2014-2015, Jon Schlinkert. - * Licensed under the MIT License. - */ + if (ch === ')') { + parens.pop(); + stack.pop(); + if (!stack.length) { + val += ch; + break; + } + } + if (ch === ']') { + brackets.pop(); + stack.pop(); + if (!stack.length) { + val += ch; + break; + } + } + val += ch; + } + tok.split = false; + tok.val = val.slice(1); + tok.idx = i; + }; +}; /** - * Results cache + * Returns true if the given string looks like a regex quantifier + * @return {Boolean} */ -var res = ''; -var cache; +utils.isQuantifier = function(str) { + return /^(?:[0-9]?,[0-9]|[0-9],)$/.test(str); +}; /** - * Expose `repeat` + * Cast `val` to an array. + * @param {*} `val` */ -module.exports = repeat; +utils.stringifyArray = function(arr) { + return [utils.arrayify(arr).join('|')]; +}; /** - * Repeat the given `string` the specified `number` - * of times. - * - * **Example:** - * - * ```js - * var repeat = require('repeat-string'); - * repeat('A', 5); - * //=> AAAAA - * ``` - * - * @param {String} `string` The string to repeat - * @param {Number} `number` The number of times to repeat the string - * @return {String} Repeated string - * @api public + * Cast `val` to an array. + * @param {*} `val` */ -function repeat(str, num) { - if (typeof str !== 'string') { - throw new TypeError('expected a string'); +utils.arrayify = function(arr) { + if (typeof arr === 'undefined') { + return []; + } + if (typeof arr === 'string') { + return [arr]; } + return arr; +}; - // cover common, quick use cases - if (num === 1) return str; - if (num === 2) return str + str; +/** + * Returns true if the given `str` is a non-empty string + * @return {Boolean} + */ - var max = str.length * num; - if (cache !== str || typeof cache === 'undefined') { - cache = str; - res = ''; - } else if (res.length >= max) { - return res.substr(0, max); - } +utils.isString = function(str) { + return str != null && typeof str === 'string'; +}; - while (max > res.length && num > 1) { - if (num & 1) { - res += str; - } +/** + * Get the last element from `array` + * @param {Array} `array` + * @return {*} + */ - num >>= 1; - str += str; - } +utils.last = function(arr, n) { + return arr[arr.length - (n || 1)]; +}; - res += str; - res = res.substr(0, max); - return res; -} +utils.escapeRegex = function(str) { + return str.replace(/\\?([!^*?()[\]{}+?/])/g, '\\$1'); +}; /***/ }), @@ -62826,1880 +62998,2079 @@ function repeat(str, num) { "use strict"; /*! - * to-regex-range + * split-string * - * Copyright (c) 2015, 2017, Jon Schlinkert. + * Copyright (c) 2015-2017, Jon Schlinkert. * Released under the MIT License. */ -var repeat = __webpack_require__(552); -var isNumber = __webpack_require__(548); -var cache = {}; +var extend = __webpack_require__(554); -function toRegexRange(min, max, options) { - if (isNumber(min) === false) { - throw new RangeError('toRegexRange: first argument is invalid.'); +module.exports = function(str, options, fn) { + if (typeof str !== 'string') { + throw new TypeError('expected a string'); } - if (typeof max === 'undefined' || min === max) { - return String(min); + if (typeof options === 'function') { + fn = options; + options = null; } - if (isNumber(max) === false) { - throw new RangeError('toRegexRange: second argument is invalid.'); + // allow separator to be defined as a string + if (typeof options === 'string') { + options = { sep: options }; } - options = options || {}; - var relax = String(options.relaxZeros); - var shorthand = String(options.shorthand); - var capture = String(options.capture); - var key = min + ':' + max + '=' + relax + shorthand + capture; - if (cache.hasOwnProperty(key)) { - return cache[key].result; + var opts = extend({sep: '.'}, options); + var quotes = opts.quotes || ['"', "'", '`']; + var brackets; + + if (opts.brackets === true) { + brackets = { + '<': '>', + '(': ')', + '[': ']', + '{': '}' + }; + } else if (opts.brackets) { + brackets = opts.brackets; } - var a = Math.min(min, max); - var b = Math.max(min, max); + var tokens = []; + var stack = []; + var arr = ['']; + var sep = opts.sep; + var len = str.length; + var idx = -1; + var closeIdx; - if (Math.abs(a - b) === 1) { - var result = min + '|' + max; - if (options.capture) { - return '(' + result + ')'; + function expected() { + if (brackets && stack.length) { + return brackets[stack[stack.length - 1]]; } - return result; } - var isPadded = padding(min) || padding(max); - var positives = []; - var negatives = []; - - var tok = {min: min, max: max, a: a, b: b}; - if (isPadded) { - tok.isPadded = isPadded; - tok.maxLen = String(tok.max).length; - } + while (++idx < len) { + var ch = str[idx]; + var next = str[idx + 1]; + var tok = { val: ch, idx: idx, arr: arr, str: str }; + tokens.push(tok); - if (a < 0) { - var newMin = b < 0 ? Math.abs(b) : 1; - var newMax = Math.abs(a); - negatives = splitToPatterns(newMin, newMax, tok, options); - a = tok.a = 0; - } + if (ch === '\\') { + tok.val = keepEscaping(opts, str, idx) === true ? (ch + next) : next; + tok.escaped = true; + if (typeof fn === 'function') { + fn(tok); + } + arr[arr.length - 1] += tok.val; + idx++; + continue; + } - if (b >= 0) { - positives = splitToPatterns(a, b, tok, options); - } + if (brackets && brackets[ch]) { + stack.push(ch); + var e = expected(); + var i = idx + 1; - tok.negatives = negatives; - tok.positives = positives; - tok.result = siftPatterns(negatives, positives, options); + if (str.indexOf(e, i + 1) !== -1) { + while (stack.length && i < len) { + var s = str[++i]; + if (s === '\\') { + s++; + continue; + } - if (options.capture && (positives.length + negatives.length) > 1) { - tok.result = '(' + tok.result + ')'; - } + if (quotes.indexOf(s) !== -1) { + i = getClosingQuote(str, s, i + 1); + continue; + } - cache[key] = tok; - return tok.result; -} + e = expected(); + if (stack.length && str.indexOf(e, i + 1) === -1) { + break; + } -function siftPatterns(neg, pos, options) { - var onlyNegative = filterPatterns(neg, pos, '-', false, options) || []; - var onlyPositive = filterPatterns(pos, neg, '', false, options) || []; - var intersected = filterPatterns(neg, pos, '-?', true, options) || []; - var subpatterns = onlyNegative.concat(intersected).concat(onlyPositive); - return subpatterns.join('|'); -} + if (brackets[s]) { + stack.push(s); + continue; + } -function splitToRanges(min, max) { - min = Number(min); - max = Number(max); + if (e === s) { + stack.pop(); + } + } + } - var nines = 1; - var stops = [max]; - var stop = +countNines(min, nines); + closeIdx = i; + if (closeIdx === -1) { + arr[arr.length - 1] += ch; + continue; + } - while (min <= stop && stop <= max) { - stops = push(stops, stop); - nines += 1; - stop = +countNines(min, nines); - } + ch = str.slice(idx, closeIdx + 1); + tok.val = ch; + tok.idx = idx = closeIdx; + } - var zeros = 1; - stop = countZeros(max + 1, zeros) - 1; + if (quotes.indexOf(ch) !== -1) { + closeIdx = getClosingQuote(str, ch, idx + 1); + if (closeIdx === -1) { + arr[arr.length - 1] += ch; + continue; + } - while (min < stop && stop <= max) { - stops = push(stops, stop); - zeros += 1; - stop = countZeros(max + 1, zeros) - 1; + if (keepQuotes(ch, opts) === true) { + ch = str.slice(idx, closeIdx + 1); + } else { + ch = str.slice(idx + 1, closeIdx); + } + + tok.val = ch; + tok.idx = idx = closeIdx; + } + + if (typeof fn === 'function') { + fn(tok, tokens); + ch = tok.val; + idx = tok.idx; + } + + if (tok.val === sep && tok.split !== false) { + arr.push(''); + continue; + } + + arr[arr.length - 1] += tok.val; } - stops.sort(compare); - return stops; + return arr; +}; + +function getClosingQuote(str, ch, i, brackets) { + var idx = str.indexOf(ch, i); + if (str.charAt(idx - 1) === '\\') { + return getClosingQuote(str, ch, idx + 1); + } + return idx; } -/** - * Convert a range to a regex pattern - * @param {Number} `start` - * @param {Number} `stop` - * @return {String} - */ +function keepQuotes(ch, opts) { + if (opts.keepDoubleQuotes === true && ch === '"') return true; + if (opts.keepSingleQuotes === true && ch === "'") return true; + return opts.keepQuotes; +} -function rangeToPattern(start, stop, options) { - if (start === stop) { - return {pattern: String(start), digits: []}; +function keepEscaping(opts, str, idx) { + if (typeof opts.keepEscaping === 'function') { + return opts.keepEscaping(str, idx); } + return opts.keepEscaping === true || str[idx + 1] === '\\'; +} - var zipped = zip(String(start), String(stop)); - var len = zipped.length, i = -1; - var pattern = ''; - var digits = 0; +/***/ }), +/* 554 */ +/***/ (function(module, exports, __webpack_require__) { - while (++i < len) { - var numbers = zipped[i]; - var startDigit = numbers[0]; - var stopDigit = numbers[1]; +"use strict"; - if (startDigit === stopDigit) { - pattern += startDigit; - } else if (startDigit !== '0' || stopDigit !== '9') { - pattern += toCharacterClass(startDigit, stopDigit); +var isExtendable = __webpack_require__(555); +var assignSymbols = __webpack_require__(544); - } else { - digits += 1; +module.exports = Object.assign || function(obj/*, objects*/) { + if (obj === null || typeof obj === 'undefined') { + throw new TypeError('Cannot convert undefined or null to object'); + } + if (!isObject(obj)) { + obj = {}; + } + for (var i = 1; i < arguments.length; i++) { + var val = arguments[i]; + if (isString(val)) { + val = toObject(val); + } + if (isObject(val)) { + assign(obj, val); + assignSymbols(obj, val); } } + return obj; +}; - if (digits) { - pattern += options.shorthand ? '\\d' : '[0-9]'; +function assign(a, b) { + for (var key in b) { + if (hasOwn(b, key)) { + a[key] = b[key]; + } } +} - return { pattern: pattern, digits: [digits] }; +function isString(val) { + return (val && typeof val === 'string'); } -function splitToPatterns(min, max, tok, options) { - var ranges = splitToRanges(min, max); - var len = ranges.length; - var idx = -1; +function toObject(str) { + var obj = {}; + for (var i in str) { + obj[i] = str[i]; + } + return obj; +} - var tokens = []; - var start = min; - var prev; +function isObject(val) { + return (val && typeof val === 'object') || isExtendable(val); +} - while (++idx < len) { - var range = ranges[idx]; - var obj = rangeToPattern(start, range, options); - var zeros = ''; +/** + * Returns true if the given `key` is an own property of `obj`. + */ - if (!tok.isPadded && prev && prev.pattern === obj.pattern) { - if (prev.digits.length > 1) { - prev.digits.pop(); - } - prev.digits.push(obj.digits[0]); - prev.string = prev.pattern + toQuantifier(prev.digits); - start = range + 1; - continue; +function hasOwn(obj, key) { + return Object.prototype.hasOwnProperty.call(obj, key); +} + +function isEnum(obj, key) { + return Object.prototype.propertyIsEnumerable.call(obj, key); +} + + +/***/ }), +/* 555 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +/*! + * is-extendable + * + * Copyright (c) 2015-2017, Jon Schlinkert. + * Released under the MIT License. + */ + + + +var isPlainObject = __webpack_require__(543); + +module.exports = function isExtendable(val) { + return isPlainObject(val) || typeof val === 'function' || Array.isArray(val); +}; + + +/***/ }), +/* 556 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +/*! + * arr-flatten + * + * Copyright (c) 2014-2017, Jon Schlinkert. + * Released under the MIT License. + */ + + + +module.exports = function (arr) { + return flat(arr, []); +}; + +function flat(arr, res) { + var i = 0, cur; + var len = arr.length; + for (; i < len; i++) { + cur = arr[i]; + Array.isArray(cur) ? flat(cur, res) : res.push(cur); + } + return res; +} + + +/***/ }), +/* 557 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +/*! + * fill-range + * + * Copyright (c) 2014-2015, 2017, Jon Schlinkert. + * Released under the MIT License. + */ + + + +var util = __webpack_require__(112); +var isNumber = __webpack_require__(558); +var extend = __webpack_require__(549); +var repeat = __webpack_require__(561); +var toRegex = __webpack_require__(562); + +/** + * Return a range of numbers or letters. + * + * @param {String} `start` Start of the range + * @param {String} `stop` End of the range + * @param {String} `step` Increment or decrement to use. + * @param {Function} `fn` Custom function to modify each element in the range. + * @return {Array} + */ + +function fillRange(start, stop, step, options) { + if (typeof start === 'undefined') { + return []; + } + + if (typeof stop === 'undefined' || start === stop) { + // special case, for handling negative zero + var isString = typeof start === 'string'; + if (isNumber(start) && !toNumber(start)) { + return [isString ? '0' : 0]; } + return [start]; + } - if (tok.isPadded) { - zeros = padZeros(range, tok); + if (typeof step !== 'number' && typeof step !== 'string') { + options = step; + step = undefined; + } + + if (typeof options === 'function') { + options = { transform: options }; + } + + var opts = extend({step: step}, options); + if (opts.step && !isValidNumber(opts.step)) { + if (opts.strictRanges === true) { + throw new TypeError('expected options.step to be a number'); } + return []; + } - obj.string = zeros + obj.pattern + toQuantifier(obj.digits); - tokens.push(obj); - start = range + 1; - prev = obj; + opts.isNumber = isValidNumber(start) && isValidNumber(stop); + if (!opts.isNumber && !isValid(start, stop)) { + if (opts.strictRanges === true) { + throw new RangeError('invalid range arguments: ' + util.inspect([start, stop])); + } + return []; } - return tokens; + opts.isPadded = isPadded(start) || isPadded(stop); + opts.toString = opts.stringify + || typeof opts.step === 'string' + || typeof start === 'string' + || typeof stop === 'string' + || !opts.isNumber; + + if (opts.isPadded) { + opts.maxLength = Math.max(String(start).length, String(stop).length); + } + + // support legacy minimatch/fill-range options + if (typeof opts.optimize === 'boolean') opts.toRegex = opts.optimize; + if (typeof opts.makeRe === 'boolean') opts.toRegex = opts.makeRe; + return expand(start, stop, opts); } -function filterPatterns(arr, comparison, prefix, intersection, options) { - var res = []; +function expand(start, stop, options) { + var a = options.isNumber ? toNumber(start) : start.charCodeAt(0); + var b = options.isNumber ? toNumber(stop) : stop.charCodeAt(0); - for (var i = 0; i < arr.length; i++) { - var tok = arr[i]; - var ele = tok.string; + var step = Math.abs(toNumber(options.step)) || 1; + if (options.toRegex && step === 1) { + return toRange(a, b, start, stop, options); + } - if (options.relaxZeros !== false) { - if (prefix === '-' && ele.charAt(0) === '0') { - if (ele.charAt(1) === '{') { - ele = '0*' + ele.replace(/^0\{\d+\}/, ''); - } else { - ele = '0*' + ele.slice(1); - } - } + var zero = {greater: [], lesser: []}; + var asc = a < b; + var arr = new Array(Math.round((asc ? b - a : a - b) / step)); + var idx = 0; + + while (asc ? a <= b : a >= b) { + var val = options.isNumber ? a : String.fromCharCode(a); + if (options.toRegex && (val >= 0 || !options.isNumber)) { + zero.greater.push(val); + } else { + zero.lesser.push(Math.abs(val)); } - if (!intersection && !contains(comparison, 'string', ele)) { - res.push(prefix + ele); + if (options.isPadded) { + val = zeros(val, options); } - if (intersection && contains(comparison, 'string', ele)) { - res.push(prefix + ele); + if (options.toString) { + val = String(val); } - } - return res; -} -/** - * Zip strings (`for in` can be used on string characters) - */ + if (typeof options.transform === 'function') { + arr[idx++] = options.transform(val, a, b, step, idx, arr, options); + } else { + arr[idx++] = val; + } -function zip(a, b) { - var arr = []; - for (var ch in a) arr.push([a[ch], b[ch]]); + if (asc) { + a += step; + } else { + a -= step; + } + } + + if (options.toRegex === true) { + return toSequence(arr, zero, options); + } return arr; } -function compare(a, b) { - return a > b ? 1 : b > a ? -1 : 0; -} +function toRange(a, b, start, stop, options) { + if (options.isPadded) { + return toRegex(start, stop, options); + } -function push(arr, ele) { - if (arr.indexOf(ele) === -1) arr.push(ele); - return arr; + if (options.isNumber) { + return toRegex(Math.min(a, b), Math.max(a, b), options); + } + + var start = String.fromCharCode(Math.min(a, b)); + var stop = String.fromCharCode(Math.max(a, b)); + return '[' + start + '-' + stop + ']'; } -function contains(arr, key, val) { - for (var i = 0; i < arr.length; i++) { - if (arr[i][key] === val) { - return true; - } +function toSequence(arr, zeros, options) { + var greater = '', lesser = ''; + if (zeros.greater.length) { + greater = zeros.greater.join('|'); } - return false; + if (zeros.lesser.length) { + lesser = '-(' + zeros.lesser.join('|') + ')'; + } + var res = greater && lesser + ? greater + '|' + lesser + : greater || lesser; + + if (options.capture) { + return '(' + res + ')'; + } + return res; } -function countNines(min, len) { - return String(min).slice(0, -len) + repeat('9', len); +function zeros(val, options) { + if (options.isPadded) { + var str = String(val); + var len = str.length; + var dash = ''; + if (str.charAt(0) === '-') { + dash = '-'; + str = str.slice(1); + } + var diff = options.maxLength - len; + var pad = repeat('0', diff); + val = (dash + pad + str); + } + if (options.stringify) { + return String(val); + } + return val; } -function countZeros(integer, zeros) { - return integer - (integer % Math.pow(10, zeros)); +function toNumber(val) { + return Number(val) || 0; } -function toQuantifier(digits) { - var start = digits[0]; - var stop = digits[1] ? (',' + digits[1]) : ''; - if (!stop && (!start || start === 1)) { - return ''; - } - return '{' + start + stop + '}'; +function isPadded(str) { + return /^-?0\d/.test(str); } -function toCharacterClass(a, b) { - return '[' + a + ((b - a === 1) ? '' : '-') + b + ']'; +function isValid(min, max) { + return (isValidNumber(min) || isValidLetter(min)) + && (isValidNumber(max) || isValidLetter(max)); } -function padding(str) { - return /^-?(0+)\d/.exec(str); +function isValidLetter(ch) { + return typeof ch === 'string' && ch.length === 1 && /^\w+$/.test(ch); } -function padZeros(val, tok) { - if (tok.isPadded) { - var diff = Math.abs(tok.maxLen - String(val).length); - switch (diff) { - case 0: - return ''; - case 1: - return '0'; - default: { - return '0{' + diff + '}'; - } - } - } - return val; +function isValidNumber(n) { + return isNumber(n) && !/\./.test(n); } /** - * Expose `toRegexRange` + * Expose `fillRange` + * @type {Function} */ -module.exports = toRegexRange; +module.exports = fillRange; /***/ }), -/* 554 */ +/* 558 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; /*! - * repeat-element + * is-number * - * Copyright (c) 2015 Jon Schlinkert. - * Licensed under the MIT license. + * Copyright (c) 2014-2015, Jon Schlinkert. + * Licensed under the MIT License. */ -module.exports = function repeat(ele, num) { - var arr = new Array(num); +var typeOf = __webpack_require__(559); - for (var i = 0; i < num; i++) { - arr[i] = ele; +module.exports = function isNumber(num) { + var type = typeOf(num); + + if (type === 'string') { + if (!num.trim()) return false; + } else if (type !== 'number') { + return false; } - return arr; + return (num - num + 1) >= 0; }; /***/ }), -/* 555 */ +/* 559 */ /***/ (function(module, exports, __webpack_require__) { -"use strict"; - - -var Node = __webpack_require__(556); -var utils = __webpack_require__(539); +var isBuffer = __webpack_require__(560); +var toString = Object.prototype.toString; /** - * Braces parsers + * Get the native `typeof` a value. + * + * @param {*} `val` + * @return {*} Native javascript type */ -module.exports = function(braces, options) { - braces.parser - .set('bos', function() { - if (!this.parsed) { - this.ast = this.nodes[0] = new Node(this.ast); - } - }) - - /** - * Character parsers - */ - - .set('escape', function() { - var pos = this.position(); - var m = this.match(/^(?:\\(.)|\$\{)/); - if (!m) return; - - var prev = this.prev(); - var last = utils.last(prev.nodes); +module.exports = function kindOf(val) { + // primitivies + if (typeof val === 'undefined') { + return 'undefined'; + } + if (val === null) { + return 'null'; + } + if (val === true || val === false || val instanceof Boolean) { + return 'boolean'; + } + if (typeof val === 'string' || val instanceof String) { + return 'string'; + } + if (typeof val === 'number' || val instanceof Number) { + return 'number'; + } - var node = pos(new Node({ - type: 'text', - multiplier: 1, - val: m[0] - })); + // functions + if (typeof val === 'function' || val instanceof Function) { + return 'function'; + } - if (node.val === '\\\\') { - return node; - } + // array + if (typeof Array.isArray !== 'undefined' && Array.isArray(val)) { + return 'array'; + } - if (node.val === '${') { - var str = this.input; - var idx = -1; - var ch; + // check for instances of RegExp and Date before calling `toString` + if (val instanceof RegExp) { + return 'regexp'; + } + if (val instanceof Date) { + return 'date'; + } - while ((ch = str[++idx])) { - this.consume(1); - node.val += ch; - if (ch === '\\') { - node.val += str[++idx]; - continue; - } - if (ch === '}') { - break; - } - } - } + // other objects + var type = toString.call(val); - if (this.options.unescape !== false) { - node.val = node.val.replace(/\\([{}])/g, '$1'); - } + if (type === '[object RegExp]') { + return 'regexp'; + } + if (type === '[object Date]') { + return 'date'; + } + if (type === '[object Arguments]') { + return 'arguments'; + } + if (type === '[object Error]') { + return 'error'; + } - if (last.val === '"' && this.input.charAt(0) === '"') { - last.val = node.val; - this.consume(1); - return; - } + // buffer + if (isBuffer(val)) { + return 'buffer'; + } - return concatNodes.call(this, pos, node, prev, options); - }) + // es6: Map, WeakMap, Set, WeakSet + if (type === '[object Set]') { + return 'set'; + } + if (type === '[object WeakSet]') { + return 'weakset'; + } + if (type === '[object Map]') { + return 'map'; + } + if (type === '[object WeakMap]') { + return 'weakmap'; + } + if (type === '[object Symbol]') { + return 'symbol'; + } - /** - * Brackets: "[...]" (basic, this is overridden by - * other parsers in more advanced implementations) - */ + // typed arrays + if (type === '[object Int8Array]') { + return 'int8array'; + } + if (type === '[object Uint8Array]') { + return 'uint8array'; + } + if (type === '[object Uint8ClampedArray]') { + return 'uint8clampedarray'; + } + if (type === '[object Int16Array]') { + return 'int16array'; + } + if (type === '[object Uint16Array]') { + return 'uint16array'; + } + if (type === '[object Int32Array]') { + return 'int32array'; + } + if (type === '[object Uint32Array]') { + return 'uint32array'; + } + if (type === '[object Float32Array]') { + return 'float32array'; + } + if (type === '[object Float64Array]') { + return 'float64array'; + } - .set('bracket', function() { - var isInside = this.isInside('brace'); - var pos = this.position(); - var m = this.match(/^(?:\[([!^]?)([^\]]{2,}|\]-)(\]|[^*+?]+)|\[)/); - if (!m) return; + // must be a plain object + return 'object'; +}; - var prev = this.prev(); - var val = m[0]; - var negated = m[1] ? '^' : ''; - var inner = m[2] || ''; - var close = m[3] || ''; - if (isInside && prev.type === 'brace') { - prev.text = prev.text || ''; - prev.text += val; - } +/***/ }), +/* 560 */ +/***/ (function(module, exports) { - var esc = this.input.slice(0, 2); - if (inner === '' && esc === '\\]') { - inner += esc; - this.consume(2); +/*! + * Determine if an object is a Buffer + * + * @author Feross Aboukhadijeh + * @license MIT + */ - var str = this.input; - var idx = -1; - var ch; +// The _isBuffer check is for Safari 5-7 support, because it's missing +// Object.prototype.constructor. Remove this eventually +module.exports = function (obj) { + return obj != null && (isBuffer(obj) || isSlowBuffer(obj) || !!obj._isBuffer) +} - while ((ch = str[++idx])) { - this.consume(1); - if (ch === ']') { - close = ch; - break; - } - inner += ch; - } - } +function isBuffer (obj) { + return !!obj.constructor && typeof obj.constructor.isBuffer === 'function' && obj.constructor.isBuffer(obj) +} - return pos(new Node({ - type: 'bracket', - val: val, - escaped: close !== ']', - negated: negated, - inner: inner, - close: close - })); - }) +// For Node v0.10 support. Remove this eventually. +function isSlowBuffer (obj) { + return typeof obj.readFloatLE === 'function' && typeof obj.slice === 'function' && isBuffer(obj.slice(0, 0)) +} - /** - * Empty braces (we capture these early to - * speed up processing in the compiler) - */ - .set('multiplier', function() { - var isInside = this.isInside('brace'); - var pos = this.position(); - var m = this.match(/^\{((?:,|\{,+\})+)\}/); - if (!m) return; +/***/ }), +/* 561 */ +/***/ (function(module, exports, __webpack_require__) { - this.multiplier = true; - var prev = this.prev(); - var val = m[0]; +"use strict"; +/*! + * repeat-string + * + * Copyright (c) 2014-2015, Jon Schlinkert. + * Licensed under the MIT License. + */ - if (isInside && prev.type === 'brace') { - prev.text = prev.text || ''; - prev.text += val; - } - var node = pos(new Node({ - type: 'text', - multiplier: 1, - match: m, - val: val - })); - return concatNodes.call(this, pos, node, prev, options); - }) +/** + * Results cache + */ - /** - * Open - */ +var res = ''; +var cache; - .set('brace.open', function() { - var pos = this.position(); - var m = this.match(/^\{(?!(?:[^\\}]?|,+)\})/); - if (!m) return; +/** + * Expose `repeat` + */ - var prev = this.prev(); - var last = utils.last(prev.nodes); +module.exports = repeat; - // if the last parsed character was an extglob character - // we need to _not optimize_ the brace pattern because - // it might be mistaken for an extglob by a downstream parser - if (last && last.val && isExtglobChar(last.val.slice(-1))) { - last.optimize = false; - } +/** + * Repeat the given `string` the specified `number` + * of times. + * + * **Example:** + * + * ```js + * var repeat = require('repeat-string'); + * repeat('A', 5); + * //=> AAAAA + * ``` + * + * @param {String} `string` The string to repeat + * @param {Number} `number` The number of times to repeat the string + * @return {String} Repeated string + * @api public + */ - var open = pos(new Node({ - type: 'brace.open', - val: m[0] - })); +function repeat(str, num) { + if (typeof str !== 'string') { + throw new TypeError('expected a string'); + } - var node = pos(new Node({ - type: 'brace', - nodes: [] - })); + // cover common, quick use cases + if (num === 1) return str; + if (num === 2) return str + str; - node.push(open); - prev.push(node); - this.push('brace', node); - }) + var max = str.length * num; + if (cache !== str || typeof cache === 'undefined') { + cache = str; + res = ''; + } else if (res.length >= max) { + return res.substr(0, max); + } - /** - * Close - */ + while (max > res.length && num > 1) { + if (num & 1) { + res += str; + } - .set('brace.close', function() { - var pos = this.position(); - var m = this.match(/^\}/); - if (!m || !m[0]) return; + num >>= 1; + str += str; + } - var brace = this.pop('brace'); - var node = pos(new Node({ - type: 'brace.close', - val: m[0] - })); + res += str; + res = res.substr(0, max); + return res; +} - if (!this.isType(brace, 'brace')) { - if (this.options.strict) { - throw new Error('missing opening "{"'); - } - node.type = 'text'; - node.multiplier = 0; - node.escaped = true; - return node; - } - var prev = this.prev(); - var last = utils.last(prev.nodes); - if (last.text) { - var lastNode = utils.last(last.nodes); - if (lastNode.val === ')' && /[!@*?+]\(/.test(last.text)) { - var open = last.nodes[0]; - var text = last.nodes[1]; - if (open.type === 'brace.open' && text && text.type === 'text') { - text.optimize = false; - } - } - } +/***/ }), +/* 562 */ +/***/ (function(module, exports, __webpack_require__) { - if (brace.nodes.length > 2) { - var first = brace.nodes[1]; - if (first.type === 'text' && first.val === ',') { - brace.nodes.splice(1, 1); - brace.nodes.push(first); - } - } +"use strict"; +/*! + * to-regex-range + * + * Copyright (c) 2015, 2017, Jon Schlinkert. + * Released under the MIT License. + */ - brace.push(node); - }) - /** - * Capture boundary characters - */ - .set('boundary', function() { - var pos = this.position(); - var m = this.match(/^[$^](?!\{)/); - if (!m) return; - return pos(new Node({ - type: 'text', - val: m[0] - })); - }) +var repeat = __webpack_require__(561); +var isNumber = __webpack_require__(558); +var cache = {}; - /** - * One or zero, non-comma characters wrapped in braces - */ +function toRegexRange(min, max, options) { + if (isNumber(min) === false) { + throw new RangeError('toRegexRange: first argument is invalid.'); + } - .set('nobrace', function() { - var isInside = this.isInside('brace'); - var pos = this.position(); - var m = this.match(/^\{[^,]?\}/); - if (!m) return; + if (typeof max === 'undefined' || min === max) { + return String(min); + } - var prev = this.prev(); - var val = m[0]; + if (isNumber(max) === false) { + throw new RangeError('toRegexRange: second argument is invalid.'); + } - if (isInside && prev.type === 'brace') { - prev.text = prev.text || ''; - prev.text += val; - } + options = options || {}; + var relax = String(options.relaxZeros); + var shorthand = String(options.shorthand); + var capture = String(options.capture); + var key = min + ':' + max + '=' + relax + shorthand + capture; + if (cache.hasOwnProperty(key)) { + return cache[key].result; + } - return pos(new Node({ - type: 'text', - multiplier: 0, - val: val - })); - }) + var a = Math.min(min, max); + var b = Math.max(min, max); - /** - * Text - */ + if (Math.abs(a - b) === 1) { + var result = min + '|' + max; + if (options.capture) { + return '(' + result + ')'; + } + return result; + } - .set('text', function() { - var isInside = this.isInside('brace'); - var pos = this.position(); - var m = this.match(/^((?!\\)[^${}[\]])+/); - if (!m) return; + var isPadded = padding(min) || padding(max); + var positives = []; + var negatives = []; - var prev = this.prev(); - var val = m[0]; + var tok = {min: min, max: max, a: a, b: b}; + if (isPadded) { + tok.isPadded = isPadded; + tok.maxLen = String(tok.max).length; + } - if (isInside && prev.type === 'brace') { - prev.text = prev.text || ''; - prev.text += val; - } + if (a < 0) { + var newMin = b < 0 ? Math.abs(b) : 1; + var newMax = Math.abs(a); + negatives = splitToPatterns(newMin, newMax, tok, options); + a = tok.a = 0; + } - var node = pos(new Node({ - type: 'text', - multiplier: 1, - val: val - })); + if (b >= 0) { + positives = splitToPatterns(a, b, tok, options); + } - return concatNodes.call(this, pos, node, prev, options); - }); -}; + tok.negatives = negatives; + tok.positives = positives; + tok.result = siftPatterns(negatives, positives, options); -/** - * Returns true if the character is an extglob character. - */ + if (options.capture && (positives.length + negatives.length) > 1) { + tok.result = '(' + tok.result + ')'; + } -function isExtglobChar(ch) { - return ch === '!' || ch === '@' || ch === '*' || ch === '?' || ch === '+'; + cache[key] = tok; + return tok.result; } -/** - * Combine text nodes, and calculate empty sets (`{,,}`) - * @param {Function} `pos` Function to calculate node position - * @param {Object} `node` AST node - * @return {Object} - */ +function siftPatterns(neg, pos, options) { + var onlyNegative = filterPatterns(neg, pos, '-', false, options) || []; + var onlyPositive = filterPatterns(pos, neg, '', false, options) || []; + var intersected = filterPatterns(neg, pos, '-?', true, options) || []; + var subpatterns = onlyNegative.concat(intersected).concat(onlyPositive); + return subpatterns.join('|'); +} -function concatNodes(pos, node, parent, options) { - node.orig = node.val; - var prev = this.prev(); - var last = utils.last(prev.nodes); - var isEscaped = false; +function splitToRanges(min, max) { + min = Number(min); + max = Number(max); - if (node.val.length > 1) { - var a = node.val.charAt(0); - var b = node.val.slice(-1); + var nines = 1; + var stops = [max]; + var stop = +countNines(min, nines); - isEscaped = (a === '"' && b === '"') - || (a === "'" && b === "'") - || (a === '`' && b === '`'); + while (min <= stop && stop <= max) { + stops = push(stops, stop); + nines += 1; + stop = +countNines(min, nines); } - if (isEscaped && options.unescape !== false) { - node.val = node.val.slice(1, node.val.length - 1); - node.escaped = true; - } + var zeros = 1; + stop = countZeros(max + 1, zeros) - 1; - if (node.match) { - var match = node.match[1]; - if (!match || match.indexOf('}') === -1) { - match = node.match[0]; - } - - // replace each set with a single "," - var val = match.replace(/\{/g, ',').replace(/\}/g, ''); - node.multiplier *= val.length; - node.val = ''; + while (min < stop && stop <= max) { + stops = push(stops, stop); + zeros += 1; + stop = countZeros(max + 1, zeros) - 1; } - var simpleText = last.type === 'text' - && last.multiplier === 1 - && node.multiplier === 1 - && node.val; + stops.sort(compare); + return stops; +} - if (simpleText) { - last.val += node.val; - return; - } +/** + * Convert a range to a regex pattern + * @param {Number} `start` + * @param {Number} `stop` + * @return {String} + */ - prev.push(node); -} +function rangeToPattern(start, stop, options) { + if (start === stop) { + return {pattern: String(start), digits: []}; + } + var zipped = zip(String(start), String(stop)); + var len = zipped.length, i = -1; -/***/ }), -/* 556 */ -/***/ (function(module, exports, __webpack_require__) { + var pattern = ''; + var digits = 0; -"use strict"; + while (++i < len) { + var numbers = zipped[i]; + var startDigit = numbers[0]; + var stopDigit = numbers[1]; + if (startDigit === stopDigit) { + pattern += startDigit; -var isObject = __webpack_require__(544); -var define = __webpack_require__(557); -var utils = __webpack_require__(564); -var ownNames; + } else if (startDigit !== '0' || stopDigit !== '9') { + pattern += toCharacterClass(startDigit, stopDigit); -/** - * Create a new AST `Node` with the given `val` and `type`. - * - * ```js - * var node = new Node('*', 'Star'); - * var node = new Node({type: 'star', val: '*'}); - * ``` - * @name Node - * @param {String|Object} `val` Pass a matched substring, or an object to merge onto the node. - * @param {String} `type` The node type to use when `val` is a string. - * @return {Object} node instance - * @api public - */ + } else { + digits += 1; + } + } -function Node(val, type, parent) { - if (typeof type !== 'string') { - parent = type; - type = null; + if (digits) { + pattern += options.shorthand ? '\\d' : '[0-9]'; } - define(this, 'parent', parent); - define(this, 'isNode', true); - define(this, 'expect', null); + return { pattern: pattern, digits: [digits] }; +} - if (typeof type !== 'string' && isObject(val)) { - lazyKeys(); - var keys = Object.keys(val); - for (var i = 0; i < keys.length; i++) { - var key = keys[i]; - if (ownNames.indexOf(key) === -1) { - this[key] = val[key]; +function splitToPatterns(min, max, tok, options) { + var ranges = splitToRanges(min, max); + var len = ranges.length; + var idx = -1; + + var tokens = []; + var start = min; + var prev; + + while (++idx < len) { + var range = ranges[idx]; + var obj = rangeToPattern(start, range, options); + var zeros = ''; + + if (!tok.isPadded && prev && prev.pattern === obj.pattern) { + if (prev.digits.length > 1) { + prev.digits.pop(); } + prev.digits.push(obj.digits[0]); + prev.string = prev.pattern + toQuantifier(prev.digits); + start = range + 1; + continue; } - } else { - this.type = type; - this.val = val; + + if (tok.isPadded) { + zeros = padZeros(range, tok); + } + + obj.string = zeros + obj.pattern + toQuantifier(obj.digits); + tokens.push(obj); + start = range + 1; + prev = obj; } + + return tokens; } -/** - * Returns true if the given value is a node. - * - * ```js - * var Node = require('snapdragon-node'); - * var node = new Node({type: 'foo'}); - * console.log(Node.isNode(node)); //=> true - * console.log(Node.isNode({})); //=> false - * ``` - * @param {Object} `node` - * @returns {Boolean} - * @api public - */ +function filterPatterns(arr, comparison, prefix, intersection, options) { + var res = []; -Node.isNode = function(node) { - return utils.isNode(node); -}; + for (var i = 0; i < arr.length; i++) { + var tok = arr[i]; + var ele = tok.string; -/** - * Define a non-enumberable property on the node instance. - * Useful for adding properties that shouldn't be extended - * or visible during debugging. - * - * ```js - * var node = new Node(); - * node.define('foo', 'something non-enumerable'); - * ``` - * @param {String} `name` - * @param {any} `val` - * @return {Object} returns the node instance - * @api public - */ + if (options.relaxZeros !== false) { + if (prefix === '-' && ele.charAt(0) === '0') { + if (ele.charAt(1) === '{') { + ele = '0*' + ele.replace(/^0\{\d+\}/, ''); + } else { + ele = '0*' + ele.slice(1); + } + } + } -Node.prototype.define = function(name, val) { - define(this, name, val); - return this; -}; + if (!intersection && !contains(comparison, 'string', ele)) { + res.push(prefix + ele); + } + + if (intersection && contains(comparison, 'string', ele)) { + res.push(prefix + ele); + } + } + return res; +} /** - * Returns true if `node.val` is an empty string, or `node.nodes` does - * not contain any non-empty text nodes. - * - * ```js - * var node = new Node({type: 'text'}); - * node.isEmpty(); //=> true - * node.val = 'foo'; - * node.isEmpty(); //=> false - * ``` - * @param {Function} `fn` (optional) Filter function that is called on `node` and/or child nodes. `isEmpty` will return false immediately when the filter function returns false on any nodes. - * @return {Boolean} - * @api public + * Zip strings (`for in` can be used on string characters) */ -Node.prototype.isEmpty = function(fn) { - return utils.isEmpty(this, fn); -}; +function zip(a, b) { + var arr = []; + for (var ch in a) arr.push([a[ch], b[ch]]); + return arr; +} -/** - * Given node `foo` and node `bar`, push node `bar` onto `foo.nodes`, and - * set `foo` as `bar.parent`. - * - * ```js - * var foo = new Node({type: 'foo'}); - * var bar = new Node({type: 'bar'}); - * foo.push(bar); - * ``` - * @param {Object} `node` - * @return {Number} Returns the length of `node.nodes` - * @api public - */ +function compare(a, b) { + return a > b ? 1 : b > a ? -1 : 0; +} -Node.prototype.push = function(node) { - assert(Node.isNode(node), 'expected node to be an instance of Node'); - define(node, 'parent', this); +function push(arr, ele) { + if (arr.indexOf(ele) === -1) arr.push(ele); + return arr; +} - this.nodes = this.nodes || []; - return this.nodes.push(node); -}; +function contains(arr, key, val) { + for (var i = 0; i < arr.length; i++) { + if (arr[i][key] === val) { + return true; + } + } + return false; +} -/** - * Given node `foo` and node `bar`, unshift node `bar` onto `foo.nodes`, and - * set `foo` as `bar.parent`. - * - * ```js - * var foo = new Node({type: 'foo'}); - * var bar = new Node({type: 'bar'}); - * foo.unshift(bar); - * ``` - * @param {Object} `node` - * @return {Number} Returns the length of `node.nodes` - * @api public - */ +function countNines(min, len) { + return String(min).slice(0, -len) + repeat('9', len); +} -Node.prototype.unshift = function(node) { - assert(Node.isNode(node), 'expected node to be an instance of Node'); - define(node, 'parent', this); +function countZeros(integer, zeros) { + return integer - (integer % Math.pow(10, zeros)); +} - this.nodes = this.nodes || []; - return this.nodes.unshift(node); -}; +function toQuantifier(digits) { + var start = digits[0]; + var stop = digits[1] ? (',' + digits[1]) : ''; + if (!stop && (!start || start === 1)) { + return ''; + } + return '{' + start + stop + '}'; +} -/** - * Pop a node from `node.nodes`. - * - * ```js - * var node = new Node({type: 'foo'}); - * node.push(new Node({type: 'a'})); - * node.push(new Node({type: 'b'})); - * node.push(new Node({type: 'c'})); - * node.push(new Node({type: 'd'})); - * console.log(node.nodes.length); - * //=> 4 - * node.pop(); - * console.log(node.nodes.length); - * //=> 3 - * ``` - * @return {Number} Returns the popped `node` - * @api public - */ +function toCharacterClass(a, b) { + return '[' + a + ((b - a === 1) ? '' : '-') + b + ']'; +} -Node.prototype.pop = function() { - return this.nodes && this.nodes.pop(); -}; +function padding(str) { + return /^-?(0+)\d/.exec(str); +} + +function padZeros(val, tok) { + if (tok.isPadded) { + var diff = Math.abs(tok.maxLen - String(val).length); + switch (diff) { + case 0: + return ''; + case 1: + return '0'; + default: { + return '0{' + diff + '}'; + } + } + } + return val; +} /** - * Shift a node from `node.nodes`. - * - * ```js - * var node = new Node({type: 'foo'}); - * node.push(new Node({type: 'a'})); - * node.push(new Node({type: 'b'})); - * node.push(new Node({type: 'c'})); - * node.push(new Node({type: 'd'})); - * console.log(node.nodes.length); - * //=> 4 - * node.shift(); - * console.log(node.nodes.length); - * //=> 3 - * ``` - * @return {Object} Returns the shifted `node` - * @api public + * Expose `toRegexRange` */ -Node.prototype.shift = function() { - return this.nodes && this.nodes.shift(); -}; +module.exports = toRegexRange; -/** - * Remove `node` from `node.nodes`. - * - * ```js - * node.remove(childNode); - * ``` - * @param {Object} `node` - * @return {Object} Returns the removed node. - * @api public - */ -Node.prototype.remove = function(node) { - assert(Node.isNode(node), 'expected node to be an instance of Node'); - this.nodes = this.nodes || []; - var idx = node.index; - if (idx !== -1) { - node.index = -1; - return this.nodes.splice(idx, 1); - } - return null; -}; +/***/ }), +/* 563 */ +/***/ (function(module, exports, __webpack_require__) { -/** - * Get the first child node from `node.nodes` that matches the given `type`. - * If `type` is a number, the child node at that index is returned. +"use strict"; +/*! + * repeat-element * - * ```js - * var child = node.find(1); //<= index of the node to get - * var child = node.find('foo'); //<= node.type of a child node - * var child = node.find(/^(foo|bar)$/); //<= regex to match node.type - * var child = node.find(['foo', 'bar']); //<= array of node.type(s) - * ``` - * @param {String} `type` - * @return {Object} Returns a child node or undefined. - * @api public + * Copyright (c) 2015 Jon Schlinkert. + * Licensed under the MIT license. */ -Node.prototype.find = function(type) { - return utils.findNode(this.nodes, type); -}; -/** - * Return true if the node is the given `type`. - * - * ```js - * var node = new Node({type: 'bar'}); - * cosole.log(node.isType('foo')); // false - * cosole.log(node.isType(/^(foo|bar)$/)); // true - * cosole.log(node.isType(['foo', 'bar'])); // true - * ``` - * @param {String} `type` - * @return {Boolean} - * @api public - */ -Node.prototype.isType = function(type) { - return utils.isType(this, type); -}; +module.exports = function repeat(ele, num) { + var arr = new Array(num); -/** - * Return true if the `node.nodes` has the given `type`. - * - * ```js - * var foo = new Node({type: 'foo'}); - * var bar = new Node({type: 'bar'}); - * foo.push(bar); - * - * cosole.log(foo.hasType('qux')); // false - * cosole.log(foo.hasType(/^(qux|bar)$/)); // true - * cosole.log(foo.hasType(['qux', 'bar'])); // true - * ``` - * @param {String} `type` - * @return {Boolean} - * @api public - */ + for (var i = 0; i < num; i++) { + arr[i] = ele; + } -Node.prototype.hasType = function(type) { - return utils.hasType(this, type); + return arr; }; -/** - * Get the siblings array, or `null` if it doesn't exist. - * - * ```js - * var foo = new Node({type: 'foo'}); - * var bar = new Node({type: 'bar'}); - * var baz = new Node({type: 'baz'}); - * foo.push(bar); - * foo.push(baz); - * - * console.log(bar.siblings.length) // 2 - * console.log(baz.siblings.length) // 2 - * ``` - * @return {Array} - * @api public - */ -Object.defineProperty(Node.prototype, 'siblings', { - set: function() { - throw new Error('node.siblings is a getter and cannot be defined'); - }, - get: function() { - return this.parent ? this.parent.nodes : null; - } -}); +/***/ }), +/* 564 */ +/***/ (function(module, exports, __webpack_require__) { -/** - * Get the node's current index from `node.parent.nodes`. - * This should always be correct, even when the parent adds nodes. - * - * ```js - * var foo = new Node({type: 'foo'}); - * var bar = new Node({type: 'bar'}); - * var baz = new Node({type: 'baz'}); - * var qux = new Node({type: 'qux'}); - * foo.push(bar); - * foo.push(baz); - * foo.unshift(qux); - * - * console.log(bar.index) // 1 - * console.log(baz.index) // 2 - * console.log(qux.index) // 0 - * ``` - * @return {Number} - * @api public - */ +"use strict"; -Object.defineProperty(Node.prototype, 'index', { - set: function(index) { - define(this, 'idx', index); - }, - get: function() { - if (!Array.isArray(this.siblings)) { - return -1; - } - var tok = this.idx !== -1 ? this.siblings[this.idx] : null; - if (tok !== this) { - this.idx = this.siblings.indexOf(this); - } - return this.idx; - } -}); + +var Node = __webpack_require__(565); +var utils = __webpack_require__(552); /** - * Get the previous node from the siblings array or `null`. - * - * ```js - * var foo = new Node({type: 'foo'}); - * var bar = new Node({type: 'bar'}); - * var baz = new Node({type: 'baz'}); - * foo.push(bar); - * foo.push(baz); - * - * console.log(baz.prev.type) // 'bar' - * ``` - * @return {Object} - * @api public + * Braces parsers */ -Object.defineProperty(Node.prototype, 'prev', { - set: function() { - throw new Error('node.prev is a getter and cannot be defined'); - }, - get: function() { - if (Array.isArray(this.siblings)) { - return this.siblings[this.index - 1] || this.parent.prev; - } - return null; - } -}); +module.exports = function(braces, options) { + braces.parser + .set('bos', function() { + if (!this.parsed) { + this.ast = this.nodes[0] = new Node(this.ast); + } + }) -/** - * Get the siblings array, or `null` if it doesn't exist. - * - * ```js - * var foo = new Node({type: 'foo'}); - * var bar = new Node({type: 'bar'}); - * var baz = new Node({type: 'baz'}); - * foo.push(bar); - * foo.push(baz); - * - * console.log(bar.siblings.length) // 2 - * console.log(baz.siblings.length) // 2 - * ``` - * @return {Object} - * @api public - */ + /** + * Character parsers + */ -Object.defineProperty(Node.prototype, 'next', { - set: function() { - throw new Error('node.next is a getter and cannot be defined'); - }, - get: function() { - if (Array.isArray(this.siblings)) { - return this.siblings[this.index + 1] || this.parent.next; - } - return null; - } -}); + .set('escape', function() { + var pos = this.position(); + var m = this.match(/^(?:\\(.)|\$\{)/); + if (!m) return; -/** - * Get the first node from `node.nodes`. - * - * ```js - * var foo = new Node({type: 'foo'}); - * var bar = new Node({type: 'bar'}); - * var baz = new Node({type: 'baz'}); - * var qux = new Node({type: 'qux'}); - * foo.push(bar); - * foo.push(baz); - * foo.push(qux); - * - * console.log(foo.first.type) // 'bar' - * ``` - * @return {Object} The first node, or undefiend - * @api public - */ + var prev = this.prev(); + var last = utils.last(prev.nodes); -Object.defineProperty(Node.prototype, 'first', { - get: function() { - return this.nodes ? this.nodes[0] : null; - } -}); + var node = pos(new Node({ + type: 'text', + multiplier: 1, + val: m[0] + })); -/** - * Get the last node from `node.nodes`. - * - * ```js - * var foo = new Node({type: 'foo'}); - * var bar = new Node({type: 'bar'}); - * var baz = new Node({type: 'baz'}); - * var qux = new Node({type: 'qux'}); - * foo.push(bar); - * foo.push(baz); - * foo.push(qux); - * - * console.log(foo.last.type) // 'qux' - * ``` - * @return {Object} The last node, or undefiend - * @api public - */ + if (node.val === '\\\\') { + return node; + } -Object.defineProperty(Node.prototype, 'last', { - get: function() { - return this.nodes ? utils.last(this.nodes) : null; - } -}); + if (node.val === '${') { + var str = this.input; + var idx = -1; + var ch; -/** - * Get the last node from `node.nodes`. - * - * ```js - * var foo = new Node({type: 'foo'}); - * var bar = new Node({type: 'bar'}); - * var baz = new Node({type: 'baz'}); - * var qux = new Node({type: 'qux'}); - * foo.push(bar); - * foo.push(baz); - * foo.push(qux); - * - * console.log(foo.last.type) // 'qux' - * ``` - * @return {Object} The last node, or undefiend - * @api public - */ + while ((ch = str[++idx])) { + this.consume(1); + node.val += ch; + if (ch === '\\') { + node.val += str[++idx]; + continue; + } + if (ch === '}') { + break; + } + } + } -Object.defineProperty(Node.prototype, 'scope', { - get: function() { - if (this.isScope !== true) { - return this.parent ? this.parent.scope : this; - } - return this; - } -}); + if (this.options.unescape !== false) { + node.val = node.val.replace(/\\([{}])/g, '$1'); + } -/** - * Get own property names from Node prototype, but only the - * first time `Node` is instantiated - */ + if (last.val === '"' && this.input.charAt(0) === '"') { + last.val = node.val; + this.consume(1); + return; + } -function lazyKeys() { - if (!ownNames) { - ownNames = Object.getOwnPropertyNames(Node.prototype); - } -} + return concatNodes.call(this, pos, node, prev, options); + }) -/** - * Simplified assertion. Throws an error is `val` is falsey. - */ + /** + * Brackets: "[...]" (basic, this is overridden by + * other parsers in more advanced implementations) + */ -function assert(val, message) { - if (!val) throw new Error(message); -} + .set('bracket', function() { + var isInside = this.isInside('brace'); + var pos = this.position(); + var m = this.match(/^(?:\[([!^]?)([^\]]{2,}|\]-)(\]|[^*+?]+)|\[)/); + if (!m) return; -/** - * Expose `Node` - */ + var prev = this.prev(); + var val = m[0]; + var negated = m[1] ? '^' : ''; + var inner = m[2] || ''; + var close = m[3] || ''; -exports = module.exports = Node; + if (isInside && prev.type === 'brace') { + prev.text = prev.text || ''; + prev.text += val; + } + var esc = this.input.slice(0, 2); + if (inner === '' && esc === '\\]') { + inner += esc; + this.consume(2); -/***/ }), -/* 557 */ -/***/ (function(module, exports, __webpack_require__) { + var str = this.input; + var idx = -1; + var ch; -"use strict"; -/*! - * define-property - * - * Copyright (c) 2015, 2017, Jon Schlinkert. - * Released under the MIT License. - */ + while ((ch = str[++idx])) { + this.consume(1); + if (ch === ']') { + close = ch; + break; + } + inner += ch; + } + } + return pos(new Node({ + type: 'bracket', + val: val, + escaped: close !== ']', + negated: negated, + inner: inner, + close: close + })); + }) + /** + * Empty braces (we capture these early to + * speed up processing in the compiler) + */ -var isDescriptor = __webpack_require__(558); + .set('multiplier', function() { + var isInside = this.isInside('brace'); + var pos = this.position(); + var m = this.match(/^\{((?:,|\{,+\})+)\}/); + if (!m) return; -module.exports = function defineProperty(obj, prop, val) { - if (typeof obj !== 'object' && typeof obj !== 'function') { - throw new TypeError('expected an object or function.'); - } + this.multiplier = true; + var prev = this.prev(); + var val = m[0]; - if (typeof prop !== 'string') { - throw new TypeError('expected `prop` to be a string.'); - } + if (isInside && prev.type === 'brace') { + prev.text = prev.text || ''; + prev.text += val; + } - if (isDescriptor(val) && ('set' in val || 'get' in val)) { - return Object.defineProperty(obj, prop, val); - } + var node = pos(new Node({ + type: 'text', + multiplier: 1, + match: m, + val: val + })); - return Object.defineProperty(obj, prop, { - configurable: true, - enumerable: false, - writable: true, - value: val - }); -}; + return concatNodes.call(this, pos, node, prev, options); + }) + /** + * Open + */ -/***/ }), -/* 558 */ -/***/ (function(module, exports, __webpack_require__) { + .set('brace.open', function() { + var pos = this.position(); + var m = this.match(/^\{(?!(?:[^\\}]?|,+)\})/); + if (!m) return; -"use strict"; -/*! - * is-descriptor - * - * Copyright (c) 2015-2017, Jon Schlinkert. - * Released under the MIT License. - */ + var prev = this.prev(); + var last = utils.last(prev.nodes); + // if the last parsed character was an extglob character + // we need to _not optimize_ the brace pattern because + // it might be mistaken for an extglob by a downstream parser + if (last && last.val && isExtglobChar(last.val.slice(-1))) { + last.optimize = false; + } + var open = pos(new Node({ + type: 'brace.open', + val: m[0] + })); -var typeOf = __webpack_require__(559); -var isAccessor = __webpack_require__(560); -var isData = __webpack_require__(562); + var node = pos(new Node({ + type: 'brace', + nodes: [] + })); -module.exports = function isDescriptor(obj, key) { - if (typeOf(obj) !== 'object') { - return false; - } - if ('get' in obj) { - return isAccessor(obj, key); - } - return isData(obj, key); -}; + node.push(open); + prev.push(node); + this.push('brace', node); + }) + /** + * Close + */ -/***/ }), -/* 559 */ -/***/ (function(module, exports) { + .set('brace.close', function() { + var pos = this.position(); + var m = this.match(/^\}/); + if (!m || !m[0]) return; -var toString = Object.prototype.toString; + var brace = this.pop('brace'); + var node = pos(new Node({ + type: 'brace.close', + val: m[0] + })); -module.exports = function kindOf(val) { - if (val === void 0) return 'undefined'; - if (val === null) return 'null'; + if (!this.isType(brace, 'brace')) { + if (this.options.strict) { + throw new Error('missing opening "{"'); + } + node.type = 'text'; + node.multiplier = 0; + node.escaped = true; + return node; + } - var type = typeof val; - if (type === 'boolean') return 'boolean'; - if (type === 'string') return 'string'; - if (type === 'number') return 'number'; - if (type === 'symbol') return 'symbol'; - if (type === 'function') { - return isGeneratorFn(val) ? 'generatorfunction' : 'function'; - } + var prev = this.prev(); + var last = utils.last(prev.nodes); + if (last.text) { + var lastNode = utils.last(last.nodes); + if (lastNode.val === ')' && /[!@*?+]\(/.test(last.text)) { + var open = last.nodes[0]; + var text = last.nodes[1]; + if (open.type === 'brace.open' && text && text.type === 'text') { + text.optimize = false; + } + } + } - if (isArray(val)) return 'array'; - if (isBuffer(val)) return 'buffer'; - if (isArguments(val)) return 'arguments'; - if (isDate(val)) return 'date'; - if (isError(val)) return 'error'; - if (isRegexp(val)) return 'regexp'; + if (brace.nodes.length > 2) { + var first = brace.nodes[1]; + if (first.type === 'text' && first.val === ',') { + brace.nodes.splice(1, 1); + brace.nodes.push(first); + } + } - switch (ctorName(val)) { - case 'Symbol': return 'symbol'; - case 'Promise': return 'promise'; + brace.push(node); + }) - // Set, Map, WeakSet, WeakMap - case 'WeakMap': return 'weakmap'; - case 'WeakSet': return 'weakset'; - case 'Map': return 'map'; - case 'Set': return 'set'; + /** + * Capture boundary characters + */ - // 8-bit typed arrays - case 'Int8Array': return 'int8array'; - case 'Uint8Array': return 'uint8array'; - case 'Uint8ClampedArray': return 'uint8clampedarray'; + .set('boundary', function() { + var pos = this.position(); + var m = this.match(/^[$^](?!\{)/); + if (!m) return; + return pos(new Node({ + type: 'text', + val: m[0] + })); + }) - // 16-bit typed arrays - case 'Int16Array': return 'int16array'; - case 'Uint16Array': return 'uint16array'; + /** + * One or zero, non-comma characters wrapped in braces + */ - // 32-bit typed arrays - case 'Int32Array': return 'int32array'; - case 'Uint32Array': return 'uint32array'; - case 'Float32Array': return 'float32array'; - case 'Float64Array': return 'float64array'; - } + .set('nobrace', function() { + var isInside = this.isInside('brace'); + var pos = this.position(); + var m = this.match(/^\{[^,]?\}/); + if (!m) return; - if (isGeneratorObj(val)) { - return 'generator'; - } + var prev = this.prev(); + var val = m[0]; - // Non-plain objects - type = toString.call(val); - switch (type) { - case '[object Object]': return 'object'; - // iterators - case '[object Map Iterator]': return 'mapiterator'; - case '[object Set Iterator]': return 'setiterator'; - case '[object String Iterator]': return 'stringiterator'; - case '[object Array Iterator]': return 'arrayiterator'; - } + if (isInside && prev.type === 'brace') { + prev.text = prev.text || ''; + prev.text += val; + } - // other - return type.slice(8, -1).toLowerCase().replace(/\s/g, ''); -}; + return pos(new Node({ + type: 'text', + multiplier: 0, + val: val + })); + }) -function ctorName(val) { - return typeof val.constructor === 'function' ? val.constructor.name : null; -} + /** + * Text + */ -function isArray(val) { - if (Array.isArray) return Array.isArray(val); - return val instanceof Array; -} + .set('text', function() { + var isInside = this.isInside('brace'); + var pos = this.position(); + var m = this.match(/^((?!\\)[^${}[\]])+/); + if (!m) return; -function isError(val) { - return val instanceof Error || (typeof val.message === 'string' && val.constructor && typeof val.constructor.stackTraceLimit === 'number'); -} + var prev = this.prev(); + var val = m[0]; -function isDate(val) { - if (val instanceof Date) return true; - return typeof val.toDateString === 'function' - && typeof val.getDate === 'function' - && typeof val.setDate === 'function'; -} + if (isInside && prev.type === 'brace') { + prev.text = prev.text || ''; + prev.text += val; + } -function isRegexp(val) { - if (val instanceof RegExp) return true; - return typeof val.flags === 'string' - && typeof val.ignoreCase === 'boolean' - && typeof val.multiline === 'boolean' - && typeof val.global === 'boolean'; -} + var node = pos(new Node({ + type: 'text', + multiplier: 1, + val: val + })); -function isGeneratorFn(name, val) { - return ctorName(name) === 'GeneratorFunction'; -} + return concatNodes.call(this, pos, node, prev, options); + }); +}; -function isGeneratorObj(val) { - return typeof val.throw === 'function' - && typeof val.return === 'function' - && typeof val.next === 'function'; -} +/** + * Returns true if the character is an extglob character. + */ -function isArguments(val) { - try { - if (typeof val.length === 'number' && typeof val.callee === 'function') { - return true; - } - } catch (err) { - if (err.message.indexOf('callee') !== -1) { - return true; - } - } - return false; +function isExtglobChar(ch) { + return ch === '!' || ch === '@' || ch === '*' || ch === '?' || ch === '+'; } /** - * If you need to support Safari 5-7 (8-10 yr-old browser), - * take a look at https://github.com/feross/is-buffer + * Combine text nodes, and calculate empty sets (`{,,}`) + * @param {Function} `pos` Function to calculate node position + * @param {Object} `node` AST node + * @return {Object} */ -function isBuffer(val) { - if (val.constructor && typeof val.constructor.isBuffer === 'function') { - return val.constructor.isBuffer(val); - } - return false; -} - - -/***/ }), -/* 560 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; -/*! - * is-accessor-descriptor - * - * Copyright (c) 2015-2017, Jon Schlinkert. - * Released under the MIT License. - */ - - - -var typeOf = __webpack_require__(561); - -// accessor descriptor properties -var accessor = { - get: 'function', - set: 'function', - configurable: 'boolean', - enumerable: 'boolean' -}; - -function isAccessorDescriptor(obj, prop) { - if (typeof prop === 'string') { - var val = Object.getOwnPropertyDescriptor(obj, prop); - return typeof val !== 'undefined'; - } - - if (typeOf(obj) !== 'object') { - return false; - } +function concatNodes(pos, node, parent, options) { + node.orig = node.val; + var prev = this.prev(); + var last = utils.last(prev.nodes); + var isEscaped = false; - if (has(obj, 'value') || has(obj, 'writable')) { - return false; - } + if (node.val.length > 1) { + var a = node.val.charAt(0); + var b = node.val.slice(-1); - if (!has(obj, 'get') || typeof obj.get !== 'function') { - return false; + isEscaped = (a === '"' && b === '"') + || (a === "'" && b === "'") + || (a === '`' && b === '`'); } - // tldr: it's valid to have "set" be undefined - // "set" might be undefined if `Object.getOwnPropertyDescriptor` - // was used to get the value, and only `get` was defined by the user - if (has(obj, 'set') && typeof obj[key] !== 'function' && typeof obj[key] !== 'undefined') { - return false; + if (isEscaped && options.unescape !== false) { + node.val = node.val.slice(1, node.val.length - 1); + node.escaped = true; } - for (var key in obj) { - if (!accessor.hasOwnProperty(key)) { - continue; - } - - if (typeOf(obj[key]) === accessor[key]) { - continue; - } - - if (typeof obj[key] !== 'undefined') { - return false; + if (node.match) { + var match = node.match[1]; + if (!match || match.indexOf('}') === -1) { + match = node.match[0]; } - } - return true; -} - -function has(obj, key) { - return {}.hasOwnProperty.call(obj, key); -} - -/** - * Expose `isAccessorDescriptor` - */ - -module.exports = isAccessorDescriptor; - - -/***/ }), -/* 561 */ -/***/ (function(module, exports) { - -var toString = Object.prototype.toString; - -module.exports = function kindOf(val) { - if (val === void 0) return 'undefined'; - if (val === null) return 'null'; - - var type = typeof val; - if (type === 'boolean') return 'boolean'; - if (type === 'string') return 'string'; - if (type === 'number') return 'number'; - if (type === 'symbol') return 'symbol'; - if (type === 'function') { - return isGeneratorFn(val) ? 'generatorfunction' : 'function'; - } - - if (isArray(val)) return 'array'; - if (isBuffer(val)) return 'buffer'; - if (isArguments(val)) return 'arguments'; - if (isDate(val)) return 'date'; - if (isError(val)) return 'error'; - if (isRegexp(val)) return 'regexp'; - - switch (ctorName(val)) { - case 'Symbol': return 'symbol'; - case 'Promise': return 'promise'; - - // Set, Map, WeakSet, WeakMap - case 'WeakMap': return 'weakmap'; - case 'WeakSet': return 'weakset'; - case 'Map': return 'map'; - case 'Set': return 'set'; - - // 8-bit typed arrays - case 'Int8Array': return 'int8array'; - case 'Uint8Array': return 'uint8array'; - case 'Uint8ClampedArray': return 'uint8clampedarray'; - // 16-bit typed arrays - case 'Int16Array': return 'int16array'; - case 'Uint16Array': return 'uint16array'; - - // 32-bit typed arrays - case 'Int32Array': return 'int32array'; - case 'Uint32Array': return 'uint32array'; - case 'Float32Array': return 'float32array'; - case 'Float64Array': return 'float64array'; - } - - if (isGeneratorObj(val)) { - return 'generator'; - } - - // Non-plain objects - type = toString.call(val); - switch (type) { - case '[object Object]': return 'object'; - // iterators - case '[object Map Iterator]': return 'mapiterator'; - case '[object Set Iterator]': return 'setiterator'; - case '[object String Iterator]': return 'stringiterator'; - case '[object Array Iterator]': return 'arrayiterator'; + // replace each set with a single "," + var val = match.replace(/\{/g, ',').replace(/\}/g, ''); + node.multiplier *= val.length; + node.val = ''; } - // other - return type.slice(8, -1).toLowerCase().replace(/\s/g, ''); -}; - -function ctorName(val) { - return typeof val.constructor === 'function' ? val.constructor.name : null; -} - -function isArray(val) { - if (Array.isArray) return Array.isArray(val); - return val instanceof Array; -} - -function isError(val) { - return val instanceof Error || (typeof val.message === 'string' && val.constructor && typeof val.constructor.stackTraceLimit === 'number'); -} - -function isDate(val) { - if (val instanceof Date) return true; - return typeof val.toDateString === 'function' - && typeof val.getDate === 'function' - && typeof val.setDate === 'function'; -} - -function isRegexp(val) { - if (val instanceof RegExp) return true; - return typeof val.flags === 'string' - && typeof val.ignoreCase === 'boolean' - && typeof val.multiline === 'boolean' - && typeof val.global === 'boolean'; -} - -function isGeneratorFn(name, val) { - return ctorName(name) === 'GeneratorFunction'; -} - -function isGeneratorObj(val) { - return typeof val.throw === 'function' - && typeof val.return === 'function' - && typeof val.next === 'function'; -} + var simpleText = last.type === 'text' + && last.multiplier === 1 + && node.multiplier === 1 + && node.val; -function isArguments(val) { - try { - if (typeof val.length === 'number' && typeof val.callee === 'function') { - return true; - } - } catch (err) { - if (err.message.indexOf('callee') !== -1) { - return true; - } + if (simpleText) { + last.val += node.val; + return; } - return false; -} - -/** - * If you need to support Safari 5-7 (8-10 yr-old browser), - * take a look at https://github.com/feross/is-buffer - */ -function isBuffer(val) { - if (val.constructor && typeof val.constructor.isBuffer === 'function') { - return val.constructor.isBuffer(val); - } - return false; + prev.push(node); } /***/ }), -/* 562 */ +/* 565 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -/*! - * is-data-descriptor - * - * Copyright (c) 2015-2017, Jon Schlinkert. - * Released under the MIT License. - */ - - - -var typeOf = __webpack_require__(563); - -module.exports = function isDataDescriptor(obj, prop) { - // data descriptor properties - var data = { - configurable: 'boolean', - enumerable: 'boolean', - writable: 'boolean' - }; - - if (typeOf(obj) !== 'object') { - return false; - } - - if (typeof prop === 'string') { - var val = Object.getOwnPropertyDescriptor(obj, prop); - return typeof val !== 'undefined'; - } - - if (!('value' in obj) && !('writable' in obj)) { - return false; - } - - for (var key in obj) { - if (key === 'value') continue; - - if (!data.hasOwnProperty(key)) { - continue; - } - - if (typeOf(obj[key]) === data[key]) { - continue; - } - - if (typeof obj[key] !== 'undefined') { - return false; - } - } - return true; -}; - - -/***/ }), -/* 563 */ -/***/ (function(module, exports) { - -var toString = Object.prototype.toString; - -module.exports = function kindOf(val) { - if (val === void 0) return 'undefined'; - if (val === null) return 'null'; - - var type = typeof val; - if (type === 'boolean') return 'boolean'; - if (type === 'string') return 'string'; - if (type === 'number') return 'number'; - if (type === 'symbol') return 'symbol'; - if (type === 'function') { - return isGeneratorFn(val) ? 'generatorfunction' : 'function'; - } - - if (isArray(val)) return 'array'; - if (isBuffer(val)) return 'buffer'; - if (isArguments(val)) return 'arguments'; - if (isDate(val)) return 'date'; - if (isError(val)) return 'error'; - if (isRegexp(val)) return 'regexp'; - - switch (ctorName(val)) { - case 'Symbol': return 'symbol'; - case 'Promise': return 'promise'; - - // Set, Map, WeakSet, WeakMap - case 'WeakMap': return 'weakmap'; - case 'WeakSet': return 'weakset'; - case 'Map': return 'map'; - case 'Set': return 'set'; - - // 8-bit typed arrays - case 'Int8Array': return 'int8array'; - case 'Uint8Array': return 'uint8array'; - case 'Uint8ClampedArray': return 'uint8clampedarray'; - // 16-bit typed arrays - case 'Int16Array': return 'int16array'; - case 'Uint16Array': return 'uint16array'; - // 32-bit typed arrays - case 'Int32Array': return 'int32array'; - case 'Uint32Array': return 'uint32array'; - case 'Float32Array': return 'float32array'; - case 'Float64Array': return 'float64array'; - } +var isObject = __webpack_require__(534); +var define = __webpack_require__(566); +var utils = __webpack_require__(567); +var ownNames; - if (isGeneratorObj(val)) { - return 'generator'; - } +/** + * Create a new AST `Node` with the given `val` and `type`. + * + * ```js + * var node = new Node('*', 'Star'); + * var node = new Node({type: 'star', val: '*'}); + * ``` + * @name Node + * @param {String|Object} `val` Pass a matched substring, or an object to merge onto the node. + * @param {String} `type` The node type to use when `val` is a string. + * @return {Object} node instance + * @api public + */ - // Non-plain objects - type = toString.call(val); - switch (type) { - case '[object Object]': return 'object'; - // iterators - case '[object Map Iterator]': return 'mapiterator'; - case '[object Set Iterator]': return 'setiterator'; - case '[object String Iterator]': return 'stringiterator'; - case '[object Array Iterator]': return 'arrayiterator'; +function Node(val, type, parent) { + if (typeof type !== 'string') { + parent = type; + type = null; } - // other - return type.slice(8, -1).toLowerCase().replace(/\s/g, ''); -}; - -function ctorName(val) { - return typeof val.constructor === 'function' ? val.constructor.name : null; -} - -function isArray(val) { - if (Array.isArray) return Array.isArray(val); - return val instanceof Array; -} - -function isError(val) { - return val instanceof Error || (typeof val.message === 'string' && val.constructor && typeof val.constructor.stackTraceLimit === 'number'); -} - -function isDate(val) { - if (val instanceof Date) return true; - return typeof val.toDateString === 'function' - && typeof val.getDate === 'function' - && typeof val.setDate === 'function'; -} - -function isRegexp(val) { - if (val instanceof RegExp) return true; - return typeof val.flags === 'string' - && typeof val.ignoreCase === 'boolean' - && typeof val.multiline === 'boolean' - && typeof val.global === 'boolean'; -} - -function isGeneratorFn(name, val) { - return ctorName(name) === 'GeneratorFunction'; -} - -function isGeneratorObj(val) { - return typeof val.throw === 'function' - && typeof val.return === 'function' - && typeof val.next === 'function'; -} + define(this, 'parent', parent); + define(this, 'isNode', true); + define(this, 'expect', null); -function isArguments(val) { - try { - if (typeof val.length === 'number' && typeof val.callee === 'function') { - return true; - } - } catch (err) { - if (err.message.indexOf('callee') !== -1) { - return true; + if (typeof type !== 'string' && isObject(val)) { + lazyKeys(); + var keys = Object.keys(val); + for (var i = 0; i < keys.length; i++) { + var key = keys[i]; + if (ownNames.indexOf(key) === -1) { + this[key] = val[key]; + } } + } else { + this.type = type; + this.val = val; } - return false; -} - -/** - * If you need to support Safari 5-7 (8-10 yr-old browser), - * take a look at https://github.com/feross/is-buffer - */ - -function isBuffer(val) { - if (val.constructor && typeof val.constructor.isBuffer === 'function') { - return val.constructor.isBuffer(val); - } - return false; } - -/***/ }), -/* 564 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -var typeOf = __webpack_require__(549); -var utils = module.exports; - /** * Returns true if the given value is a node. * * ```js * var Node = require('snapdragon-node'); * var node = new Node({type: 'foo'}); - * console.log(utils.isNode(node)); //=> true - * console.log(utils.isNode({})); //=> false + * console.log(Node.isNode(node)); //=> true + * console.log(Node.isNode({})); //=> false * ``` - * @param {Object} `node` Instance of [snapdragon-node][] + * @param {Object} `node` * @returns {Boolean} * @api public */ -utils.isNode = function(node) { - return typeOf(node) === 'object' && node.isNode === true; +Node.isNode = function(node) { + return utils.isNode(node); }; /** - * Emit an empty string for the given `node`. + * Define a non-enumberable property on the node instance. + * Useful for adding properties that shouldn't be extended + * or visible during debugging. * * ```js - * // do nothing for beginning-of-string - * snapdragon.compiler.set('bos', utils.noop); + * var node = new Node(); + * node.define('foo', 'something non-enumerable'); * ``` - * @param {Object} `node` Instance of [snapdragon-node][] - * @returns {undefined} + * @param {String} `name` + * @param {any} `val` + * @return {Object} returns the node instance * @api public */ -utils.noop = function(node) { - append(this, '', node); +Node.prototype.define = function(name, val) { + define(this, name, val); + return this; }; /** - * Appdend `node.val` to `compiler.output`, exactly as it was created - * by the parser. + * Returns true if `node.val` is an empty string, or `node.nodes` does + * not contain any non-empty text nodes. * * ```js - * snapdragon.compiler.set('text', utils.identity); + * var node = new Node({type: 'text'}); + * node.isEmpty(); //=> true + * node.val = 'foo'; + * node.isEmpty(); //=> false * ``` - * @param {Object} `node` Instance of [snapdragon-node][] - * @returns {undefined} + * @param {Function} `fn` (optional) Filter function that is called on `node` and/or child nodes. `isEmpty` will return false immediately when the filter function returns false on any nodes. + * @return {Boolean} * @api public */ -utils.identity = function(node) { - append(this, node.val, node); +Node.prototype.isEmpty = function(fn) { + return utils.isEmpty(this, fn); }; /** - * Previously named `.emit`, this method appends the given `val` - * to `compiler.output` for the given node. Useful when you know - * what value should be appended advance, regardless of the actual - * value of `node.val`. + * Given node `foo` and node `bar`, push node `bar` onto `foo.nodes`, and + * set `foo` as `bar.parent`. * * ```js - * snapdragon.compiler - * .set('i', function(node) { - * this.mapVisit(node); - * }) - * .set('i.open', utils.append('')) - * .set('i.close', utils.append('')) + * var foo = new Node({type: 'foo'}); + * var bar = new Node({type: 'bar'}); + * foo.push(bar); * ``` - * @param {Object} `node` Instance of [snapdragon-node][] - * @returns {Function} Returns a compiler middleware function. + * @param {Object} `node` + * @return {Number} Returns the length of `node.nodes` * @api public */ -utils.append = function(val) { - return function(node) { - append(this, val, node); - }; -}; +Node.prototype.push = function(node) { + assert(Node.isNode(node), 'expected node to be an instance of Node'); + define(node, 'parent', this); + + this.nodes = this.nodes || []; + return this.nodes.push(node); +}; + +/** + * Given node `foo` and node `bar`, unshift node `bar` onto `foo.nodes`, and + * set `foo` as `bar.parent`. + * + * ```js + * var foo = new Node({type: 'foo'}); + * var bar = new Node({type: 'bar'}); + * foo.unshift(bar); + * ``` + * @param {Object} `node` + * @return {Number} Returns the length of `node.nodes` + * @api public + */ + +Node.prototype.unshift = function(node) { + assert(Node.isNode(node), 'expected node to be an instance of Node'); + define(node, 'parent', this); + + this.nodes = this.nodes || []; + return this.nodes.unshift(node); +}; + +/** + * Pop a node from `node.nodes`. + * + * ```js + * var node = new Node({type: 'foo'}); + * node.push(new Node({type: 'a'})); + * node.push(new Node({type: 'b'})); + * node.push(new Node({type: 'c'})); + * node.push(new Node({type: 'd'})); + * console.log(node.nodes.length); + * //=> 4 + * node.pop(); + * console.log(node.nodes.length); + * //=> 3 + * ``` + * @return {Number} Returns the popped `node` + * @api public + */ + +Node.prototype.pop = function() { + return this.nodes && this.nodes.pop(); +}; + +/** + * Shift a node from `node.nodes`. + * + * ```js + * var node = new Node({type: 'foo'}); + * node.push(new Node({type: 'a'})); + * node.push(new Node({type: 'b'})); + * node.push(new Node({type: 'c'})); + * node.push(new Node({type: 'd'})); + * console.log(node.nodes.length); + * //=> 4 + * node.shift(); + * console.log(node.nodes.length); + * //=> 3 + * ``` + * @return {Object} Returns the shifted `node` + * @api public + */ + +Node.prototype.shift = function() { + return this.nodes && this.nodes.shift(); +}; + +/** + * Remove `node` from `node.nodes`. + * + * ```js + * node.remove(childNode); + * ``` + * @param {Object} `node` + * @return {Object} Returns the removed node. + * @api public + */ + +Node.prototype.remove = function(node) { + assert(Node.isNode(node), 'expected node to be an instance of Node'); + this.nodes = this.nodes || []; + var idx = node.index; + if (idx !== -1) { + node.index = -1; + return this.nodes.splice(idx, 1); + } + return null; +}; + +/** + * Get the first child node from `node.nodes` that matches the given `type`. + * If `type` is a number, the child node at that index is returned. + * + * ```js + * var child = node.find(1); //<= index of the node to get + * var child = node.find('foo'); //<= node.type of a child node + * var child = node.find(/^(foo|bar)$/); //<= regex to match node.type + * var child = node.find(['foo', 'bar']); //<= array of node.type(s) + * ``` + * @param {String} `type` + * @return {Object} Returns a child node or undefined. + * @api public + */ + +Node.prototype.find = function(type) { + return utils.findNode(this.nodes, type); +}; + +/** + * Return true if the node is the given `type`. + * + * ```js + * var node = new Node({type: 'bar'}); + * cosole.log(node.isType('foo')); // false + * cosole.log(node.isType(/^(foo|bar)$/)); // true + * cosole.log(node.isType(['foo', 'bar'])); // true + * ``` + * @param {String} `type` + * @return {Boolean} + * @api public + */ + +Node.prototype.isType = function(type) { + return utils.isType(this, type); +}; + +/** + * Return true if the `node.nodes` has the given `type`. + * + * ```js + * var foo = new Node({type: 'foo'}); + * var bar = new Node({type: 'bar'}); + * foo.push(bar); + * + * cosole.log(foo.hasType('qux')); // false + * cosole.log(foo.hasType(/^(qux|bar)$/)); // true + * cosole.log(foo.hasType(['qux', 'bar'])); // true + * ``` + * @param {String} `type` + * @return {Boolean} + * @api public + */ + +Node.prototype.hasType = function(type) { + return utils.hasType(this, type); +}; + +/** + * Get the siblings array, or `null` if it doesn't exist. + * + * ```js + * var foo = new Node({type: 'foo'}); + * var bar = new Node({type: 'bar'}); + * var baz = new Node({type: 'baz'}); + * foo.push(bar); + * foo.push(baz); + * + * console.log(bar.siblings.length) // 2 + * console.log(baz.siblings.length) // 2 + * ``` + * @return {Array} + * @api public + */ + +Object.defineProperty(Node.prototype, 'siblings', { + set: function() { + throw new Error('node.siblings is a getter and cannot be defined'); + }, + get: function() { + return this.parent ? this.parent.nodes : null; + } +}); + +/** + * Get the node's current index from `node.parent.nodes`. + * This should always be correct, even when the parent adds nodes. + * + * ```js + * var foo = new Node({type: 'foo'}); + * var bar = new Node({type: 'bar'}); + * var baz = new Node({type: 'baz'}); + * var qux = new Node({type: 'qux'}); + * foo.push(bar); + * foo.push(baz); + * foo.unshift(qux); + * + * console.log(bar.index) // 1 + * console.log(baz.index) // 2 + * console.log(qux.index) // 0 + * ``` + * @return {Number} + * @api public + */ + +Object.defineProperty(Node.prototype, 'index', { + set: function(index) { + define(this, 'idx', index); + }, + get: function() { + if (!Array.isArray(this.siblings)) { + return -1; + } + var tok = this.idx !== -1 ? this.siblings[this.idx] : null; + if (tok !== this) { + this.idx = this.siblings.indexOf(this); + } + return this.idx; + } +}); + +/** + * Get the previous node from the siblings array or `null`. + * + * ```js + * var foo = new Node({type: 'foo'}); + * var bar = new Node({type: 'bar'}); + * var baz = new Node({type: 'baz'}); + * foo.push(bar); + * foo.push(baz); + * + * console.log(baz.prev.type) // 'bar' + * ``` + * @return {Object} + * @api public + */ + +Object.defineProperty(Node.prototype, 'prev', { + set: function() { + throw new Error('node.prev is a getter and cannot be defined'); + }, + get: function() { + if (Array.isArray(this.siblings)) { + return this.siblings[this.index - 1] || this.parent.prev; + } + return null; + } +}); + +/** + * Get the siblings array, or `null` if it doesn't exist. + * + * ```js + * var foo = new Node({type: 'foo'}); + * var bar = new Node({type: 'bar'}); + * var baz = new Node({type: 'baz'}); + * foo.push(bar); + * foo.push(baz); + * + * console.log(bar.siblings.length) // 2 + * console.log(baz.siblings.length) // 2 + * ``` + * @return {Object} + * @api public + */ + +Object.defineProperty(Node.prototype, 'next', { + set: function() { + throw new Error('node.next is a getter and cannot be defined'); + }, + get: function() { + if (Array.isArray(this.siblings)) { + return this.siblings[this.index + 1] || this.parent.next; + } + return null; + } +}); + +/** + * Get the first node from `node.nodes`. + * + * ```js + * var foo = new Node({type: 'foo'}); + * var bar = new Node({type: 'bar'}); + * var baz = new Node({type: 'baz'}); + * var qux = new Node({type: 'qux'}); + * foo.push(bar); + * foo.push(baz); + * foo.push(qux); + * + * console.log(foo.first.type) // 'bar' + * ``` + * @return {Object} The first node, or undefiend + * @api public + */ + +Object.defineProperty(Node.prototype, 'first', { + get: function() { + return this.nodes ? this.nodes[0] : null; + } +}); + +/** + * Get the last node from `node.nodes`. + * + * ```js + * var foo = new Node({type: 'foo'}); + * var bar = new Node({type: 'bar'}); + * var baz = new Node({type: 'baz'}); + * var qux = new Node({type: 'qux'}); + * foo.push(bar); + * foo.push(baz); + * foo.push(qux); + * + * console.log(foo.last.type) // 'qux' + * ``` + * @return {Object} The last node, or undefiend + * @api public + */ + +Object.defineProperty(Node.prototype, 'last', { + get: function() { + return this.nodes ? utils.last(this.nodes) : null; + } +}); + +/** + * Get the last node from `node.nodes`. + * + * ```js + * var foo = new Node({type: 'foo'}); + * var bar = new Node({type: 'bar'}); + * var baz = new Node({type: 'baz'}); + * var qux = new Node({type: 'qux'}); + * foo.push(bar); + * foo.push(baz); + * foo.push(qux); + * + * console.log(foo.last.type) // 'qux' + * ``` + * @return {Object} The last node, or undefiend + * @api public + */ + +Object.defineProperty(Node.prototype, 'scope', { + get: function() { + if (this.isScope !== true) { + return this.parent ? this.parent.scope : this; + } + return this; + } +}); + +/** + * Get own property names from Node prototype, but only the + * first time `Node` is instantiated + */ + +function lazyKeys() { + if (!ownNames) { + ownNames = Object.getOwnPropertyNames(Node.prototype); + } +} + +/** + * Simplified assertion. Throws an error is `val` is falsey. + */ + +function assert(val, message) { + if (!val) throw new Error(message); +} + +/** + * Expose `Node` + */ + +exports = module.exports = Node; + + +/***/ }), +/* 566 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +/*! + * define-property + * + * Copyright (c) 2015, 2017, Jon Schlinkert. + * Released under the MIT License. + */ + + + +var isDescriptor = __webpack_require__(535); + +module.exports = function defineProperty(obj, prop, val) { + if (typeof obj !== 'object' && typeof obj !== 'function') { + throw new TypeError('expected an object or function.'); + } + + if (typeof prop !== 'string') { + throw new TypeError('expected `prop` to be a string.'); + } + + if (isDescriptor(val) && ('set' in val || 'get' in val)) { + return Object.defineProperty(obj, prop, val); + } + + return Object.defineProperty(obj, prop, { + configurable: true, + enumerable: false, + writable: true, + value: val + }); +}; + + +/***/ }), +/* 567 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +var typeOf = __webpack_require__(559); +var utils = module.exports; + +/** + * Returns true if the given value is a node. + * + * ```js + * var Node = require('snapdragon-node'); + * var node = new Node({type: 'foo'}); + * console.log(utils.isNode(node)); //=> true + * console.log(utils.isNode({})); //=> false + * ``` + * @param {Object} `node` Instance of [snapdragon-node][] + * @returns {Boolean} + * @api public + */ + +utils.isNode = function(node) { + return typeOf(node) === 'object' && node.isNode === true; +}; + +/** + * Emit an empty string for the given `node`. + * + * ```js + * // do nothing for beginning-of-string + * snapdragon.compiler.set('bos', utils.noop); + * ``` + * @param {Object} `node` Instance of [snapdragon-node][] + * @returns {undefined} + * @api public + */ + +utils.noop = function(node) { + append(this, '', node); +}; + +/** + * Appdend `node.val` to `compiler.output`, exactly as it was created + * by the parser. + * + * ```js + * snapdragon.compiler.set('text', utils.identity); + * ``` + * @param {Object} `node` Instance of [snapdragon-node][] + * @returns {undefined} + * @api public + */ + +utils.identity = function(node) { + append(this, node.val, node); +}; + +/** + * Previously named `.emit`, this method appends the given `val` + * to `compiler.output` for the given node. Useful when you know + * what value should be appended advance, regardless of the actual + * value of `node.val`. + * + * ```js + * snapdragon.compiler + * .set('i', function(node) { + * this.mapVisit(node); + * }) + * .set('i.open', utils.append('')) + * .set('i.close', utils.append('')) + * ``` + * @param {Object} `node` Instance of [snapdragon-node][] + * @returns {Function} Returns a compiler middleware function. + * @api public + */ + +utils.append = function(val) { + return function(node) { + append(this, val, node); + }; +}; /** * Used in compiler middleware, this onverts an AST node into @@ -65278,2835 +65649,1707 @@ utils.hasOpen = function(node) { * console.log(utils.hasClose(brace)); // true * ``` * @param {Object} `node` Instance of [snapdragon-node][] - * @return {Boolean} - * @api public - */ - -utils.hasClose = function(node) { - assert(utils.isNode(node), 'expected node to be an instance of Node'); - var last = node.last || node.nodes ? node.nodes[node.nodes.length - 1] : null; - if (utils.isNode(last)) { - return last.type === node.type + '.close'; - } - return false; -}; - -/** - * Returns true if `node.nodes` has both `.open` and `.close` nodes - * - * ```js - * var Node = require('snapdragon-node'); - * var brace = new Node({ - * type: 'brace', - * nodes: [] - * }); - * - * var open = new Node({type: 'brace.open'}); - * var close = new Node({type: 'brace.close'}); - * console.log(utils.hasOpen(brace)); // false - * console.log(utils.hasClose(brace)); // false - * - * brace.pushNode(open); - * brace.pushNode(close); - * console.log(utils.hasOpen(brace)); // true - * console.log(utils.hasClose(brace)); // true - * ``` - * @param {Object} `node` Instance of [snapdragon-node][] - * @return {Boolean} - * @api public - */ - -utils.hasOpenAndClose = function(node) { - return utils.hasOpen(node) && utils.hasClose(node); -}; - -/** - * Push the given `node` onto the `state.inside` array for the - * given type. This array is used as a specialized "stack" for - * only the given `node.type`. - * - * ```js - * var state = { inside: {}}; - * var node = new Node({type: 'brace'}); - * utils.addType(state, node); - * console.log(state.inside); - * //=> { brace: [{type: 'brace'}] } - * ``` - * @param {Object} `state` The `compiler.state` object or custom state object. - * @param {Object} `node` Instance of [snapdragon-node][] - * @return {Array} Returns the `state.inside` stack for the given type. - * @api public - */ - -utils.addType = function(state, node) { - assert(utils.isNode(node), 'expected node to be an instance of Node'); - assert(isObject(state), 'expected state to be an object'); - - var type = node.parent - ? node.parent.type - : node.type.replace(/\.open$/, ''); - - if (!state.hasOwnProperty('inside')) { - state.inside = {}; - } - if (!state.inside.hasOwnProperty(type)) { - state.inside[type] = []; - } - - var arr = state.inside[type]; - arr.push(node); - return arr; -}; - -/** - * Remove the given `node` from the `state.inside` array for the - * given type. This array is used as a specialized "stack" for - * only the given `node.type`. - * - * ```js - * var state = { inside: {}}; - * var node = new Node({type: 'brace'}); - * utils.addType(state, node); - * console.log(state.inside); - * //=> { brace: [{type: 'brace'}] } - * utils.removeType(state, node); - * //=> { brace: [] } - * ``` - * @param {Object} `state` The `compiler.state` object or custom state object. - * @param {Object} `node` Instance of [snapdragon-node][] - * @return {Array} Returns the `state.inside` stack for the given type. - * @api public - */ - -utils.removeType = function(state, node) { - assert(utils.isNode(node), 'expected node to be an instance of Node'); - assert(isObject(state), 'expected state to be an object'); - - var type = node.parent - ? node.parent.type - : node.type.replace(/\.close$/, ''); - - if (state.inside.hasOwnProperty(type)) { - return state.inside[type].pop(); - } -}; - -/** - * Returns true if `node.val` is an empty string, or `node.nodes` does - * not contain any non-empty text nodes. - * - * ```js - * var node = new Node({type: 'text'}); - * utils.isEmpty(node); //=> true - * node.val = 'foo'; - * utils.isEmpty(node); //=> false - * ``` - * @param {Object} `node` Instance of [snapdragon-node][] - * @param {Function} `fn` - * @return {Boolean} - * @api public - */ - -utils.isEmpty = function(node, fn) { - assert(utils.isNode(node), 'expected node to be an instance of Node'); - - if (!Array.isArray(node.nodes)) { - if (node.type !== 'text') { - return true; - } - if (typeof fn === 'function') { - return fn(node, node.parent); - } - return !utils.trim(node.val); - } - - for (var i = 0; i < node.nodes.length; i++) { - var child = node.nodes[i]; - if (utils.isOpen(child) || utils.isClose(child)) { - continue; - } - if (!utils.isEmpty(child, fn)) { - return false; - } - } - - return true; -}; - -/** - * Returns true if the `state.inside` stack for the given type exists - * and has one or more nodes on it. - * - * ```js - * var state = { inside: {}}; - * var node = new Node({type: 'brace'}); - * console.log(utils.isInsideType(state, 'brace')); //=> false - * utils.addType(state, node); - * console.log(utils.isInsideType(state, 'brace')); //=> true - * utils.removeType(state, node); - * console.log(utils.isInsideType(state, 'brace')); //=> false - * ``` - * @param {Object} `state` - * @param {String} `type` - * @return {Boolean} - * @api public - */ - -utils.isInsideType = function(state, type) { - assert(isObject(state), 'expected state to be an object'); - assert(isString(type), 'expected type to be a string'); - - if (!state.hasOwnProperty('inside')) { - return false; - } - - if (!state.inside.hasOwnProperty(type)) { - return false; - } - - return state.inside[type].length > 0; -}; - -/** - * Returns true if `node` is either a child or grand-child of the given `type`, - * or `state.inside[type]` is a non-empty array. - * - * ```js - * var state = { inside: {}}; - * var node = new Node({type: 'brace'}); - * var open = new Node({type: 'brace.open'}); - * console.log(utils.isInside(state, open, 'brace')); //=> false - * utils.pushNode(node, open); - * console.log(utils.isInside(state, open, 'brace')); //=> true - * ``` - * @param {Object} `state` Either the `compiler.state` object, if it exists, or a user-supplied state object. - * @param {Object} `node` Instance of [snapdragon-node][] - * @param {String} `type` The `node.type` to check for. - * @return {Boolean} - * @api public - */ - -utils.isInside = function(state, node, type) { - assert(utils.isNode(node), 'expected node to be an instance of Node'); - assert(isObject(state), 'expected state to be an object'); - - if (Array.isArray(type)) { - for (var i = 0; i < type.length; i++) { - if (utils.isInside(state, node, type[i])) { - return true; - } - } - return false; - } - - var parent = node.parent; - if (typeof type === 'string') { - return (parent && parent.type === type) || utils.isInsideType(state, type); - } - - if (typeOf(type) === 'regexp') { - if (parent && parent.type && type.test(parent.type)) { - return true; - } - - var keys = Object.keys(state.inside); - var len = keys.length; - var idx = -1; - while (++idx < len) { - var key = keys[idx]; - var val = state.inside[key]; - - if (Array.isArray(val) && val.length !== 0 && type.test(key)) { - return true; - } - } - } - return false; -}; - -/** - * Get the last `n` element from the given `array`. Used for getting - * a node from `node.nodes.` - * - * @param {Array} `array` - * @param {Number} `n` - * @return {undefined} - * @api public - */ - -utils.last = function(arr, n) { - return arr[arr.length - (n || 1)]; -}; - -/** - * Cast the given `val` to an array. - * - * ```js - * console.log(utils.arrayify('')); - * //=> [] - * console.log(utils.arrayify('foo')); - * //=> ['foo'] - * console.log(utils.arrayify(['foo'])); - * //=> ['foo'] - * ``` - * @param {any} `val` - * @return {Array} - * @api public - */ - -utils.arrayify = function(val) { - if (typeof val === 'string' && val !== '') { - return [val]; - } - if (!Array.isArray(val)) { - return []; - } - return val; -}; - -/** - * Convert the given `val` to a string by joining with `,`. Useful - * for creating a cheerio/CSS/DOM-style selector from a list of strings. - * - * @param {any} `val` - * @return {Array} - * @api public - */ - -utils.stringify = function(val) { - return utils.arrayify(val).join(','); -}; - -/** - * Ensure that the given value is a string and call `.trim()` on it, - * or return an empty string. - * - * @param {String} `str` - * @return {String} - * @api public - */ - -utils.trim = function(str) { - return typeof str === 'string' ? str.trim() : ''; -}; - -/** - * Return true if val is an object - */ - -function isObject(val) { - return typeOf(val) === 'object'; -} - -/** - * Return true if val is a string - */ - -function isString(val) { - return typeof val === 'string'; -} - -/** - * Return true if val is a function - */ - -function isFunction(val) { - return typeof val === 'function'; -} - -/** - * Return true if val is an array - */ - -function isArray(val) { - return Array.isArray(val); -} - -/** - * Shim to ensure the `.append` methods work with any version of snapdragon - */ - -function append(compiler, val, node) { - if (typeof compiler.append !== 'function') { - return compiler.emit(val, node); - } - return compiler.append(val, node); -} - -/** - * Simplified assertion. Throws an error is `val` is falsey. - */ - -function assert(val, message) { - if (!val) throw new Error(message); -} - - -/***/ }), -/* 565 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -var extend = __webpack_require__(532); -var Snapdragon = __webpack_require__(566); -var compilers = __webpack_require__(538); -var parsers = __webpack_require__(555); -var utils = __webpack_require__(539); - -/** - * Customize Snapdragon parser and renderer - */ - -function Braces(options) { - this.options = extend({}, options); -} - -/** - * Initialize braces - */ - -Braces.prototype.init = function(options) { - if (this.isInitialized) return; - this.isInitialized = true; - var opts = utils.createOptions({}, this.options, options); - this.snapdragon = this.options.snapdragon || new Snapdragon(opts); - this.compiler = this.snapdragon.compiler; - this.parser = this.snapdragon.parser; - - compilers(this.snapdragon, opts); - parsers(this.snapdragon, opts); - - /** - * Call Snapdragon `.parse` method. When AST is returned, we check to - * see if any unclosed braces are left on the stack and, if so, we iterate - * over the stack and correct the AST so that compilers are called in the correct - * order and unbalance braces are properly escaped. - */ - - utils.define(this.snapdragon, 'parse', function(pattern, options) { - var parsed = Snapdragon.prototype.parse.apply(this, arguments); - this.parser.ast.input = pattern; - - var stack = this.parser.stack; - while (stack.length) { - addParent({type: 'brace.close', val: ''}, stack.pop()); - } - - function addParent(node, parent) { - utils.define(node, 'parent', parent); - parent.nodes.push(node); - } - - // add non-enumerable parser reference - utils.define(parsed, 'parser', this.parser); - return parsed; - }); -}; - -/** - * Decorate `.parse` method - */ - -Braces.prototype.parse = function(ast, options) { - if (ast && typeof ast === 'object' && ast.nodes) return ast; - this.init(options); - return this.snapdragon.parse(ast, options); -}; - -/** - * Decorate `.compile` method - */ - -Braces.prototype.compile = function(ast, options) { - if (typeof ast === 'string') { - ast = this.parse(ast, options); - } else { - this.init(options); - } - return this.snapdragon.compile(ast, options); -}; - -/** - * Expand - */ - -Braces.prototype.expand = function(pattern) { - var ast = this.parse(pattern, {expand: true}); - return this.compile(ast, {expand: true}); -}; - -/** - * Optimize - */ - -Braces.prototype.optimize = function(pattern) { - var ast = this.parse(pattern, {optimize: true}); - return this.compile(ast, {optimize: true}); -}; - -/** - * Expose `Braces` - */ - -module.exports = Braces; - - -/***/ }), -/* 566 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -var Base = __webpack_require__(567); -var define = __webpack_require__(593); -var Compiler = __webpack_require__(603); -var Parser = __webpack_require__(632); -var utils = __webpack_require__(612); -var regexCache = {}; -var cache = {}; - -/** - * Create a new instance of `Snapdragon` with the given `options`. - * - * ```js - * var snapdragon = new Snapdragon(); - * ``` - * - * @param {Object} `options` - * @api public - */ - -function Snapdragon(options) { - Base.call(this, null, options); - this.options = utils.extend({source: 'string'}, this.options); - this.compiler = new Compiler(this.options); - this.parser = new Parser(this.options); - - Object.defineProperty(this, 'compilers', { - get: function() { - return this.compiler.compilers; - } - }); - - Object.defineProperty(this, 'parsers', { - get: function() { - return this.parser.parsers; - } - }); - - Object.defineProperty(this, 'regex', { - get: function() { - return this.parser.regex; - } - }); -} - -/** - * Inherit Base - */ - -Base.extend(Snapdragon); - -/** - * Add a parser to `snapdragon.parsers` for capturing the given `type` using - * the specified regex or parser function. A function is useful if you need - * to customize how the token is created and/or have access to the parser - * instance to check options, etc. - * - * ```js - * snapdragon - * .capture('slash', /^\//) - * .capture('dot', function() { - * var pos = this.position(); - * var m = this.match(/^\./); - * if (!m) return; - * return pos({ - * type: 'dot', - * val: m[0] - * }); - * }); - * ``` - * @param {String} `type` - * @param {RegExp|Function} `regex` - * @return {Object} Returns the parser instance for chaining - * @api public - */ - -Snapdragon.prototype.capture = function() { - return this.parser.capture.apply(this.parser, arguments); -}; - -/** - * Register a plugin `fn`. - * - * ```js - * var snapdragon = new Snapdgragon([options]); - * snapdragon.use(function() { - * console.log(this); //<= snapdragon instance - * console.log(this.parser); //<= parser instance - * console.log(this.compiler); //<= compiler instance - * }); - * ``` - * @param {Object} `fn` - * @api public - */ - -Snapdragon.prototype.use = function(fn) { - fn.call(this, this); - return this; -}; - -/** - * Parse the given `str`. - * - * ```js - * var snapdragon = new Snapdgragon([options]); - * // register parsers - * snapdragon.parser.use(function() {}); - * - * // parse - * var ast = snapdragon.parse('foo/bar'); - * console.log(ast); - * ``` - * @param {String} `str` - * @param {Object} `options` Set `options.sourcemap` to true to enable source maps. - * @return {Object} Returns an AST. - * @api public - */ - -Snapdragon.prototype.parse = function(str, options) { - this.options = utils.extend({}, this.options, options); - var parsed = this.parser.parse(str, this.options); - - // add non-enumerable parser reference - define(parsed, 'parser', this.parser); - return parsed; -}; - -/** - * Compile the given `AST`. - * - * ```js - * var snapdragon = new Snapdgragon([options]); - * // register plugins - * snapdragon.use(function() {}); - * // register parser plugins - * snapdragon.parser.use(function() {}); - * // register compiler plugins - * snapdragon.compiler.use(function() {}); - * - * // parse - * var ast = snapdragon.parse('foo/bar'); - * - * // compile - * var res = snapdragon.compile(ast); - * console.log(res.output); - * ``` - * @param {Object} `ast` - * @param {Object} `options` - * @return {Object} Returns an object with an `output` property with the rendered string. - * @api public - */ - -Snapdragon.prototype.compile = function(ast, options) { - this.options = utils.extend({}, this.options, options); - var compiled = this.compiler.compile(ast, this.options); - - // add non-enumerable compiler reference - define(compiled, 'compiler', this.compiler); - return compiled; -}; - -/** - * Expose `Snapdragon` - */ - -module.exports = Snapdragon; - -/** - * Expose `Parser` and `Compiler` - */ - -module.exports.Compiler = Compiler; -module.exports.Parser = Parser; - - -/***/ }), -/* 567 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -var util = __webpack_require__(111); -var define = __webpack_require__(568); -var CacheBase = __webpack_require__(569); -var Emitter = __webpack_require__(570); -var isObject = __webpack_require__(544); -var merge = __webpack_require__(587); -var pascal = __webpack_require__(590); -var cu = __webpack_require__(591); - -/** - * Optionally define a custom `cache` namespace to use. - */ - -function namespace(name) { - var Cache = name ? CacheBase.namespace(name) : CacheBase; - var fns = []; - - /** - * Create an instance of `Base` with the given `config` and `options`. - * - * ```js - * // initialize with `config` and `options` - * var app = new Base({isApp: true}, {abc: true}); - * app.set('foo', 'bar'); - * - * // values defined with the given `config` object will be on the root of the instance - * console.log(app.baz); //=> undefined - * console.log(app.foo); //=> 'bar' - * // or use `.get` - * console.log(app.get('isApp')); //=> true - * console.log(app.get('foo')); //=> 'bar' - * - * // values defined with the given `options` object will be on `app.options - * console.log(app.options.abc); //=> true - * ``` - * - * @param {Object} `config` If supplied, this object is passed to [cache-base][] to merge onto the the instance upon instantiation. - * @param {Object} `options` If supplied, this object is used to initialize the `base.options` object. - * @api public - */ - - function Base(config, options) { - if (!(this instanceof Base)) { - return new Base(config, options); - } - Cache.call(this, config); - this.is('base'); - this.initBase(config, options); - } - - /** - * Inherit cache-base - */ - - util.inherits(Base, Cache); - - /** - * Add static emitter methods - */ - - Emitter(Base); - - /** - * Initialize `Base` defaults with the given `config` object - */ - - Base.prototype.initBase = function(config, options) { - this.options = merge({}, this.options, options); - this.cache = this.cache || {}; - this.define('registered', {}); - if (name) this[name] = {}; - - // make `app._callbacks` non-enumerable - this.define('_callbacks', this._callbacks); - if (isObject(config)) { - this.visit('set', config); - } - Base.run(this, 'use', fns); - }; - - /** - * Set the given `name` on `app._name` and `app.is*` properties. Used for doing - * lookups in plugins. - * - * ```js - * app.is('foo'); - * console.log(app._name); - * //=> 'foo' - * console.log(app.isFoo); - * //=> true - * app.is('bar'); - * console.log(app.isFoo); - * //=> true - * console.log(app.isBar); - * //=> true - * console.log(app._name); - * //=> 'bar' - * ``` - * @name .is - * @param {String} `name` - * @return {Boolean} - * @api public - */ - - Base.prototype.is = function(name) { - if (typeof name !== 'string') { - throw new TypeError('expected name to be a string'); - } - this.define('is' + pascal(name), true); - this.define('_name', name); - this.define('_appname', name); - return this; - }; - - /** - * Returns true if a plugin has already been registered on an instance. - * - * Plugin implementors are encouraged to use this first thing in a plugin - * to prevent the plugin from being called more than once on the same - * instance. - * - * ```js - * var base = new Base(); - * base.use(function(app) { - * if (app.isRegistered('myPlugin')) return; - * // do stuff to `app` - * }); - * - * // to also record the plugin as being registered - * base.use(function(app) { - * if (app.isRegistered('myPlugin', true)) return; - * // do stuff to `app` - * }); - * ``` - * @name .isRegistered - * @emits `plugin` Emits the name of the plugin being registered. Useful for unit tests, to ensure plugins are only registered once. - * @param {String} `name` The plugin name. - * @param {Boolean} `register` If the plugin if not already registered, to record it as being registered pass `true` as the second argument. - * @return {Boolean} Returns true if a plugin is already registered. - * @api public - */ - - Base.prototype.isRegistered = function(name, register) { - if (this.registered.hasOwnProperty(name)) { - return true; - } - if (register !== false) { - this.registered[name] = true; - this.emit('plugin', name); - } - return false; - }; - - /** - * Define a plugin function to be called immediately upon init. Plugins are chainable - * and expose the following arguments to the plugin function: - * - * - `app`: the current instance of `Base` - * - `base`: the [first ancestor instance](#base) of `Base` - * - * ```js - * var app = new Base() - * .use(foo) - * .use(bar) - * .use(baz) - * ``` - * @name .use - * @param {Function} `fn` plugin function to call - * @return {Object} Returns the item instance for chaining. - * @api public - */ - - Base.prototype.use = function(fn) { - fn.call(this, this); - return this; - }; - - /** - * The `.define` method is used for adding non-enumerable property on the instance. - * Dot-notation is **not supported** with `define`. - * - * ```js - * // arbitrary `render` function using lodash `template` - * app.define('render', function(str, locals) { - * return _.template(str)(locals); - * }); - * ``` - * @name .define - * @param {String} `key` The name of the property to define. - * @param {any} `value` - * @return {Object} Returns the instance for chaining. - * @api public - */ - - Base.prototype.define = function(key, val) { - if (isObject(key)) { - return this.visit('define', key); - } - define(this, key, val); - return this; - }; - - /** - * Mix property `key` onto the Base prototype. If base is inherited using - * `Base.extend` this method will be overridden by a new `mixin` method that will - * only add properties to the prototype of the inheriting application. - * - * ```js - * app.mixin('foo', function() { - * // do stuff - * }); - * ``` - * @name .mixin - * @param {String} `key` - * @param {Object|Array} `val` - * @return {Object} Returns the `base` instance for chaining. - * @api public - */ - - Base.prototype.mixin = function(key, val) { - Base.prototype[key] = val; - return this; - }; - - /** - * Non-enumberable mixin array, used by the static [Base.mixin]() method. - */ - - Base.prototype.mixins = Base.prototype.mixins || []; - - /** - * Getter/setter used when creating nested instances of `Base`, for storing a reference - * to the first ancestor instance. This works by setting an instance of `Base` on the `parent` - * property of a "child" instance. The `base` property defaults to the current instance if - * no `parent` property is defined. - * - * ```js - * // create an instance of `Base`, this is our first ("base") instance - * var first = new Base(); - * first.foo = 'bar'; // arbitrary property, to make it easier to see what's happening later - * - * // create another instance - * var second = new Base(); - * // create a reference to the first instance (`first`) - * second.parent = first; - * - * // create another instance - * var third = new Base(); - * // create a reference to the previous instance (`second`) - * // repeat this pattern every time a "child" instance is created - * third.parent = second; - * - * // we can always access the first instance using the `base` property - * console.log(first.base.foo); - * //=> 'bar' - * console.log(second.base.foo); - * //=> 'bar' - * console.log(third.base.foo); - * //=> 'bar' - * // and now you know how to get to third base ;) - * ``` - * @name .base - * @api public - */ - - Object.defineProperty(Base.prototype, 'base', { - configurable: true, - get: function() { - return this.parent ? this.parent.base : this; - } - }); - - /** - * Static method for adding global plugin functions that will - * be added to an instance when created. - * - * ```js - * Base.use(function(app) { - * app.foo = 'bar'; - * }); - * var app = new Base(); - * console.log(app.foo); - * //=> 'bar' - * ``` - * @name #use - * @param {Function} `fn` Plugin function to use on each instance. - * @return {Object} Returns the `Base` constructor for chaining - * @api public - */ - - define(Base, 'use', function(fn) { - fns.push(fn); - return Base; - }); - - /** - * Run an array of functions by passing each function - * to a method on the given object specified by the given property. - * - * @param {Object} `obj` Object containing method to use. - * @param {String} `prop` Name of the method on the object to use. - * @param {Array} `arr` Array of functions to pass to the method. - */ - - define(Base, 'run', function(obj, prop, arr) { - var len = arr.length, i = 0; - while (len--) { - obj[prop](arr[i++]); - } - return Base; - }); - - /** - * Static method for inheriting the prototype and static methods of the `Base` class. - * This method greatly simplifies the process of creating inheritance-based applications. - * See [static-extend][] for more details. - * - * ```js - * var extend = cu.extend(Parent); - * Parent.extend(Child); - * - * // optional methods - * Parent.extend(Child, { - * foo: function() {}, - * bar: function() {} - * }); - * ``` - * @name #extend - * @param {Function} `Ctor` constructor to extend - * @param {Object} `methods` Optional prototype properties to mix in. - * @return {Object} Returns the `Base` constructor for chaining - * @api public - */ - - define(Base, 'extend', cu.extend(Base, function(Ctor, Parent) { - Ctor.prototype.mixins = Ctor.prototype.mixins || []; - - define(Ctor, 'mixin', function(fn) { - var mixin = fn(Ctor.prototype, Ctor); - if (typeof mixin === 'function') { - Ctor.prototype.mixins.push(mixin); - } - return Ctor; - }); - - define(Ctor, 'mixins', function(Child) { - Base.run(Child, 'mixin', Ctor.prototype.mixins); - return Ctor; - }); - - Ctor.prototype.mixin = function(key, value) { - Ctor.prototype[key] = value; - return this; - }; - return Base; - })); - - /** - * Used for adding methods to the `Base` prototype, and/or to the prototype of child instances. - * When a mixin function returns a function, the returned function is pushed onto the `.mixins` - * array, making it available to be used on inheriting classes whenever `Base.mixins()` is - * called (e.g. `Base.mixins(Child)`). - * - * ```js - * Base.mixin(function(proto) { - * proto.foo = function(msg) { - * return 'foo ' + msg; - * }; - * }); - * ``` - * @name #mixin - * @param {Function} `fn` Function to call - * @return {Object} Returns the `Base` constructor for chaining - * @api public - */ - - define(Base, 'mixin', function(fn) { - var mixin = fn(Base.prototype, Base); - if (typeof mixin === 'function') { - Base.prototype.mixins.push(mixin); - } - return Base; - }); - - /** - * Static method for running global mixin functions against a child constructor. - * Mixins must be registered before calling this method. - * - * ```js - * Base.extend(Child); - * Base.mixins(Child); - * ``` - * @name #mixins - * @param {Function} `Child` Constructor function of a child class - * @return {Object} Returns the `Base` constructor for chaining - * @api public - */ - - define(Base, 'mixins', function(Child) { - Base.run(Child, 'mixin', Base.prototype.mixins); - return Base; - }); - - /** - * Similar to `util.inherit`, but copies all static properties, prototype properties, and - * getters/setters from `Provider` to `Receiver`. See [class-utils][]{#inherit} for more details. - * - * ```js - * Base.inherit(Foo, Bar); - * ``` - * @name #inherit - * @param {Function} `Receiver` Receiving (child) constructor - * @param {Function} `Provider` Providing (parent) constructor - * @return {Object} Returns the `Base` constructor for chaining - * @api public - */ - - define(Base, 'inherit', cu.inherit); - define(Base, 'bubble', cu.bubble); - return Base; -} - -/** - * Expose `Base` with default settings - */ - -module.exports = namespace(); - -/** - * Allow users to define a namespace - */ - -module.exports.namespace = namespace; - - -/***/ }), -/* 568 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; -/*! - * define-property - * - * Copyright (c) 2015, 2017, Jon Schlinkert. - * Released under the MIT License. - */ - - - -var isDescriptor = __webpack_require__(558); - -module.exports = function defineProperty(obj, prop, val) { - if (typeof obj !== 'object' && typeof obj !== 'function') { - throw new TypeError('expected an object or function.'); - } - - if (typeof prop !== 'string') { - throw new TypeError('expected `prop` to be a string.'); - } - - if (isDescriptor(val) && ('set' in val || 'get' in val)) { - return Object.defineProperty(obj, prop, val); - } - - return Object.defineProperty(obj, prop, { - configurable: true, - enumerable: false, - writable: true, - value: val - }); -}; - - -/***/ }), -/* 569 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -var isObject = __webpack_require__(544); -var Emitter = __webpack_require__(570); -var visit = __webpack_require__(571); -var toPath = __webpack_require__(574); -var union = __webpack_require__(575); -var del = __webpack_require__(579); -var get = __webpack_require__(577); -var has = __webpack_require__(584); -var set = __webpack_require__(578); - -/** - * Create a `Cache` constructor that when instantiated will - * store values on the given `prop`. - * - * ```js - * var Cache = require('cache-base').namespace('data'); - * var cache = new Cache(); - * - * cache.set('foo', 'bar'); - * //=> {data: {foo: 'bar'}} - * ``` - * @param {String} `prop` The property name to use for storing values. - * @return {Function} Returns a custom `Cache` constructor - * @api public - */ - -function namespace(prop) { - - /** - * Create a new `Cache`. Internally the `Cache` constructor is created using - * the `namespace` function, with `cache` defined as the storage object. - * - * ```js - * var app = new Cache(); - * ``` - * @param {Object} `cache` Optionally pass an object to initialize with. - * @constructor - * @api public - */ - - function Cache(cache) { - if (prop) { - this[prop] = {}; - } - if (cache) { - this.set(cache); - } - } - - /** - * Inherit Emitter - */ - - Emitter(Cache.prototype); - - /** - * Assign `value` to `key`. Also emits `set` with - * the key and value. - * - * ```js - * app.on('set', function(key, val) { - * // do something when `set` is emitted - * }); - * - * app.set(key, value); - * - * // also takes an object or array - * app.set({name: 'Halle'}); - * app.set([{foo: 'bar'}, {baz: 'quux'}]); - * console.log(app); - * //=> {name: 'Halle', foo: 'bar', baz: 'quux'} - * ``` - * - * @name .set - * @emits `set` with `key` and `value` as arguments. - * @param {String} `key` - * @param {any} `value` - * @return {Object} Returns the instance for chaining. - * @api public - */ - - Cache.prototype.set = function(key, val) { - if (Array.isArray(key) && arguments.length === 2) { - key = toPath(key); - } - if (isObject(key) || Array.isArray(key)) { - this.visit('set', key); - } else { - set(prop ? this[prop] : this, key, val); - this.emit('set', key, val); - } - return this; - }; - - /** - * Union `array` to `key`. Also emits `set` with - * the key and value. - * - * ```js - * app.union('a.b', ['foo']); - * app.union('a.b', ['bar']); - * console.log(app.get('a')); - * //=> {b: ['foo', 'bar']} - * ``` - * @name .union - * @param {String} `key` - * @param {any} `value` - * @return {Object} Returns the instance for chaining. - * @api public - */ - - Cache.prototype.union = function(key, val) { - if (Array.isArray(key) && arguments.length === 2) { - key = toPath(key); - } - var ctx = prop ? this[prop] : this; - union(ctx, key, arrayify(val)); - this.emit('union', val); - return this; - }; - - /** - * Return the value of `key`. Dot notation may be used - * to get [nested property values][get-value]. - * - * ```js - * app.set('a.b.c', 'd'); - * app.get('a.b'); - * //=> {c: 'd'} - * - * app.get(['a', 'b']); - * //=> {c: 'd'} - * ``` - * - * @name .get - * @emits `get` with `key` and `value` as arguments. - * @param {String} `key` The name of the property to get. Dot-notation may be used. - * @return {any} Returns the value of `key` - * @api public - */ - - Cache.prototype.get = function(key) { - key = toPath(arguments); - - var ctx = prop ? this[prop] : this; - var val = get(ctx, key); - - this.emit('get', key, val); - return val; - }; - - /** - * Return true if app has a stored value for `key`, - * false only if value is `undefined`. - * - * ```js - * app.set('foo', 'bar'); - * app.has('foo'); - * //=> true - * ``` - * - * @name .has - * @emits `has` with `key` and true or false as arguments. - * @param {String} `key` - * @return {Boolean} - * @api public - */ - - Cache.prototype.has = function(key) { - key = toPath(arguments); - - var ctx = prop ? this[prop] : this; - var val = get(ctx, key); - - var has = typeof val !== 'undefined'; - this.emit('has', key, has); - return has; - }; - - /** - * Delete one or more properties from the instance. - * - * ```js - * app.del(); // delete all - * // or - * app.del('foo'); - * // or - * app.del(['foo', 'bar']); - * ``` - * @name .del - * @emits `del` with the `key` as the only argument. - * @param {String|Array} `key` Property name or array of property names. - * @return {Object} Returns the instance for chaining. - * @api public - */ - - Cache.prototype.del = function(key) { - if (Array.isArray(key)) { - this.visit('del', key); - } else { - del(prop ? this[prop] : this, key); - this.emit('del', key); - } - return this; - }; - - /** - * Reset the entire cache to an empty object. - * - * ```js - * app.clear(); - * ``` - * @api public - */ - - Cache.prototype.clear = function() { - if (prop) { - this[prop] = {}; - } - }; - - /** - * Visit `method` over the properties in the given object, or map - * visit over the object-elements in an array. - * - * @name .visit - * @param {String} `method` The name of the `base` method to call. - * @param {Object|Array} `val` The object or array to iterate over. - * @return {Object} Returns the instance for chaining. - * @api public - */ - - Cache.prototype.visit = function(method, val) { - visit(this, method, val); - return this; - }; - - return Cache; -} - -/** - * Cast val to an array - */ - -function arrayify(val) { - return val ? (Array.isArray(val) ? val : [val]) : []; -} - -/** - * Expose `Cache` - */ - -module.exports = namespace(); - -/** - * Expose `Cache.namespace` - */ - -module.exports.namespace = namespace; - - -/***/ }), -/* 570 */ -/***/ (function(module, exports, __webpack_require__) { - - -/** - * Expose `Emitter`. - */ - -if (true) { - module.exports = Emitter; -} - -/** - * Initialize a new `Emitter`. - * - * @api public - */ - -function Emitter(obj) { - if (obj) return mixin(obj); -}; - -/** - * Mixin the emitter properties. - * - * @param {Object} obj - * @return {Object} - * @api private - */ - -function mixin(obj) { - for (var key in Emitter.prototype) { - obj[key] = Emitter.prototype[key]; - } - return obj; -} - -/** - * Listen on the given `event` with `fn`. - * - * @param {String} event - * @param {Function} fn - * @return {Emitter} - * @api public - */ - -Emitter.prototype.on = -Emitter.prototype.addEventListener = function(event, fn){ - this._callbacks = this._callbacks || {}; - (this._callbacks['$' + event] = this._callbacks['$' + event] || []) - .push(fn); - return this; -}; - -/** - * Adds an `event` listener that will be invoked a single - * time then automatically removed. - * - * @param {String} event - * @param {Function} fn - * @return {Emitter} - * @api public - */ - -Emitter.prototype.once = function(event, fn){ - function on() { - this.off(event, on); - fn.apply(this, arguments); - } - - on.fn = fn; - this.on(event, on); - return this; -}; - -/** - * Remove the given callback for `event` or all - * registered callbacks. - * - * @param {String} event - * @param {Function} fn - * @return {Emitter} - * @api public - */ - -Emitter.prototype.off = -Emitter.prototype.removeListener = -Emitter.prototype.removeAllListeners = -Emitter.prototype.removeEventListener = function(event, fn){ - this._callbacks = this._callbacks || {}; - - // all - if (0 == arguments.length) { - this._callbacks = {}; - return this; - } - - // specific event - var callbacks = this._callbacks['$' + event]; - if (!callbacks) return this; - - // remove all handlers - if (1 == arguments.length) { - delete this._callbacks['$' + event]; - return this; - } - - // remove specific handler - var cb; - for (var i = 0; i < callbacks.length; i++) { - cb = callbacks[i]; - if (cb === fn || cb.fn === fn) { - callbacks.splice(i, 1); - break; - } - } - return this; -}; - -/** - * Emit `event` with the given args. - * - * @param {String} event - * @param {Mixed} ... - * @return {Emitter} - */ - -Emitter.prototype.emit = function(event){ - this._callbacks = this._callbacks || {}; - var args = [].slice.call(arguments, 1) - , callbacks = this._callbacks['$' + event]; - - if (callbacks) { - callbacks = callbacks.slice(0); - for (var i = 0, len = callbacks.length; i < len; ++i) { - callbacks[i].apply(this, args); - } - } - - return this; -}; - -/** - * Return array of callbacks for `event`. - * - * @param {String} event - * @return {Array} - * @api public - */ - -Emitter.prototype.listeners = function(event){ - this._callbacks = this._callbacks || {}; - return this._callbacks['$' + event] || []; -}; - -/** - * Check if this emitter has `event` handlers. - * - * @param {String} event - * @return {Boolean} - * @api public - */ - -Emitter.prototype.hasListeners = function(event){ - return !! this.listeners(event).length; -}; - - -/***/ }), -/* 571 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; -/*! - * collection-visit - * - * Copyright (c) 2015, 2017, Jon Schlinkert. - * Released under the MIT License. + * @return {Boolean} + * @api public */ - - -var visit = __webpack_require__(572); -var mapVisit = __webpack_require__(573); - -module.exports = function(collection, method, val) { - var result; - - if (typeof val === 'string' && (method in collection)) { - var args = [].slice.call(arguments, 2); - result = collection[method].apply(collection, args); - } else if (Array.isArray(val)) { - result = mapVisit.apply(null, arguments); - } else { - result = visit.apply(null, arguments); - } - - if (typeof result !== 'undefined') { - return result; +utils.hasClose = function(node) { + assert(utils.isNode(node), 'expected node to be an instance of Node'); + var last = node.last || node.nodes ? node.nodes[node.nodes.length - 1] : null; + if (utils.isNode(last)) { + return last.type === node.type + '.close'; } - - return collection; + return false; }; - -/***/ }), -/* 572 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; -/*! - * object-visit +/** + * Returns true if `node.nodes` has both `.open` and `.close` nodes * - * Copyright (c) 2015, 2017, Jon Schlinkert. - * Released under the MIT License. + * ```js + * var Node = require('snapdragon-node'); + * var brace = new Node({ + * type: 'brace', + * nodes: [] + * }); + * + * var open = new Node({type: 'brace.open'}); + * var close = new Node({type: 'brace.close'}); + * console.log(utils.hasOpen(brace)); // false + * console.log(utils.hasClose(brace)); // false + * + * brace.pushNode(open); + * brace.pushNode(close); + * console.log(utils.hasOpen(brace)); // true + * console.log(utils.hasClose(brace)); // true + * ``` + * @param {Object} `node` Instance of [snapdragon-node][] + * @return {Boolean} + * @api public */ +utils.hasOpenAndClose = function(node) { + return utils.hasOpen(node) && utils.hasClose(node); +}; +/** + * Push the given `node` onto the `state.inside` array for the + * given type. This array is used as a specialized "stack" for + * only the given `node.type`. + * + * ```js + * var state = { inside: {}}; + * var node = new Node({type: 'brace'}); + * utils.addType(state, node); + * console.log(state.inside); + * //=> { brace: [{type: 'brace'}] } + * ``` + * @param {Object} `state` The `compiler.state` object or custom state object. + * @param {Object} `node` Instance of [snapdragon-node][] + * @return {Array} Returns the `state.inside` stack for the given type. + * @api public + */ -var isObject = __webpack_require__(544); +utils.addType = function(state, node) { + assert(utils.isNode(node), 'expected node to be an instance of Node'); + assert(isObject(state), 'expected state to be an object'); -module.exports = function visit(thisArg, method, target, val) { - if (!isObject(thisArg) && typeof thisArg !== 'function') { - throw new Error('object-visit expects `thisArg` to be an object.'); - } + var type = node.parent + ? node.parent.type + : node.type.replace(/\.open$/, ''); - if (typeof method !== 'string') { - throw new Error('object-visit expects `method` name to be a string'); + if (!state.hasOwnProperty('inside')) { + state.inside = {}; } - - if (typeof thisArg[method] !== 'function') { - return thisArg; + if (!state.inside.hasOwnProperty(type)) { + state.inside[type] = []; } - var args = [].slice.call(arguments, 3); - target = target || {}; - - for (var key in target) { - var arr = [key, target[key]].concat(args); - thisArg[method].apply(thisArg, arr); - } - return thisArg; + var arr = state.inside[type]; + arr.push(node); + return arr; }; - -/***/ }), -/* 573 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -var util = __webpack_require__(111); -var visit = __webpack_require__(572); - /** - * Map `visit` over an array of objects. + * Remove the given `node` from the `state.inside` array for the + * given type. This array is used as a specialized "stack" for + * only the given `node.type`. * - * @param {Object} `collection` The context in which to invoke `method` - * @param {String} `method` Name of the method to call on `collection` - * @param {Object} `arr` Array of objects. + * ```js + * var state = { inside: {}}; + * var node = new Node({type: 'brace'}); + * utils.addType(state, node); + * console.log(state.inside); + * //=> { brace: [{type: 'brace'}] } + * utils.removeType(state, node); + * //=> { brace: [] } + * ``` + * @param {Object} `state` The `compiler.state` object or custom state object. + * @param {Object} `node` Instance of [snapdragon-node][] + * @return {Array} Returns the `state.inside` stack for the given type. + * @api public */ -module.exports = function mapVisit(collection, method, val) { - if (isObject(val)) { - return visit.apply(null, arguments); - } - - if (!Array.isArray(val)) { - throw new TypeError('expected an array: ' + util.inspect(val)); - } +utils.removeType = function(state, node) { + assert(utils.isNode(node), 'expected node to be an instance of Node'); + assert(isObject(state), 'expected state to be an object'); - var args = [].slice.call(arguments, 3); + var type = node.parent + ? node.parent.type + : node.type.replace(/\.close$/, ''); - for (var i = 0; i < val.length; i++) { - var ele = val[i]; - if (isObject(ele)) { - visit.apply(null, [collection, method, ele].concat(args)); - } else { - collection[method].apply(collection, [ele].concat(args)); - } + if (state.inside.hasOwnProperty(type)) { + return state.inside[type].pop(); } }; -function isObject(val) { - return val && (typeof val === 'function' || (!Array.isArray(val) && typeof val === 'object')); -} - - -/***/ }), -/* 574 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; -/*! - * to-object-path +/** + * Returns true if `node.val` is an empty string, or `node.nodes` does + * not contain any non-empty text nodes. * - * Copyright (c) 2015, Jon Schlinkert. - * Licensed under the MIT License. + * ```js + * var node = new Node({type: 'text'}); + * utils.isEmpty(node); //=> true + * node.val = 'foo'; + * utils.isEmpty(node); //=> false + * ``` + * @param {Object} `node` Instance of [snapdragon-node][] + * @param {Function} `fn` + * @return {Boolean} + * @api public */ +utils.isEmpty = function(node, fn) { + assert(utils.isNode(node), 'expected node to be an instance of Node'); - -var typeOf = __webpack_require__(549); - -module.exports = function toPath(args) { - if (typeOf(args) !== 'arguments') { - args = arguments; + if (!Array.isArray(node.nodes)) { + if (node.type !== 'text') { + return true; + } + if (typeof fn === 'function') { + return fn(node, node.parent); + } + return !utils.trim(node.val); } - return filter(args).join('.'); -}; - -function filter(arr) { - var len = arr.length; - var idx = -1; - var res = []; - while (++idx < len) { - var ele = arr[idx]; - if (typeOf(ele) === 'arguments' || Array.isArray(ele)) { - res.push.apply(res, filter(ele)); - } else if (typeof ele === 'string') { - res.push(ele); + for (var i = 0; i < node.nodes.length; i++) { + var child = node.nodes[i]; + if (utils.isOpen(child) || utils.isClose(child)) { + continue; + } + if (!utils.isEmpty(child, fn)) { + return false; } } - return res; -} - - -/***/ }), -/* 575 */ -/***/ (function(module, exports, __webpack_require__) { -"use strict"; + return true; +}; +/** + * Returns true if the `state.inside` stack for the given type exists + * and has one or more nodes on it. + * + * ```js + * var state = { inside: {}}; + * var node = new Node({type: 'brace'}); + * console.log(utils.isInsideType(state, 'brace')); //=> false + * utils.addType(state, node); + * console.log(utils.isInsideType(state, 'brace')); //=> true + * utils.removeType(state, node); + * console.log(utils.isInsideType(state, 'brace')); //=> false + * ``` + * @param {Object} `state` + * @param {String} `type` + * @return {Boolean} + * @api public + */ -var isObject = __webpack_require__(536); -var union = __webpack_require__(576); -var get = __webpack_require__(577); -var set = __webpack_require__(578); +utils.isInsideType = function(state, type) { + assert(isObject(state), 'expected state to be an object'); + assert(isString(type), 'expected type to be a string'); -module.exports = function unionValue(obj, prop, value) { - if (!isObject(obj)) { - throw new TypeError('union-value expects the first argument to be an object.'); + if (!state.hasOwnProperty('inside')) { + return false; } - if (typeof prop !== 'string') { - throw new TypeError('union-value expects `prop` to be a string.'); + if (!state.inside.hasOwnProperty(type)) { + return false; } - var arr = arrayify(get(obj, prop)); - set(obj, prop, union(arr, arrayify(value))); - return obj; + return state.inside[type].length > 0; }; -function arrayify(val) { - if (val === null || typeof val === 'undefined') { - return []; - } - if (Array.isArray(val)) { - return val; - } - return [val]; -} - - -/***/ }), -/* 576 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; +/** + * Returns true if `node` is either a child or grand-child of the given `type`, + * or `state.inside[type]` is a non-empty array. + * + * ```js + * var state = { inside: {}}; + * var node = new Node({type: 'brace'}); + * var open = new Node({type: 'brace.open'}); + * console.log(utils.isInside(state, open, 'brace')); //=> false + * utils.pushNode(node, open); + * console.log(utils.isInside(state, open, 'brace')); //=> true + * ``` + * @param {Object} `state` Either the `compiler.state` object, if it exists, or a user-supplied state object. + * @param {Object} `node` Instance of [snapdragon-node][] + * @param {String} `type` The `node.type` to check for. + * @return {Boolean} + * @api public + */ +utils.isInside = function(state, node, type) { + assert(utils.isNode(node), 'expected node to be an instance of Node'); + assert(isObject(state), 'expected state to be an object'); -module.exports = function union(init) { - if (!Array.isArray(init)) { - throw new TypeError('arr-union expects the first argument to be an array.'); + if (Array.isArray(type)) { + for (var i = 0; i < type.length; i++) { + if (utils.isInside(state, node, type[i])) { + return true; + } + } + return false; } - var len = arguments.length; - var i = 0; - - while (++i < len) { - var arg = arguments[i]; - if (!arg) continue; + var parent = node.parent; + if (typeof type === 'string') { + return (parent && parent.type === type) || utils.isInsideType(state, type); + } - if (!Array.isArray(arg)) { - arg = [arg]; + if (typeOf(type) === 'regexp') { + if (parent && parent.type && type.test(parent.type)) { + return true; } - for (var j = 0; j < arg.length; j++) { - var ele = arg[j]; + var keys = Object.keys(state.inside); + var len = keys.length; + var idx = -1; + while (++idx < len) { + var key = keys[idx]; + var val = state.inside[key]; - if (init.indexOf(ele) >= 0) { - continue; + if (Array.isArray(val) && val.length !== 0 && type.test(key)) { + return true; } - init.push(ele); } } - return init; + return false; }; - -/***/ }), -/* 577 */ -/***/ (function(module, exports) { - -/*! - * get-value +/** + * Get the last `n` element from the given `array`. Used for getting + * a node from `node.nodes.` * - * Copyright (c) 2014-2015, Jon Schlinkert. - * Licensed under the MIT License. + * @param {Array} `array` + * @param {Number} `n` + * @return {undefined} + * @api public */ -module.exports = function(obj, prop, a, b, c) { - if (!isObject(obj) || !prop) { - return obj; - } - - prop = toString(prop); +utils.last = function(arr, n) { + return arr[arr.length - (n || 1)]; +}; - // allowing for multiple properties to be passed as - // a string or array, but much faster (3-4x) than doing - // `[].slice.call(arguments)` - if (a) prop += '.' + toString(a); - if (b) prop += '.' + toString(b); - if (c) prop += '.' + toString(c); +/** + * Cast the given `val` to an array. + * + * ```js + * console.log(utils.arrayify('')); + * //=> [] + * console.log(utils.arrayify('foo')); + * //=> ['foo'] + * console.log(utils.arrayify(['foo'])); + * //=> ['foo'] + * ``` + * @param {any} `val` + * @return {Array} + * @api public + */ - if (prop in obj) { - return obj[prop]; +utils.arrayify = function(val) { + if (typeof val === 'string' && val !== '') { + return [val]; } - - var segs = prop.split('.'); - var len = segs.length; - var i = -1; - - while (obj && (++i < len)) { - var key = segs[i]; - while (key[key.length - 1] === '\\') { - key = key.slice(0, -1) + '.' + segs[++i]; - } - obj = obj[key]; + if (!Array.isArray(val)) { + return []; } - return obj; + return val; }; -function isObject(val) { - return val !== null && (typeof val === 'object' || typeof val === 'function'); -} +/** + * Convert the given `val` to a string by joining with `,`. Useful + * for creating a cheerio/CSS/DOM-style selector from a list of strings. + * + * @param {any} `val` + * @return {Array} + * @api public + */ -function toString(val) { - if (!val) return ''; - if (Array.isArray(val)) { - return val.join('.'); - } - return val; -} +utils.stringify = function(val) { + return utils.arrayify(val).join(','); +}; +/** + * Ensure that the given value is a string and call `.trim()` on it, + * or return an empty string. + * + * @param {String} `str` + * @return {String} + * @api public + */ -/***/ }), -/* 578 */ -/***/ (function(module, exports, __webpack_require__) { +utils.trim = function(str) { + return typeof str === 'string' ? str.trim() : ''; +}; -"use strict"; -/*! - * set-value - * - * Copyright (c) 2014-2015, 2017, Jon Schlinkert. - * Released under the MIT License. +/** + * Return true if val is an object */ +function isObject(val) { + return typeOf(val) === 'object'; +} +/** + * Return true if val is a string + */ -var split = __webpack_require__(540); -var extend = __webpack_require__(535); -var isPlainObject = __webpack_require__(543); -var isObject = __webpack_require__(536); +function isString(val) { + return typeof val === 'string'; +} -module.exports = function(obj, prop, val) { - if (!isObject(obj)) { - return obj; - } +/** + * Return true if val is a function + */ - if (Array.isArray(prop)) { - prop = [].concat.apply([], prop).join('.'); - } +function isFunction(val) { + return typeof val === 'function'; +} - if (typeof prop !== 'string') { - return obj; - } +/** + * Return true if val is an array + */ - var keys = split(prop, {sep: '.', brackets: true}).filter(isValidKey); - var len = keys.length; - var idx = -1; - var current = obj; +function isArray(val) { + return Array.isArray(val); +} - while (++idx < len) { - var key = keys[idx]; - if (idx !== len - 1) { - if (!isObject(current[key])) { - current[key] = {}; - } - current = current[key]; - continue; - } +/** + * Shim to ensure the `.append` methods work with any version of snapdragon + */ - if (isPlainObject(current[key]) && isPlainObject(val)) { - current[key] = extend({}, current[key], val); - } else { - current[key] = val; - } +function append(compiler, val, node) { + if (typeof compiler.append !== 'function') { + return compiler.emit(val, node); } + return compiler.append(val, node); +} - return obj; -}; +/** + * Simplified assertion. Throws an error is `val` is falsey. + */ -function isValidKey(key) { - return key !== '__proto__' && key !== 'constructor' && key !== 'prototype'; +function assert(val, message) { + if (!val) throw new Error(message); } /***/ }), -/* 579 */ +/* 568 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -/*! - * unset-value - * - * Copyright (c) 2015, 2017, Jon Schlinkert. - * Released under the MIT License. + + +var extend = __webpack_require__(549); +var Snapdragon = __webpack_require__(569); +var compilers = __webpack_require__(551); +var parsers = __webpack_require__(564); +var utils = __webpack_require__(552); + +/** + * Customize Snapdragon parser and renderer + */ + +function Braces(options) { + this.options = extend({}, options); +} + +/** + * Initialize braces */ +Braces.prototype.init = function(options) { + if (this.isInitialized) return; + this.isInitialized = true; + var opts = utils.createOptions({}, this.options, options); + this.snapdragon = this.options.snapdragon || new Snapdragon(opts); + this.compiler = this.snapdragon.compiler; + this.parser = this.snapdragon.parser; + compilers(this.snapdragon, opts); + parsers(this.snapdragon, opts); -var isObject = __webpack_require__(544); -var has = __webpack_require__(580); + /** + * Call Snapdragon `.parse` method. When AST is returned, we check to + * see if any unclosed braces are left on the stack and, if so, we iterate + * over the stack and correct the AST so that compilers are called in the correct + * order and unbalance braces are properly escaped. + */ -module.exports = function unset(obj, prop) { - if (!isObject(obj)) { - throw new TypeError('expected an object.'); - } - if (obj.hasOwnProperty(prop)) { - delete obj[prop]; - return true; - } + utils.define(this.snapdragon, 'parse', function(pattern, options) { + var parsed = Snapdragon.prototype.parse.apply(this, arguments); + this.parser.ast.input = pattern; - if (has(obj, prop)) { - var segs = prop.split('.'); - var last = segs.pop(); - while (segs.length && segs[segs.length - 1].slice(-1) === '\\') { - last = segs.pop().slice(0, -1) + '.' + last; + var stack = this.parser.stack; + while (stack.length) { + addParent({type: 'brace.close', val: ''}, stack.pop()); } - while (segs.length) obj = obj[prop = segs.shift()]; - return (delete obj[last]); - } - return true; + + function addParent(node, parent) { + utils.define(node, 'parent', parent); + parent.nodes.push(node); + } + + // add non-enumerable parser reference + utils.define(parsed, 'parser', this.parser); + return parsed; + }); }; +/** + * Decorate `.parse` method + */ -/***/ }), -/* 580 */ -/***/ (function(module, exports, __webpack_require__) { +Braces.prototype.parse = function(ast, options) { + if (ast && typeof ast === 'object' && ast.nodes) return ast; + this.init(options); + return this.snapdragon.parse(ast, options); +}; -"use strict"; -/*! - * has-value - * - * Copyright (c) 2014-2016, Jon Schlinkert. - * Licensed under the MIT License. +/** + * Decorate `.compile` method */ +Braces.prototype.compile = function(ast, options) { + if (typeof ast === 'string') { + ast = this.parse(ast, options); + } else { + this.init(options); + } + return this.snapdragon.compile(ast, options); +}; +/** + * Expand + */ -var isObject = __webpack_require__(581); -var hasValues = __webpack_require__(583); -var get = __webpack_require__(577); +Braces.prototype.expand = function(pattern) { + var ast = this.parse(pattern, {expand: true}); + return this.compile(ast, {expand: true}); +}; -module.exports = function(obj, prop, noZero) { - if (isObject(obj)) { - return hasValues(get(obj, prop), noZero); - } - return hasValues(obj, prop); +/** + * Optimize + */ + +Braces.prototype.optimize = function(pattern) { + var ast = this.parse(pattern, {optimize: true}); + return this.compile(ast, {optimize: true}); }; +/** + * Expose `Braces` + */ + +module.exports = Braces; + /***/ }), -/* 581 */ +/* 569 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -/*! - * isobject + + +var Base = __webpack_require__(570); +var define = __webpack_require__(596); +var Compiler = __webpack_require__(606); +var Parser = __webpack_require__(635); +var utils = __webpack_require__(615); +var regexCache = {}; +var cache = {}; + +/** + * Create a new instance of `Snapdragon` with the given `options`. * - * Copyright (c) 2014-2015, Jon Schlinkert. - * Licensed under the MIT License. + * ```js + * var snapdragon = new Snapdragon(); + * ``` + * + * @param {Object} `options` + * @api public */ +function Snapdragon(options) { + Base.call(this, null, options); + this.options = utils.extend({source: 'string'}, this.options); + this.compiler = new Compiler(this.options); + this.parser = new Parser(this.options); + Object.defineProperty(this, 'compilers', { + get: function() { + return this.compiler.compilers; + } + }); -var isArray = __webpack_require__(582); + Object.defineProperty(this, 'parsers', { + get: function() { + return this.parser.parsers; + } + }); -module.exports = function isObject(val) { - return val != null && typeof val === 'object' && isArray(val) === false; -}; + Object.defineProperty(this, 'regex', { + get: function() { + return this.parser.regex; + } + }); +} +/** + * Inherit Base + */ -/***/ }), -/* 582 */ -/***/ (function(module, exports) { +Base.extend(Snapdragon); -var toString = {}.toString; +/** + * Add a parser to `snapdragon.parsers` for capturing the given `type` using + * the specified regex or parser function. A function is useful if you need + * to customize how the token is created and/or have access to the parser + * instance to check options, etc. + * + * ```js + * snapdragon + * .capture('slash', /^\//) + * .capture('dot', function() { + * var pos = this.position(); + * var m = this.match(/^\./); + * if (!m) return; + * return pos({ + * type: 'dot', + * val: m[0] + * }); + * }); + * ``` + * @param {String} `type` + * @param {RegExp|Function} `regex` + * @return {Object} Returns the parser instance for chaining + * @api public + */ -module.exports = Array.isArray || function (arr) { - return toString.call(arr) == '[object Array]'; +Snapdragon.prototype.capture = function() { + return this.parser.capture.apply(this.parser, arguments); }; +/** + * Register a plugin `fn`. + * + * ```js + * var snapdragon = new Snapdgragon([options]); + * snapdragon.use(function() { + * console.log(this); //<= snapdragon instance + * console.log(this.parser); //<= parser instance + * console.log(this.compiler); //<= compiler instance + * }); + * ``` + * @param {Object} `fn` + * @api public + */ -/***/ }), -/* 583 */ -/***/ (function(module, exports, __webpack_require__) { +Snapdragon.prototype.use = function(fn) { + fn.call(this, this); + return this; +}; -"use strict"; -/*! - * has-values +/** + * Parse the given `str`. * - * Copyright (c) 2014-2015, Jon Schlinkert. - * Licensed under the MIT License. + * ```js + * var snapdragon = new Snapdgragon([options]); + * // register parsers + * snapdragon.parser.use(function() {}); + * + * // parse + * var ast = snapdragon.parse('foo/bar'); + * console.log(ast); + * ``` + * @param {String} `str` + * @param {Object} `options` Set `options.sourcemap` to true to enable source maps. + * @return {Object} Returns an AST. + * @api public */ +Snapdragon.prototype.parse = function(str, options) { + this.options = utils.extend({}, this.options, options); + var parsed = this.parser.parse(str, this.options); + + // add non-enumerable parser reference + define(parsed, 'parser', this.parser); + return parsed; +}; + +/** + * Compile the given `AST`. + * + * ```js + * var snapdragon = new Snapdgragon([options]); + * // register plugins + * snapdragon.use(function() {}); + * // register parser plugins + * snapdragon.parser.use(function() {}); + * // register compiler plugins + * snapdragon.compiler.use(function() {}); + * + * // parse + * var ast = snapdragon.parse('foo/bar'); + * + * // compile + * var res = snapdragon.compile(ast); + * console.log(res.output); + * ``` + * @param {Object} `ast` + * @param {Object} `options` + * @return {Object} Returns an object with an `output` property with the rendered string. + * @api public + */ +Snapdragon.prototype.compile = function(ast, options) { + this.options = utils.extend({}, this.options, options); + var compiled = this.compiler.compile(ast, this.options); -module.exports = function hasValue(o, noZero) { - if (o === null || o === undefined) { - return false; - } + // add non-enumerable compiler reference + define(compiled, 'compiler', this.compiler); + return compiled; +}; - if (typeof o === 'boolean') { - return true; - } +/** + * Expose `Snapdragon` + */ - if (typeof o === 'number') { - if (o === 0 && noZero === true) { - return false; - } - return true; - } +module.exports = Snapdragon; - if (o.length !== undefined) { - return o.length !== 0; - } +/** + * Expose `Parser` and `Compiler` + */ - for (var key in o) { - if (o.hasOwnProperty(key)) { - return true; - } - } - return false; -}; +module.exports.Compiler = Compiler; +module.exports.Parser = Parser; /***/ }), -/* 584 */ +/* 570 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -/*! - * has-value - * - * Copyright (c) 2014-2017, Jon Schlinkert. - * Licensed under the MIT License. + + +var util = __webpack_require__(112); +var define = __webpack_require__(571); +var CacheBase = __webpack_require__(572); +var Emitter = __webpack_require__(573); +var isObject = __webpack_require__(534); +var merge = __webpack_require__(590); +var pascal = __webpack_require__(593); +var cu = __webpack_require__(594); + +/** + * Optionally define a custom `cache` namespace to use. */ +function namespace(name) { + var Cache = name ? CacheBase.namespace(name) : CacheBase; + var fns = []; + /** + * Create an instance of `Base` with the given `config` and `options`. + * + * ```js + * // initialize with `config` and `options` + * var app = new Base({isApp: true}, {abc: true}); + * app.set('foo', 'bar'); + * + * // values defined with the given `config` object will be on the root of the instance + * console.log(app.baz); //=> undefined + * console.log(app.foo); //=> 'bar' + * // or use `.get` + * console.log(app.get('isApp')); //=> true + * console.log(app.get('foo')); //=> 'bar' + * + * // values defined with the given `options` object will be on `app.options + * console.log(app.options.abc); //=> true + * ``` + * + * @param {Object} `config` If supplied, this object is passed to [cache-base][] to merge onto the the instance upon instantiation. + * @param {Object} `options` If supplied, this object is used to initialize the `base.options` object. + * @api public + */ -var isObject = __webpack_require__(544); -var hasValues = __webpack_require__(585); -var get = __webpack_require__(577); + function Base(config, options) { + if (!(this instanceof Base)) { + return new Base(config, options); + } + Cache.call(this, config); + this.is('base'); + this.initBase(config, options); + } -module.exports = function(val, prop) { - return hasValues(isObject(val) && prop ? get(val, prop) : val); -}; + /** + * Inherit cache-base + */ + util.inherits(Base, Cache); -/***/ }), -/* 585 */ -/***/ (function(module, exports, __webpack_require__) { + /** + * Add static emitter methods + */ -"use strict"; -/*! - * has-values - * - * Copyright (c) 2014-2015, 2017, Jon Schlinkert. - * Released under the MIT License. - */ + Emitter(Base); + /** + * Initialize `Base` defaults with the given `config` object + */ + Base.prototype.initBase = function(config, options) { + this.options = merge({}, this.options, options); + this.cache = this.cache || {}; + this.define('registered', {}); + if (name) this[name] = {}; -var typeOf = __webpack_require__(586); -var isNumber = __webpack_require__(548); + // make `app._callbacks` non-enumerable + this.define('_callbacks', this._callbacks); + if (isObject(config)) { + this.visit('set', config); + } + Base.run(this, 'use', fns); + }; -module.exports = function hasValue(val) { - // is-number checks for NaN and other edge cases - if (isNumber(val)) { - return true; - } + /** + * Set the given `name` on `app._name` and `app.is*` properties. Used for doing + * lookups in plugins. + * + * ```js + * app.is('foo'); + * console.log(app._name); + * //=> 'foo' + * console.log(app.isFoo); + * //=> true + * app.is('bar'); + * console.log(app.isFoo); + * //=> true + * console.log(app.isBar); + * //=> true + * console.log(app._name); + * //=> 'bar' + * ``` + * @name .is + * @param {String} `name` + * @return {Boolean} + * @api public + */ - switch (typeOf(val)) { - case 'null': - case 'boolean': - case 'function': + Base.prototype.is = function(name) { + if (typeof name !== 'string') { + throw new TypeError('expected name to be a string'); + } + this.define('is' + pascal(name), true); + this.define('_name', name); + this.define('_appname', name); + return this; + }; + + /** + * Returns true if a plugin has already been registered on an instance. + * + * Plugin implementors are encouraged to use this first thing in a plugin + * to prevent the plugin from being called more than once on the same + * instance. + * + * ```js + * var base = new Base(); + * base.use(function(app) { + * if (app.isRegistered('myPlugin')) return; + * // do stuff to `app` + * }); + * + * // to also record the plugin as being registered + * base.use(function(app) { + * if (app.isRegistered('myPlugin', true)) return; + * // do stuff to `app` + * }); + * ``` + * @name .isRegistered + * @emits `plugin` Emits the name of the plugin being registered. Useful for unit tests, to ensure plugins are only registered once. + * @param {String} `name` The plugin name. + * @param {Boolean} `register` If the plugin if not already registered, to record it as being registered pass `true` as the second argument. + * @return {Boolean} Returns true if a plugin is already registered. + * @api public + */ + + Base.prototype.isRegistered = function(name, register) { + if (this.registered.hasOwnProperty(name)) { return true; - case 'string': - case 'arguments': - return val.length !== 0; - case 'error': - return val.message !== ''; - case 'array': - var len = val.length; - if (len === 0) { - return false; - } - for (var i = 0; i < len; i++) { - if (hasValue(val[i])) { - return true; - } - } - return false; - case 'file': - case 'map': - case 'set': - return val.size !== 0; - case 'object': - var keys = Object.keys(val); - if (keys.length === 0) { - return false; - } - for (var i = 0; i < keys.length; i++) { - var key = keys[i]; - if (hasValue(val[key])) { - return true; - } - } - return false; - default: { - return false; } - } -}; + if (register !== false) { + this.registered[name] = true; + this.emit('plugin', name); + } + return false; + }; + /** + * Define a plugin function to be called immediately upon init. Plugins are chainable + * and expose the following arguments to the plugin function: + * + * - `app`: the current instance of `Base` + * - `base`: the [first ancestor instance](#base) of `Base` + * + * ```js + * var app = new Base() + * .use(foo) + * .use(bar) + * .use(baz) + * ``` + * @name .use + * @param {Function} `fn` plugin function to call + * @return {Object} Returns the item instance for chaining. + * @api public + */ -/***/ }), -/* 586 */ -/***/ (function(module, exports, __webpack_require__) { + Base.prototype.use = function(fn) { + fn.call(this, this); + return this; + }; -var isBuffer = __webpack_require__(529); -var toString = Object.prototype.toString; + /** + * The `.define` method is used for adding non-enumerable property on the instance. + * Dot-notation is **not supported** with `define`. + * + * ```js + * // arbitrary `render` function using lodash `template` + * app.define('render', function(str, locals) { + * return _.template(str)(locals); + * }); + * ``` + * @name .define + * @param {String} `key` The name of the property to define. + * @param {any} `value` + * @return {Object} Returns the instance for chaining. + * @api public + */ -/** - * Get the native `typeof` a value. - * - * @param {*} `val` - * @return {*} Native javascript type - */ + Base.prototype.define = function(key, val) { + if (isObject(key)) { + return this.visit('define', key); + } + define(this, key, val); + return this; + }; -module.exports = function kindOf(val) { - // primitivies - if (typeof val === 'undefined') { - return 'undefined'; - } - if (val === null) { - return 'null'; - } - if (val === true || val === false || val instanceof Boolean) { - return 'boolean'; - } - if (typeof val === 'string' || val instanceof String) { - return 'string'; - } - if (typeof val === 'number' || val instanceof Number) { - return 'number'; - } + /** + * Mix property `key` onto the Base prototype. If base is inherited using + * `Base.extend` this method will be overridden by a new `mixin` method that will + * only add properties to the prototype of the inheriting application. + * + * ```js + * app.mixin('foo', function() { + * // do stuff + * }); + * ``` + * @name .mixin + * @param {String} `key` + * @param {Object|Array} `val` + * @return {Object} Returns the `base` instance for chaining. + * @api public + */ - // functions - if (typeof val === 'function' || val instanceof Function) { - return 'function'; - } + Base.prototype.mixin = function(key, val) { + Base.prototype[key] = val; + return this; + }; - // array - if (typeof Array.isArray !== 'undefined' && Array.isArray(val)) { - return 'array'; - } + /** + * Non-enumberable mixin array, used by the static [Base.mixin]() method. + */ - // check for instances of RegExp and Date before calling `toString` - if (val instanceof RegExp) { - return 'regexp'; - } - if (val instanceof Date) { - return 'date'; - } + Base.prototype.mixins = Base.prototype.mixins || []; - // other objects - var type = toString.call(val); + /** + * Getter/setter used when creating nested instances of `Base`, for storing a reference + * to the first ancestor instance. This works by setting an instance of `Base` on the `parent` + * property of a "child" instance. The `base` property defaults to the current instance if + * no `parent` property is defined. + * + * ```js + * // create an instance of `Base`, this is our first ("base") instance + * var first = new Base(); + * first.foo = 'bar'; // arbitrary property, to make it easier to see what's happening later + * + * // create another instance + * var second = new Base(); + * // create a reference to the first instance (`first`) + * second.parent = first; + * + * // create another instance + * var third = new Base(); + * // create a reference to the previous instance (`second`) + * // repeat this pattern every time a "child" instance is created + * third.parent = second; + * + * // we can always access the first instance using the `base` property + * console.log(first.base.foo); + * //=> 'bar' + * console.log(second.base.foo); + * //=> 'bar' + * console.log(third.base.foo); + * //=> 'bar' + * // and now you know how to get to third base ;) + * ``` + * @name .base + * @api public + */ - if (type === '[object RegExp]') { - return 'regexp'; - } - if (type === '[object Date]') { - return 'date'; - } - if (type === '[object Arguments]') { - return 'arguments'; - } - if (type === '[object Error]') { - return 'error'; - } - if (type === '[object Promise]') { - return 'promise'; - } + Object.defineProperty(Base.prototype, 'base', { + configurable: true, + get: function() { + return this.parent ? this.parent.base : this; + } + }); - // buffer - if (isBuffer(val)) { - return 'buffer'; - } + /** + * Static method for adding global plugin functions that will + * be added to an instance when created. + * + * ```js + * Base.use(function(app) { + * app.foo = 'bar'; + * }); + * var app = new Base(); + * console.log(app.foo); + * //=> 'bar' + * ``` + * @name #use + * @param {Function} `fn` Plugin function to use on each instance. + * @return {Object} Returns the `Base` constructor for chaining + * @api public + */ - // es6: Map, WeakMap, Set, WeakSet - if (type === '[object Set]') { - return 'set'; - } - if (type === '[object WeakSet]') { - return 'weakset'; - } - if (type === '[object Map]') { - return 'map'; - } - if (type === '[object WeakMap]') { - return 'weakmap'; - } - if (type === '[object Symbol]') { - return 'symbol'; - } + define(Base, 'use', function(fn) { + fns.push(fn); + return Base; + }); - // typed arrays - if (type === '[object Int8Array]') { - return 'int8array'; - } - if (type === '[object Uint8Array]') { - return 'uint8array'; - } - if (type === '[object Uint8ClampedArray]') { - return 'uint8clampedarray'; - } - if (type === '[object Int16Array]') { - return 'int16array'; - } - if (type === '[object Uint16Array]') { - return 'uint16array'; - } - if (type === '[object Int32Array]') { - return 'int32array'; - } - if (type === '[object Uint32Array]') { - return 'uint32array'; - } - if (type === '[object Float32Array]') { - return 'float32array'; - } - if (type === '[object Float64Array]') { - return 'float64array'; - } + /** + * Run an array of functions by passing each function + * to a method on the given object specified by the given property. + * + * @param {Object} `obj` Object containing method to use. + * @param {String} `prop` Name of the method on the object to use. + * @param {Array} `arr` Array of functions to pass to the method. + */ - // must be a plain object - return 'object'; -}; + define(Base, 'run', function(obj, prop, arr) { + var len = arr.length, i = 0; + while (len--) { + obj[prop](arr[i++]); + } + return Base; + }); + /** + * Static method for inheriting the prototype and static methods of the `Base` class. + * This method greatly simplifies the process of creating inheritance-based applications. + * See [static-extend][] for more details. + * + * ```js + * var extend = cu.extend(Parent); + * Parent.extend(Child); + * + * // optional methods + * Parent.extend(Child, { + * foo: function() {}, + * bar: function() {} + * }); + * ``` + * @name #extend + * @param {Function} `Ctor` constructor to extend + * @param {Object} `methods` Optional prototype properties to mix in. + * @return {Object} Returns the `Base` constructor for chaining + * @api public + */ -/***/ }), -/* 587 */ -/***/ (function(module, exports, __webpack_require__) { + define(Base, 'extend', cu.extend(Base, function(Ctor, Parent) { + Ctor.prototype.mixins = Ctor.prototype.mixins || []; -"use strict"; + define(Ctor, 'mixin', function(fn) { + var mixin = fn(Ctor.prototype, Ctor); + if (typeof mixin === 'function') { + Ctor.prototype.mixins.push(mixin); + } + return Ctor; + }); + define(Ctor, 'mixins', function(Child) { + Base.run(Child, 'mixin', Ctor.prototype.mixins); + return Ctor; + }); -var isExtendable = __webpack_require__(588); -var forIn = __webpack_require__(589); + Ctor.prototype.mixin = function(key, value) { + Ctor.prototype[key] = value; + return this; + }; + return Base; + })); -function mixinDeep(target, objects) { - var len = arguments.length, i = 0; - while (++i < len) { - var obj = arguments[i]; - if (isObject(obj)) { - forIn(obj, copy, target); - } - } - return target; -} + /** + * Used for adding methods to the `Base` prototype, and/or to the prototype of child instances. + * When a mixin function returns a function, the returned function is pushed onto the `.mixins` + * array, making it available to be used on inheriting classes whenever `Base.mixins()` is + * called (e.g. `Base.mixins(Child)`). + * + * ```js + * Base.mixin(function(proto) { + * proto.foo = function(msg) { + * return 'foo ' + msg; + * }; + * }); + * ``` + * @name #mixin + * @param {Function} `fn` Function to call + * @return {Object} Returns the `Base` constructor for chaining + * @api public + */ -/** - * Copy properties from the source object to the - * target object. - * - * @param {*} `val` - * @param {String} `key` - */ + define(Base, 'mixin', function(fn) { + var mixin = fn(Base.prototype, Base); + if (typeof mixin === 'function') { + Base.prototype.mixins.push(mixin); + } + return Base; + }); -function copy(val, key) { - if (!isValidKey(key)) { - return; - } + /** + * Static method for running global mixin functions against a child constructor. + * Mixins must be registered before calling this method. + * + * ```js + * Base.extend(Child); + * Base.mixins(Child); + * ``` + * @name #mixins + * @param {Function} `Child` Constructor function of a child class + * @return {Object} Returns the `Base` constructor for chaining + * @api public + */ - var obj = this[key]; - if (isObject(val) && isObject(obj)) { - mixinDeep(obj, val); - } else { - this[key] = val; - } -} + define(Base, 'mixins', function(Child) { + Base.run(Child, 'mixin', Base.prototype.mixins); + return Base; + }); -/** - * Returns true if `val` is an object or function. - * - * @param {any} val - * @return {Boolean} - */ + /** + * Similar to `util.inherit`, but copies all static properties, prototype properties, and + * getters/setters from `Provider` to `Receiver`. See [class-utils][]{#inherit} for more details. + * + * ```js + * Base.inherit(Foo, Bar); + * ``` + * @name #inherit + * @param {Function} `Receiver` Receiving (child) constructor + * @param {Function} `Provider` Providing (parent) constructor + * @return {Object} Returns the `Base` constructor for chaining + * @api public + */ -function isObject(val) { - return isExtendable(val) && !Array.isArray(val); + define(Base, 'inherit', cu.inherit); + define(Base, 'bubble', cu.bubble); + return Base; } /** - * Returns true if `key` is a valid key to use when extending objects. - * - * @param {String} `key` - * @return {Boolean} + * Expose `Base` with default settings */ -function isValidKey(key) { - return key !== '__proto__' && key !== 'constructor' && key !== 'prototype'; -}; +module.exports = namespace(); /** - * Expose `mixinDeep` + * Allow users to define a namespace */ -module.exports = mixinDeep; +module.exports.namespace = namespace; /***/ }), -/* 588 */ +/* 571 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; /*! - * is-extendable + * define-property * - * Copyright (c) 2015-2017, Jon Schlinkert. + * Copyright (c) 2015, 2017, Jon Schlinkert. * Released under the MIT License. */ -var isPlainObject = __webpack_require__(543); +var isDescriptor = __webpack_require__(535); -module.exports = function isExtendable(val) { - return isPlainObject(val) || typeof val === 'function' || Array.isArray(val); +module.exports = function defineProperty(obj, prop, val) { + if (typeof obj !== 'object' && typeof obj !== 'function') { + throw new TypeError('expected an object or function.'); + } + + if (typeof prop !== 'string') { + throw new TypeError('expected `prop` to be a string.'); + } + + if (isDescriptor(val) && ('set' in val || 'get' in val)) { + return Object.defineProperty(obj, prop, val); + } + + return Object.defineProperty(obj, prop, { + configurable: true, + enumerable: false, + writable: true, + value: val + }); }; /***/ }), -/* 589 */ +/* 572 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -/*! - * for-in + + +var isObject = __webpack_require__(534); +var Emitter = __webpack_require__(573); +var visit = __webpack_require__(574); +var toPath = __webpack_require__(577); +var union = __webpack_require__(578); +var del = __webpack_require__(582); +var get = __webpack_require__(580); +var has = __webpack_require__(587); +var set = __webpack_require__(581); + +/** + * Create a `Cache` constructor that when instantiated will + * store values on the given `prop`. * - * Copyright (c) 2014-2017, Jon Schlinkert. - * Released under the MIT License. + * ```js + * var Cache = require('cache-base').namespace('data'); + * var cache = new Cache(); + * + * cache.set('foo', 'bar'); + * //=> {data: {foo: 'bar'}} + * ``` + * @param {String} `prop` The property name to use for storing values. + * @return {Function} Returns a custom `Cache` constructor + * @api public */ +function namespace(prop) { + + /** + * Create a new `Cache`. Internally the `Cache` constructor is created using + * the `namespace` function, with `cache` defined as the storage object. + * + * ```js + * var app = new Cache(); + * ``` + * @param {Object} `cache` Optionally pass an object to initialize with. + * @constructor + * @api public + */ + + function Cache(cache) { + if (prop) { + this[prop] = {}; + } + if (cache) { + this.set(cache); + } + } + + /** + * Inherit Emitter + */ + + Emitter(Cache.prototype); + /** + * Assign `value` to `key`. Also emits `set` with + * the key and value. + * + * ```js + * app.on('set', function(key, val) { + * // do something when `set` is emitted + * }); + * + * app.set(key, value); + * + * // also takes an object or array + * app.set({name: 'Halle'}); + * app.set([{foo: 'bar'}, {baz: 'quux'}]); + * console.log(app); + * //=> {name: 'Halle', foo: 'bar', baz: 'quux'} + * ``` + * + * @name .set + * @emits `set` with `key` and `value` as arguments. + * @param {String} `key` + * @param {any} `value` + * @return {Object} Returns the instance for chaining. + * @api public + */ -module.exports = function forIn(obj, fn, thisArg) { - for (var key in obj) { - if (fn.call(thisArg, obj[key], key, obj) === false) { - break; + Cache.prototype.set = function(key, val) { + if (Array.isArray(key) && arguments.length === 2) { + key = toPath(key); } - } -}; - - -/***/ }), -/* 590 */ -/***/ (function(module, exports) { - -/*! - * pascalcase - * - * Copyright (c) 2015, Jon Schlinkert. - * Licensed under the MIT License. - */ - -function pascalcase(str) { - if (typeof str !== 'string') { - throw new TypeError('expected a string.'); - } - str = str.replace(/([A-Z])/g, ' $1'); - if (str.length === 1) { return str.toUpperCase(); } - str = str.replace(/^[\W_]+|[\W_]+$/g, '').toLowerCase(); - str = str.charAt(0).toUpperCase() + str.slice(1); - return str.replace(/[\W_]+(\w|$)/g, function (_, ch) { - return ch.toUpperCase(); - }); -} - -module.exports = pascalcase; + if (isObject(key) || Array.isArray(key)) { + this.visit('set', key); + } else { + set(prop ? this[prop] : this, key, val); + this.emit('set', key, val); + } + return this; + }; + /** + * Union `array` to `key`. Also emits `set` with + * the key and value. + * + * ```js + * app.union('a.b', ['foo']); + * app.union('a.b', ['bar']); + * console.log(app.get('a')); + * //=> {b: ['foo', 'bar']} + * ``` + * @name .union + * @param {String} `key` + * @param {any} `value` + * @return {Object} Returns the instance for chaining. + * @api public + */ -/***/ }), -/* 591 */ -/***/ (function(module, exports, __webpack_require__) { + Cache.prototype.union = function(key, val) { + if (Array.isArray(key) && arguments.length === 2) { + key = toPath(key); + } + var ctx = prop ? this[prop] : this; + union(ctx, key, arrayify(val)); + this.emit('union', val); + return this; + }; -"use strict"; + /** + * Return the value of `key`. Dot notation may be used + * to get [nested property values][get-value]. + * + * ```js + * app.set('a.b.c', 'd'); + * app.get('a.b'); + * //=> {c: 'd'} + * + * app.get(['a', 'b']); + * //=> {c: 'd'} + * ``` + * + * @name .get + * @emits `get` with `key` and `value` as arguments. + * @param {String} `key` The name of the property to get. Dot-notation may be used. + * @return {any} Returns the value of `key` + * @api public + */ + Cache.prototype.get = function(key) { + key = toPath(arguments); -var util = __webpack_require__(111); -var utils = __webpack_require__(592); + var ctx = prop ? this[prop] : this; + var val = get(ctx, key); -/** - * Expose class utils - */ + this.emit('get', key, val); + return val; + }; -var cu = module.exports; + /** + * Return true if app has a stored value for `key`, + * false only if value is `undefined`. + * + * ```js + * app.set('foo', 'bar'); + * app.has('foo'); + * //=> true + * ``` + * + * @name .has + * @emits `has` with `key` and true or false as arguments. + * @param {String} `key` + * @return {Boolean} + * @api public + */ -/** - * Expose class utils: `cu` - */ + Cache.prototype.has = function(key) { + key = toPath(arguments); -cu.isObject = function isObject(val) { - return utils.isObj(val) || typeof val === 'function'; -}; + var ctx = prop ? this[prop] : this; + var val = get(ctx, key); -/** - * Returns true if an array has any of the given elements, or an - * object has any of the give keys. - * - * ```js - * cu.has(['a', 'b', 'c'], 'c'); - * //=> true - * - * cu.has(['a', 'b', 'c'], ['c', 'z']); - * //=> true - * - * cu.has({a: 'b', c: 'd'}, ['c', 'z']); - * //=> true - * ``` - * @param {Object} `obj` - * @param {String|Array} `val` - * @return {Boolean} - * @api public - */ + var has = typeof val !== 'undefined'; + this.emit('has', key, has); + return has; + }; -cu.has = function has(obj, val) { - val = cu.arrayify(val); - var len = val.length; + /** + * Delete one or more properties from the instance. + * + * ```js + * app.del(); // delete all + * // or + * app.del('foo'); + * // or + * app.del(['foo', 'bar']); + * ``` + * @name .del + * @emits `del` with the `key` as the only argument. + * @param {String|Array} `key` Property name or array of property names. + * @return {Object} Returns the instance for chaining. + * @api public + */ - if (cu.isObject(obj)) { - for (var key in obj) { - if (val.indexOf(key) > -1) { - return true; - } + Cache.prototype.del = function(key) { + if (Array.isArray(key)) { + this.visit('del', key); + } else { + del(prop ? this[prop] : this, key); + this.emit('del', key); } + return this; + }; - var keys = cu.nativeKeys(obj); - return cu.has(keys, val); - } + /** + * Reset the entire cache to an empty object. + * + * ```js + * app.clear(); + * ``` + * @api public + */ - if (Array.isArray(obj)) { - var arr = obj; - while (len--) { - if (arr.indexOf(val[len]) > -1) { - return true; - } + Cache.prototype.clear = function() { + if (prop) { + this[prop] = {}; } - return false; - } + }; - throw new TypeError('expected an array or object.'); -}; + /** + * Visit `method` over the properties in the given object, or map + * visit over the object-elements in an array. + * + * @name .visit + * @param {String} `method` The name of the `base` method to call. + * @param {Object|Array} `val` The object or array to iterate over. + * @return {Object} Returns the instance for chaining. + * @api public + */ -/** - * Returns true if an array or object has all of the given values. - * - * ```js - * cu.hasAll(['a', 'b', 'c'], 'c'); - * //=> true - * - * cu.hasAll(['a', 'b', 'c'], ['c', 'z']); - * //=> false - * - * cu.hasAll({a: 'b', c: 'd'}, ['c', 'z']); - * //=> false - * ``` - * @param {Object|Array} `val` - * @param {String|Array} `values` - * @return {Boolean} - * @api public - */ + Cache.prototype.visit = function(method, val) { + visit(this, method, val); + return this; + }; -cu.hasAll = function hasAll(val, values) { - values = cu.arrayify(values); - var len = values.length; - while (len--) { - if (!cu.has(val, values[len])) { - return false; - } - } - return true; -}; + return Cache; +} /** - * Cast the given value to an array. - * - * ```js - * cu.arrayify('foo'); - * //=> ['foo'] - * - * cu.arrayify(['foo']); - * //=> ['foo'] - * ``` - * - * @param {String|Array} `val` - * @return {Array} - * @api public + * Cast val to an array */ -cu.arrayify = function arrayify(val) { +function arrayify(val) { return val ? (Array.isArray(val) ? val : [val]) : []; -}; - -/** - * Noop - */ - -cu.noop = function noop() { - return; -}; +} /** - * Returns the first argument passed to the function. + * Expose `Cache` */ -cu.identity = function identity(val) { - return val; -}; +module.exports = namespace(); /** - * Returns true if a value has a `contructor` - * - * ```js - * cu.hasConstructor({}); - * //=> true - * - * cu.hasConstructor(Object.create(null)); - * //=> false - * ``` - * @param {Object} `value` - * @return {Boolean} - * @api public + * Expose `Cache.namespace` */ -cu.hasConstructor = function hasConstructor(val) { - return cu.isObject(val) && typeof val.constructor !== 'undefined'; -}; +module.exports.namespace = namespace; -/** - * Get the native `ownPropertyNames` from the constructor of the - * given `object`. An empty array is returned if the object does - * not have a constructor. - * - * ```js - * cu.nativeKeys({a: 'b', b: 'c', c: 'd'}) - * //=> ['a', 'b', 'c'] - * - * cu.nativeKeys(function(){}) - * //=> ['length', 'caller'] - * ``` - * - * @param {Object} `obj` Object that has a `constructor`. - * @return {Array} Array of keys. - * @api public - */ -cu.nativeKeys = function nativeKeys(val) { - if (!cu.hasConstructor(val)) return []; - return Object.getOwnPropertyNames(val); -}; +/***/ }), +/* 573 */ +/***/ (function(module, exports, __webpack_require__) { -/** - * Returns property descriptor `key` if it's an "own" property - * of the given object. - * - * ```js - * function App() {} - * Object.defineProperty(App.prototype, 'count', { - * get: function() { - * return Object.keys(this).length; - * } - * }); - * cu.getDescriptor(App.prototype, 'count'); - * // returns: - * // { - * // get: [Function], - * // set: undefined, - * // enumerable: false, - * // configurable: false - * // } - * ``` - * - * @param {Object} `obj` - * @param {String} `key` - * @return {Object} Returns descriptor `key` - * @api public - */ + +/** + * Expose `Emitter`. + */ + +if (true) { + module.exports = Emitter; +} + +/** + * Initialize a new `Emitter`. + * + * @api public + */ + +function Emitter(obj) { + if (obj) return mixin(obj); +}; + +/** + * Mixin the emitter properties. + * + * @param {Object} obj + * @return {Object} + * @api private + */ + +function mixin(obj) { + for (var key in Emitter.prototype) { + obj[key] = Emitter.prototype[key]; + } + return obj; +} + +/** + * Listen on the given `event` with `fn`. + * + * @param {String} event + * @param {Function} fn + * @return {Emitter} + * @api public + */ + +Emitter.prototype.on = +Emitter.prototype.addEventListener = function(event, fn){ + this._callbacks = this._callbacks || {}; + (this._callbacks['$' + event] = this._callbacks['$' + event] || []) + .push(fn); + return this; +}; + +/** + * Adds an `event` listener that will be invoked a single + * time then automatically removed. + * + * @param {String} event + * @param {Function} fn + * @return {Emitter} + * @api public + */ + +Emitter.prototype.once = function(event, fn){ + function on() { + this.off(event, on); + fn.apply(this, arguments); + } + + on.fn = fn; + this.on(event, on); + return this; +}; + +/** + * Remove the given callback for `event` or all + * registered callbacks. + * + * @param {String} event + * @param {Function} fn + * @return {Emitter} + * @api public + */ + +Emitter.prototype.off = +Emitter.prototype.removeListener = +Emitter.prototype.removeAllListeners = +Emitter.prototype.removeEventListener = function(event, fn){ + this._callbacks = this._callbacks || {}; + + // all + if (0 == arguments.length) { + this._callbacks = {}; + return this; + } + + // specific event + var callbacks = this._callbacks['$' + event]; + if (!callbacks) return this; + + // remove all handlers + if (1 == arguments.length) { + delete this._callbacks['$' + event]; + return this; + } + + // remove specific handler + var cb; + for (var i = 0; i < callbacks.length; i++) { + cb = callbacks[i]; + if (cb === fn || cb.fn === fn) { + callbacks.splice(i, 1); + break; + } + } + return this; +}; + +/** + * Emit `event` with the given args. + * + * @param {String} event + * @param {Mixed} ... + * @return {Emitter} + */ + +Emitter.prototype.emit = function(event){ + this._callbacks = this._callbacks || {}; + var args = [].slice.call(arguments, 1) + , callbacks = this._callbacks['$' + event]; + + if (callbacks) { + callbacks = callbacks.slice(0); + for (var i = 0, len = callbacks.length; i < len; ++i) { + callbacks[i].apply(this, args); + } + } + + return this; +}; + +/** + * Return array of callbacks for `event`. + * + * @param {String} event + * @return {Array} + * @api public + */ + +Emitter.prototype.listeners = function(event){ + this._callbacks = this._callbacks || {}; + return this._callbacks['$' + event] || []; +}; + +/** + * Check if this emitter has `event` handlers. + * + * @param {String} event + * @return {Boolean} + * @api public + */ + +Emitter.prototype.hasListeners = function(event){ + return !! this.listeners(event).length; +}; -cu.getDescriptor = function getDescriptor(obj, key) { - if (!cu.isObject(obj)) { - throw new TypeError('expected an object.'); - } - if (typeof key !== 'string') { - throw new TypeError('expected key to be a string.'); - } - return Object.getOwnPropertyDescriptor(obj, key); -}; -/** - * Copy a descriptor from one object to another. +/***/ }), +/* 574 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +/*! + * collection-visit * - * ```js - * function App() {} - * Object.defineProperty(App.prototype, 'count', { - * get: function() { - * return Object.keys(this).length; - * } - * }); - * var obj = {}; - * cu.copyDescriptor(obj, App.prototype, 'count'); - * ``` - * @param {Object} `receiver` - * @param {Object} `provider` - * @param {String} `name` - * @return {Object} - * @api public + * Copyright (c) 2015, 2017, Jon Schlinkert. + * Released under the MIT License. */ -cu.copyDescriptor = function copyDescriptor(receiver, provider, name) { - if (!cu.isObject(receiver)) { - throw new TypeError('expected receiving object to be an object.'); - } - if (!cu.isObject(provider)) { - throw new TypeError('expected providing object to be an object.'); - } - if (typeof name !== 'string') { - throw new TypeError('expected name to be a string.'); - } - var val = cu.getDescriptor(provider, name); - if (val) Object.defineProperty(receiver, name, val); -}; -/** - * Copy static properties, prototype properties, and descriptors - * from one object to another. - * - * @param {Object} `receiver` - * @param {Object} `provider` - * @param {String|Array} `omit` One or more properties to omit - * @return {Object} - * @api public - */ +var visit = __webpack_require__(575); +var mapVisit = __webpack_require__(576); -cu.copy = function copy(receiver, provider, omit) { - if (!cu.isObject(receiver)) { - throw new TypeError('expected receiving object to be an object.'); - } - if (!cu.isObject(provider)) { - throw new TypeError('expected providing object to be an object.'); - } - var props = Object.getOwnPropertyNames(provider); - var keys = Object.keys(provider); - var len = props.length, - key; - omit = cu.arrayify(omit); +module.exports = function(collection, method, val) { + var result; - while (len--) { - key = props[len]; + if (typeof val === 'string' && (method in collection)) { + var args = [].slice.call(arguments, 2); + result = collection[method].apply(collection, args); + } else if (Array.isArray(val)) { + result = mapVisit.apply(null, arguments); + } else { + result = visit.apply(null, arguments); + } - if (cu.has(keys, key)) { - utils.define(receiver, key, provider[key]); - } else if (!(key in receiver) && !cu.has(omit, key)) { - cu.copyDescriptor(receiver, provider, key); - } + if (typeof result !== 'undefined') { + return result; } + + return collection; }; -/** - * Inherit the static properties, prototype properties, and descriptors - * from of an object. + +/***/ }), +/* 575 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +/*! + * object-visit * - * @param {Object} `receiver` - * @param {Object} `provider` - * @param {String|Array} `omit` One or more properties to omit - * @return {Object} - * @api public + * Copyright (c) 2015, 2017, Jon Schlinkert. + * Released under the MIT License. */ -cu.inherit = function inherit(receiver, provider, omit) { - if (!cu.isObject(receiver)) { - throw new TypeError('expected receiving object to be an object.'); - } - if (!cu.isObject(provider)) { - throw new TypeError('expected providing object to be an object.'); - } - var keys = []; - for (var key in provider) { - keys.push(key); - receiver[key] = provider[key]; - } - keys = keys.concat(cu.arrayify(omit)); +var isObject = __webpack_require__(534); - var a = provider.prototype || provider; - var b = receiver.prototype || receiver; - cu.copy(b, a, keys); -}; +module.exports = function visit(thisArg, method, target, val) { + if (!isObject(thisArg) && typeof thisArg !== 'function') { + throw new Error('object-visit expects `thisArg` to be an object.'); + } -/** - * Returns a function for extending the static properties, - * prototype properties, and descriptors from the `Parent` - * constructor onto `Child` constructors. - * - * ```js - * var extend = cu.extend(Parent); - * Parent.extend(Child); - * - * // optional methods - * Parent.extend(Child, { - * foo: function() {}, - * bar: function() {} - * }); - * ``` - * @param {Function} `Parent` Parent ctor - * @param {Function} `extend` Optional extend function to handle custom extensions. Useful when updating methods that require a specific prototype. - * @param {Function} `Child` Child ctor - * @param {Object} `proto` Optionally pass additional prototype properties to inherit. - * @return {Object} - * @api public - */ + if (typeof method !== 'string') { + throw new Error('object-visit expects `method` name to be a string'); + } -cu.extend = function() { - // keep it lazy, instead of assigning to `cu.extend` - return utils.staticExtend.apply(null, arguments); -}; + if (typeof thisArg[method] !== 'function') { + return thisArg; + } -/** - * Bubble up events emitted from static methods on the Parent ctor. - * - * @param {Object} `Parent` - * @param {Array} `events` Event names to bubble up - * @api public - */ + var args = [].slice.call(arguments, 3); + target = target || {}; -cu.bubble = function(Parent, events) { - events = events || []; - Parent.bubble = function(Child, arr) { - if (Array.isArray(arr)) { - events = utils.union([], events, arr); - } - var len = events.length; - var idx = -1; - while (++idx < len) { - var name = events[idx]; - Parent.on(name, Child.emit.bind(Child, name)); - } - cu.bubble(Child, events); - }; + for (var key in target) { + var arr = [key, target[key]].concat(args); + thisArg[method].apply(thisArg, arr); + } + return thisArg; }; /***/ }), -/* 592 */ +/* 576 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var utils = {}; - - +var util = __webpack_require__(112); +var visit = __webpack_require__(575); /** - * Lazily required module dependencies + * Map `visit` over an array of objects. + * + * @param {Object} `collection` The context in which to invoke `method` + * @param {String} `method` Name of the method to call on `collection` + * @param {Object} `arr` Array of objects. */ -utils.union = __webpack_require__(576); -utils.define = __webpack_require__(593); -utils.isObj = __webpack_require__(544); -utils.staticExtend = __webpack_require__(600); +module.exports = function mapVisit(collection, method, val) { + if (isObject(val)) { + return visit.apply(null, arguments); + } + if (!Array.isArray(val)) { + throw new TypeError('expected an array: ' + util.inspect(val)); + } -/** - * Expose `utils` - */ + var args = [].slice.call(arguments, 3); -module.exports = utils; + for (var i = 0; i < val.length; i++) { + var ele = val[i]; + if (isObject(ele)) { + visit.apply(null, [collection, method, ele].concat(args)); + } else { + collection[method].apply(collection, [ele].concat(args)); + } + } +}; + +function isObject(val) { + return val && (typeof val === 'function' || (!Array.isArray(val) && typeof val === 'object')); +} /***/ }), -/* 593 */ +/* 577 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; /*! - * define-property + * to-object-path * * Copyright (c) 2015, Jon Schlinkert. * Licensed under the MIT License. @@ -68114,477 +67357,458 @@ module.exports = utils; -var isDescriptor = __webpack_require__(594); +var typeOf = __webpack_require__(559); -module.exports = function defineProperty(obj, prop, val) { - if (typeof obj !== 'object' && typeof obj !== 'function') { - throw new TypeError('expected an object or function.'); +module.exports = function toPath(args) { + if (typeOf(args) !== 'arguments') { + args = arguments; } + return filter(args).join('.'); +}; - if (typeof prop !== 'string') { - throw new TypeError('expected `prop` to be a string.'); +function filter(arr) { + var len = arr.length; + var idx = -1; + var res = []; + + while (++idx < len) { + var ele = arr[idx]; + if (typeOf(ele) === 'arguments' || Array.isArray(ele)) { + res.push.apply(res, filter(ele)); + } else if (typeof ele === 'string') { + res.push(ele); + } } + return res; +} - if (isDescriptor(val) && ('set' in val || 'get' in val)) { - return Object.defineProperty(obj, prop, val); + +/***/ }), +/* 578 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +var isObject = __webpack_require__(550); +var union = __webpack_require__(579); +var get = __webpack_require__(580); +var set = __webpack_require__(581); + +module.exports = function unionValue(obj, prop, value) { + if (!isObject(obj)) { + throw new TypeError('union-value expects the first argument to be an object.'); } - return Object.defineProperty(obj, prop, { - configurable: true, - enumerable: false, - writable: true, - value: val - }); + if (typeof prop !== 'string') { + throw new TypeError('union-value expects `prop` to be a string.'); + } + + var arr = arrayify(get(obj, prop)); + set(obj, prop, union(arr, arrayify(value))); + return obj; }; +function arrayify(val) { + if (val === null || typeof val === 'undefined') { + return []; + } + if (Array.isArray(val)) { + return val; + } + return [val]; +} + /***/ }), -/* 594 */ +/* 579 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -/*! - * is-descriptor - * - * Copyright (c) 2015-2017, Jon Schlinkert. - * Released under the MIT License. - */ +module.exports = function union(init) { + if (!Array.isArray(init)) { + throw new TypeError('arr-union expects the first argument to be an array.'); + } -var typeOf = __webpack_require__(595); -var isAccessor = __webpack_require__(596); -var isData = __webpack_require__(598); + var len = arguments.length; + var i = 0; -module.exports = function isDescriptor(obj, key) { - if (typeOf(obj) !== 'object') { - return false; - } - if ('get' in obj) { - return isAccessor(obj, key); + while (++i < len) { + var arg = arguments[i]; + if (!arg) continue; + + if (!Array.isArray(arg)) { + arg = [arg]; + } + + for (var j = 0; j < arg.length; j++) { + var ele = arg[j]; + + if (init.indexOf(ele) >= 0) { + continue; + } + init.push(ele); + } } - return isData(obj, key); + return init; }; /***/ }), -/* 595 */ +/* 580 */ /***/ (function(module, exports) { -var toString = Object.prototype.toString; - -/** - * Get the native `typeof` a value. +/*! + * get-value * - * @param {*} `val` - * @return {*} Native javascript type + * Copyright (c) 2014-2015, Jon Schlinkert. + * Licensed under the MIT License. */ -module.exports = function kindOf(val) { - var type = typeof val; - - // primitivies - if (type === 'undefined') { - return 'undefined'; - } - if (val === null) { - return 'null'; - } - if (val === true || val === false || val instanceof Boolean) { - return 'boolean'; - } - if (type === 'string' || val instanceof String) { - return 'string'; +module.exports = function(obj, prop, a, b, c) { + if (!isObject(obj) || !prop) { + return obj; } - if (type === 'number' || val instanceof Number) { - return 'number'; + + prop = toString(prop); + + // allowing for multiple properties to be passed as + // a string or array, but much faster (3-4x) than doing + // `[].slice.call(arguments)` + if (a) prop += '.' + toString(a); + if (b) prop += '.' + toString(b); + if (c) prop += '.' + toString(c); + + if (prop in obj) { + return obj[prop]; } - // functions - if (type === 'function' || val instanceof Function) { - if (typeof val.constructor.name !== 'undefined' && val.constructor.name.slice(0, 9) === 'Generator') { - return 'generatorfunction'; + var segs = prop.split('.'); + var len = segs.length; + var i = -1; + + while (obj && (++i < len)) { + var key = segs[i]; + while (key[key.length - 1] === '\\') { + key = key.slice(0, -1) + '.' + segs[++i]; } - return 'function'; + obj = obj[key]; } + return obj; +}; - // array - if (typeof Array.isArray !== 'undefined' && Array.isArray(val)) { - return 'array'; - } +function isObject(val) { + return val !== null && (typeof val === 'object' || typeof val === 'function'); +} - // check for instances of RegExp and Date before calling `toString` - if (val instanceof RegExp) { - return 'regexp'; - } - if (val instanceof Date) { - return 'date'; +function toString(val) { + if (!val) return ''; + if (Array.isArray(val)) { + return val.join('.'); } + return val; +} - // other objects - type = toString.call(val); - if (type === '[object RegExp]') { - return 'regexp'; - } - if (type === '[object Date]') { - return 'date'; - } - if (type === '[object Arguments]') { - return 'arguments'; - } - if (type === '[object Error]') { - return 'error'; - } - if (type === '[object Promise]') { - return 'promise'; - } +/***/ }), +/* 581 */ +/***/ (function(module, exports, __webpack_require__) { - // buffer - if (isBuffer(val)) { - return 'buffer'; - } +"use strict"; +/*! + * set-value + * + * Copyright (c) 2014-2015, 2017, Jon Schlinkert. + * Released under the MIT License. + */ - // es6: Map, WeakMap, Set, WeakSet - if (type === '[object Set]') { - return 'set'; - } - if (type === '[object WeakSet]') { - return 'weakset'; - } - if (type === '[object Map]') { - return 'map'; - } - if (type === '[object WeakMap]') { - return 'weakmap'; - } - if (type === '[object Symbol]') { - return 'symbol'; - } - - if (type === '[object Map Iterator]') { - return 'mapiterator'; - } - if (type === '[object Set Iterator]') { - return 'setiterator'; - } - if (type === '[object String Iterator]') { - return 'stringiterator'; - } - if (type === '[object Array Iterator]') { - return 'arrayiterator'; - } - - // typed arrays - if (type === '[object Int8Array]') { - return 'int8array'; - } - if (type === '[object Uint8Array]') { - return 'uint8array'; - } - if (type === '[object Uint8ClampedArray]') { - return 'uint8clampedarray'; - } - if (type === '[object Int16Array]') { - return 'int16array'; - } - if (type === '[object Uint16Array]') { - return 'uint16array'; - } - if (type === '[object Int32Array]') { - return 'int32array'; + + +var split = __webpack_require__(553); +var extend = __webpack_require__(549); +var isPlainObject = __webpack_require__(543); +var isObject = __webpack_require__(550); + +module.exports = function(obj, prop, val) { + if (!isObject(obj)) { + return obj; } - if (type === '[object Uint32Array]') { - return 'uint32array'; + + if (Array.isArray(prop)) { + prop = [].concat.apply([], prop).join('.'); } - if (type === '[object Float32Array]') { - return 'float32array'; + + if (typeof prop !== 'string') { + return obj; } - if (type === '[object Float64Array]') { - return 'float64array'; + + var keys = split(prop, {sep: '.', brackets: true}).filter(isValidKey); + var len = keys.length; + var idx = -1; + var current = obj; + + while (++idx < len) { + var key = keys[idx]; + if (idx !== len - 1) { + if (!isObject(current[key])) { + current[key] = {}; + } + current = current[key]; + continue; + } + + if (isPlainObject(current[key]) && isPlainObject(val)) { + current[key] = extend({}, current[key], val); + } else { + current[key] = val; + } } - // must be a plain object - return 'object'; + return obj; }; -/** - * If you need to support Safari 5-7 (8-10 yr-old browser), - * take a look at https://github.com/feross/is-buffer - */ - -function isBuffer(val) { - return val.constructor - && typeof val.constructor.isBuffer === 'function' - && val.constructor.isBuffer(val); +function isValidKey(key) { + return key !== '__proto__' && key !== 'constructor' && key !== 'prototype'; } /***/ }), -/* 596 */ +/* 582 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; /*! - * is-accessor-descriptor + * unset-value * - * Copyright (c) 2015, Jon Schlinkert. - * Licensed under the MIT License. + * Copyright (c) 2015, 2017, Jon Schlinkert. + * Released under the MIT License. */ -var typeOf = __webpack_require__(597); - -// accessor descriptor properties -var accessor = { - get: 'function', - set: 'function', - configurable: 'boolean', - enumerable: 'boolean' -}; +var isObject = __webpack_require__(534); +var has = __webpack_require__(583); -function isAccessorDescriptor(obj, prop) { - if (typeof prop === 'string') { - var val = Object.getOwnPropertyDescriptor(obj, prop); - return typeof val !== 'undefined'; +module.exports = function unset(obj, prop) { + if (!isObject(obj)) { + throw new TypeError('expected an object.'); } - - if (typeOf(obj) !== 'object') { - return false; + if (obj.hasOwnProperty(prop)) { + delete obj[prop]; + return true; } - if (has(obj, 'value') || has(obj, 'writable')) { - return false; + if (has(obj, prop)) { + var segs = prop.split('.'); + var last = segs.pop(); + while (segs.length && segs[segs.length - 1].slice(-1) === '\\') { + last = segs.pop().slice(0, -1) + '.' + last; + } + while (segs.length) obj = obj[prop = segs.shift()]; + return (delete obj[last]); } + return true; +}; - if (!has(obj, 'get') || typeof obj.get !== 'function') { - return false; - } - // tldr: it's valid to have "set" be undefined - // "set" might be undefined if `Object.getOwnPropertyDescriptor` - // was used to get the value, and only `get` was defined by the user - if (has(obj, 'set') && typeof obj[key] !== 'function' && typeof obj[key] !== 'undefined') { - return false; - } +/***/ }), +/* 583 */ +/***/ (function(module, exports, __webpack_require__) { - for (var key in obj) { - if (!accessor.hasOwnProperty(key)) { - continue; - } +"use strict"; +/*! + * has-value + * + * Copyright (c) 2014-2016, Jon Schlinkert. + * Licensed under the MIT License. + */ - if (typeOf(obj[key]) === accessor[key]) { - continue; - } - if (typeof obj[key] !== 'undefined') { - return false; - } + +var isObject = __webpack_require__(584); +var hasValues = __webpack_require__(586); +var get = __webpack_require__(580); + +module.exports = function(obj, prop, noZero) { + if (isObject(obj)) { + return hasValues(get(obj, prop), noZero); } - return true; -} + return hasValues(obj, prop); +}; -function has(obj, key) { - return {}.hasOwnProperty.call(obj, key); -} -/** - * Expose `isAccessorDescriptor` +/***/ }), +/* 584 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +/*! + * isobject + * + * Copyright (c) 2014-2015, Jon Schlinkert. + * Licensed under the MIT License. */ -module.exports = isAccessorDescriptor; + + +var isArray = __webpack_require__(585); + +module.exports = function isObject(val) { + return val != null && typeof val === 'object' && isArray(val) === false; +}; /***/ }), -/* 597 */ -/***/ (function(module, exports, __webpack_require__) { +/* 585 */ +/***/ (function(module, exports) { -var isBuffer = __webpack_require__(529); -var toString = Object.prototype.toString; +var toString = {}.toString; -/** - * Get the native `typeof` a value. - * - * @param {*} `val` - * @return {*} Native javascript type - */ +module.exports = Array.isArray || function (arr) { + return toString.call(arr) == '[object Array]'; +}; -module.exports = function kindOf(val) { - // primitivies - if (typeof val === 'undefined') { - return 'undefined'; - } - if (val === null) { - return 'null'; - } - if (val === true || val === false || val instanceof Boolean) { - return 'boolean'; - } - if (typeof val === 'string' || val instanceof String) { - return 'string'; - } - if (typeof val === 'number' || val instanceof Number) { - return 'number'; - } - // functions - if (typeof val === 'function' || val instanceof Function) { - return 'function'; - } +/***/ }), +/* 586 */ +/***/ (function(module, exports, __webpack_require__) { - // array - if (typeof Array.isArray !== 'undefined' && Array.isArray(val)) { - return 'array'; - } +"use strict"; +/*! + * has-values + * + * Copyright (c) 2014-2015, Jon Schlinkert. + * Licensed under the MIT License. + */ - // check for instances of RegExp and Date before calling `toString` - if (val instanceof RegExp) { - return 'regexp'; - } - if (val instanceof Date) { - return 'date'; - } - // other objects - var type = toString.call(val); - if (type === '[object RegExp]') { - return 'regexp'; - } - if (type === '[object Date]') { - return 'date'; - } - if (type === '[object Arguments]') { - return 'arguments'; - } - if (type === '[object Error]') { - return 'error'; +module.exports = function hasValue(o, noZero) { + if (o === null || o === undefined) { + return false; } - // buffer - if (isBuffer(val)) { - return 'buffer'; + if (typeof o === 'boolean') { + return true; } - // es6: Map, WeakMap, Set, WeakSet - if (type === '[object Set]') { - return 'set'; - } - if (type === '[object WeakSet]') { - return 'weakset'; - } - if (type === '[object Map]') { - return 'map'; - } - if (type === '[object WeakMap]') { - return 'weakmap'; - } - if (type === '[object Symbol]') { - return 'symbol'; + if (typeof o === 'number') { + if (o === 0 && noZero === true) { + return false; + } + return true; } - // typed arrays - if (type === '[object Int8Array]') { - return 'int8array'; - } - if (type === '[object Uint8Array]') { - return 'uint8array'; - } - if (type === '[object Uint8ClampedArray]') { - return 'uint8clampedarray'; - } - if (type === '[object Int16Array]') { - return 'int16array'; - } - if (type === '[object Uint16Array]') { - return 'uint16array'; - } - if (type === '[object Int32Array]') { - return 'int32array'; - } - if (type === '[object Uint32Array]') { - return 'uint32array'; - } - if (type === '[object Float32Array]') { - return 'float32array'; - } - if (type === '[object Float64Array]') { - return 'float64array'; + if (o.length !== undefined) { + return o.length !== 0; } - // must be a plain object - return 'object'; + for (var key in o) { + if (o.hasOwnProperty(key)) { + return true; + } + } + return false; }; /***/ }), -/* 598 */ +/* 587 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; /*! - * is-data-descriptor + * has-value * - * Copyright (c) 2015, Jon Schlinkert. + * Copyright (c) 2014-2017, Jon Schlinkert. * Licensed under the MIT License. */ -var typeOf = __webpack_require__(599); +var isObject = __webpack_require__(534); +var hasValues = __webpack_require__(588); +var get = __webpack_require__(580); -// data descriptor properties -var data = { - configurable: 'boolean', - enumerable: 'boolean', - writable: 'boolean' +module.exports = function(val, prop) { + return hasValues(isObject(val) && prop ? get(val, prop) : val); }; -function isDataDescriptor(obj, prop) { - if (typeOf(obj) !== 'object') { - return false; - } - if (typeof prop === 'string') { - var val = Object.getOwnPropertyDescriptor(obj, prop); - return typeof val !== 'undefined'; - } +/***/ }), +/* 588 */ +/***/ (function(module, exports, __webpack_require__) { - if (!('value' in obj) && !('writable' in obj)) { - return false; - } +"use strict"; +/*! + * has-values + * + * Copyright (c) 2014-2015, 2017, Jon Schlinkert. + * Released under the MIT License. + */ - for (var key in obj) { - if (key === 'value') continue; - if (!data.hasOwnProperty(key)) { - continue; - } - if (typeOf(obj[key]) === data[key]) { - continue; - } +var typeOf = __webpack_require__(589); +var isNumber = __webpack_require__(558); - if (typeof obj[key] !== 'undefined') { +module.exports = function hasValue(val) { + // is-number checks for NaN and other edge cases + if (isNumber(val)) { + return true; + } + + switch (typeOf(val)) { + case 'null': + case 'boolean': + case 'function': + return true; + case 'string': + case 'arguments': + return val.length !== 0; + case 'error': + return val.message !== ''; + case 'array': + var len = val.length; + if (len === 0) { + return false; + } + for (var i = 0; i < len; i++) { + if (hasValue(val[i])) { + return true; + } + } + return false; + case 'file': + case 'map': + case 'set': + return val.size !== 0; + case 'object': + var keys = Object.keys(val); + if (keys.length === 0) { + return false; + } + for (var i = 0; i < keys.length; i++) { + var key = keys[i]; + if (hasValue(val[key])) { + return true; + } + } + return false; + default: { return false; } } - return true; -} - -/** - * Expose `isDataDescriptor` - */ - -module.exports = isDataDescriptor; +}; /***/ }), -/* 599 */ +/* 589 */ /***/ (function(module, exports, __webpack_require__) { -var isBuffer = __webpack_require__(529); +var isBuffer = __webpack_require__(560); var toString = Object.prototype.toString; /** @@ -68645,6 +67869,9 @@ module.exports = function kindOf(val) { if (type === '[object Error]') { return 'error'; } + if (type === '[object Promise]') { + return 'promise'; + } // buffer if (isBuffer(val)) { @@ -68703,196 +67930,204 @@ module.exports = function kindOf(val) { /***/ }), -/* 600 */ +/* 590 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -/*! - * static-extend - * - * Copyright (c) 2016, Jon Schlinkert. - * Licensed under the MIT License. - */ +var isExtendable = __webpack_require__(591); +var forIn = __webpack_require__(592); -var copy = __webpack_require__(601); -var define = __webpack_require__(593); -var util = __webpack_require__(111); +function mixinDeep(target, objects) { + var len = arguments.length, i = 0; + while (++i < len) { + var obj = arguments[i]; + if (isObject(obj)) { + forIn(obj, copy, target); + } + } + return target; +} /** - * Returns a function for extending the static properties, - * prototype properties, and descriptors from the `Parent` - * constructor onto `Child` constructors. + * Copy properties from the source object to the + * target object. * - * ```js - * var extend = require('static-extend'); - * Parent.extend = extend(Parent); + * @param {*} `val` + * @param {String} `key` + */ + +function copy(val, key) { + if (!isValidKey(key)) { + return; + } + + var obj = this[key]; + if (isObject(val) && isObject(obj)) { + mixinDeep(obj, val); + } else { + this[key] = val; + } +} + +/** + * Returns true if `val` is an object or function. * - * // optionally pass a custom merge function as the second arg - * Parent.extend = extend(Parent, function(Child) { - * Child.prototype.mixin = function(key, val) { - * Child.prototype[key] = val; - * }; - * }); + * @param {any} val + * @return {Boolean} + */ + +function isObject(val) { + return isExtendable(val) && !Array.isArray(val); +} + +/** + * Returns true if `key` is a valid key to use when extending objects. * - * // extend "child" constructors - * Parent.extend(Child); + * @param {String} `key` + * @return {Boolean} + */ + +function isValidKey(key) { + return key !== '__proto__' && key !== 'constructor' && key !== 'prototype'; +}; + +/** + * Expose `mixinDeep` + */ + +module.exports = mixinDeep; + + +/***/ }), +/* 591 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +/*! + * is-extendable * - * // optionally define prototype methods as the second arg - * Parent.extend(Child, { - * foo: function() {}, - * bar: function() {} - * }); - * ``` - * @param {Function} `Parent` Parent ctor - * @param {Function} `extendFn` Optional extend function for handling any necessary custom merging. Useful when updating methods that require a specific prototype. - * @param {Function} `Child` Child ctor - * @param {Object} `proto` Optionally pass additional prototype properties to inherit. - * @return {Object} - * @api public + * Copyright (c) 2015-2017, Jon Schlinkert. + * Released under the MIT License. */ -function extend(Parent, extendFn) { - if (typeof Parent !== 'function') { - throw new TypeError('expected Parent to be a function.'); - } - return function(Ctor, proto) { - if (typeof Ctor !== 'function') { - throw new TypeError('expected Ctor to be a function.'); - } - util.inherits(Ctor, Parent); - copy(Ctor, Parent); +var isPlainObject = __webpack_require__(543); - // proto can be null or a plain object - if (typeof proto === 'object') { - var obj = Object.create(proto); +module.exports = function isExtendable(val) { + return isPlainObject(val) || typeof val === 'function' || Array.isArray(val); +}; - for (var k in obj) { - Ctor.prototype[k] = obj[k]; - } - } - // keep a reference to the parent prototype - define(Ctor.prototype, '_parent_', { - configurable: true, - set: function() {}, - get: function() { - return Parent.prototype; - } - }); +/***/ }), +/* 592 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +/*! + * for-in + * + * Copyright (c) 2014-2017, Jon Schlinkert. + * Released under the MIT License. + */ + - if (typeof extendFn === 'function') { - extendFn(Ctor, Parent); - } - Ctor.extend = extend(Ctor, extendFn); - }; +module.exports = function forIn(obj, fn, thisArg) { + for (var key in obj) { + if (fn.call(thisArg, obj[key], key, obj) === false) { + break; + } + } }; -/** - * Expose `extend` + +/***/ }), +/* 593 */ +/***/ (function(module, exports) { + +/*! + * pascalcase + * + * Copyright (c) 2015, Jon Schlinkert. + * Licensed under the MIT License. */ -module.exports = extend; +function pascalcase(str) { + if (typeof str !== 'string') { + throw new TypeError('expected a string.'); + } + str = str.replace(/([A-Z])/g, ' $1'); + if (str.length === 1) { return str.toUpperCase(); } + str = str.replace(/^[\W_]+|[\W_]+$/g, '').toLowerCase(); + str = str.charAt(0).toUpperCase() + str.slice(1); + return str.replace(/[\W_]+(\w|$)/g, function (_, ch) { + return ch.toUpperCase(); + }); +} + +module.exports = pascalcase; /***/ }), -/* 601 */ +/* 594 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var typeOf = __webpack_require__(549); -var copyDescriptor = __webpack_require__(602); -var define = __webpack_require__(593); +var util = __webpack_require__(112); +var utils = __webpack_require__(595); /** - * Copy static properties, prototype properties, and descriptors from one object to another. - * - * ```js - * function App() {} - * var proto = App.prototype; - * App.prototype.set = function() {}; - * App.prototype.get = function() {}; - * - * var obj = {}; - * copy(obj, proto); - * ``` - * @param {Object} `receiver` - * @param {Object} `provider` - * @param {String|Array} `omit` One or more properties to omit - * @return {Object} - * @api public + * Expose class utils */ -function copy(receiver, provider, omit) { - if (!isObject(receiver)) { - throw new TypeError('expected receiving object to be an object.'); - } - if (!isObject(provider)) { - throw new TypeError('expected providing object to be an object.'); - } - - var props = nativeKeys(provider); - var keys = Object.keys(provider); - var len = props.length; - omit = arrayify(omit); - - while (len--) { - var key = props[len]; - - if (has(keys, key)) { - define(receiver, key, provider[key]); - } else if (!(key in receiver) && !has(omit, key)) { - copyDescriptor(receiver, provider, key); - } - } -}; +var cu = module.exports; /** - * Return true if the given value is an object or function + * Expose class utils: `cu` */ -function isObject(val) { - return typeOf(val) === 'object' || typeof val === 'function'; -} +cu.isObject = function isObject(val) { + return utils.isObj(val) || typeof val === 'function'; +}; /** * Returns true if an array has any of the given elements, or an * object has any of the give keys. * * ```js - * has(['a', 'b', 'c'], 'c'); + * cu.has(['a', 'b', 'c'], 'c'); * //=> true * - * has(['a', 'b', 'c'], ['c', 'z']); + * cu.has(['a', 'b', 'c'], ['c', 'z']); * //=> true * - * has({a: 'b', c: 'd'}, ['c', 'z']); + * cu.has({a: 'b', c: 'd'}, ['c', 'z']); * //=> true * ``` * @param {Object} `obj` * @param {String|Array} `val` * @return {Boolean} + * @api public */ -function has(obj, val) { - val = arrayify(val); +cu.has = function has(obj, val) { + val = cu.arrayify(val); var len = val.length; - if (isObject(obj)) { + if (cu.isObject(obj)) { for (var key in obj) { if (val.indexOf(key) > -1) { return true; } } - var keys = nativeKeys(obj); - return has(keys, val); + var keys = cu.nativeKeys(obj); + return cu.has(keys, val); } if (Array.isArray(obj)) { @@ -68906,44 +68141,92 @@ function has(obj, val) { } throw new TypeError('expected an array or object.'); -} +}; + +/** + * Returns true if an array or object has all of the given values. + * + * ```js + * cu.hasAll(['a', 'b', 'c'], 'c'); + * //=> true + * + * cu.hasAll(['a', 'b', 'c'], ['c', 'z']); + * //=> false + * + * cu.hasAll({a: 'b', c: 'd'}, ['c', 'z']); + * //=> false + * ``` + * @param {Object|Array} `val` + * @param {String|Array} `values` + * @return {Boolean} + * @api public + */ + +cu.hasAll = function hasAll(val, values) { + values = cu.arrayify(values); + var len = values.length; + while (len--) { + if (!cu.has(val, values[len])) { + return false; + } + } + return true; +}; /** * Cast the given value to an array. * * ```js - * arrayify('foo'); + * cu.arrayify('foo'); * //=> ['foo'] * - * arrayify(['foo']); + * cu.arrayify(['foo']); * //=> ['foo'] * ``` * * @param {String|Array} `val` * @return {Array} + * @api public */ -function arrayify(val) { +cu.arrayify = function arrayify(val) { return val ? (Array.isArray(val) ? val : [val]) : []; -} +}; + +/** + * Noop + */ + +cu.noop = function noop() { + return; +}; + +/** + * Returns the first argument passed to the function. + */ + +cu.identity = function identity(val) { + return val; +}; /** * Returns true if a value has a `contructor` * * ```js - * hasConstructor({}); + * cu.hasConstructor({}); * //=> true * - * hasConstructor(Object.create(null)); + * cu.hasConstructor(Object.create(null)); * //=> false * ``` * @param {Object} `value` * @return {Boolean} + * @api public */ -function hasConstructor(val) { - return isObject(val) && typeof val.constructor !== 'undefined'; -} +cu.hasConstructor = function hasConstructor(val) { + return cu.isObject(val) && typeof val.constructor !== 'undefined'; +}; /** * Get the native `ownPropertyNames` from the constructor of the @@ -68951,437 +68234,217 @@ function hasConstructor(val) { * not have a constructor. * * ```js - * nativeKeys({a: 'b', b: 'c', c: 'd'}) + * cu.nativeKeys({a: 'b', b: 'c', c: 'd'}) * //=> ['a', 'b', 'c'] * - * nativeKeys(function(){}) + * cu.nativeKeys(function(){}) * //=> ['length', 'caller'] * ``` * * @param {Object} `obj` Object that has a `constructor`. * @return {Array} Array of keys. + * @api public */ -function nativeKeys(val) { - if (!hasConstructor(val)) return []; +cu.nativeKeys = function nativeKeys(val) { + if (!cu.hasConstructor(val)) return []; return Object.getOwnPropertyNames(val); -} - -/** - * Expose `copy` - */ - -module.exports = copy; +}; /** - * Expose `copy.has` for tests - */ - -module.exports.has = has; - - -/***/ }), -/* 602 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; -/*! - * copy-descriptor + * Returns property descriptor `key` if it's an "own" property + * of the given object. * - * Copyright (c) 2015, Jon Schlinkert. - * Licensed under the MIT License. + * ```js + * function App() {} + * Object.defineProperty(App.prototype, 'count', { + * get: function() { + * return Object.keys(this).length; + * } + * }); + * cu.getDescriptor(App.prototype, 'count'); + * // returns: + * // { + * // get: [Function], + * // set: undefined, + * // enumerable: false, + * // configurable: false + * // } + * ``` + * + * @param {Object} `obj` + * @param {String} `key` + * @return {Object} Returns descriptor `key` + * @api public */ - +cu.getDescriptor = function getDescriptor(obj, key) { + if (!cu.isObject(obj)) { + throw new TypeError('expected an object.'); + } + if (typeof key !== 'string') { + throw new TypeError('expected key to be a string.'); + } + return Object.getOwnPropertyDescriptor(obj, key); +}; /** * Copy a descriptor from one object to another. * * ```js - * function App() { - * this.cache = {}; - * } - * App.prototype.set = function(key, val) { - * this.cache[key] = val; - * return this; - * }; + * function App() {} * Object.defineProperty(App.prototype, 'count', { * get: function() { - * return Object.keys(this.cache).length; + * return Object.keys(this).length; * } * }); - * - * copy(App.prototype, 'count', 'len'); - * - * // create an instance - * var app = new App(); - * - * app.set('a', true); - * app.set('b', true); - * app.set('c', true); - * - * console.log(app.count); - * //=> 3 - * console.log(app.len); - * //=> 3 + * var obj = {}; + * cu.copyDescriptor(obj, App.prototype, 'count'); * ``` - * @name copy - * @param {Object} `receiver` The target object - * @param {Object} `provider` The provider object - * @param {String} `from` The key to copy on provider. - * @param {String} `to` Optionally specify a new key name to use. + * @param {Object} `receiver` + * @param {Object} `provider` + * @param {String} `name` * @return {Object} * @api public */ -module.exports = function copyDescriptor(receiver, provider, from, to) { - if (!isObject(provider) && typeof provider !== 'function') { - to = from; - from = provider; - provider = receiver; - } - if (!isObject(receiver) && typeof receiver !== 'function') { - throw new TypeError('expected the first argument to be an object'); - } - if (!isObject(provider) && typeof provider !== 'function') { - throw new TypeError('expected provider to be an object'); - } - - if (typeof to !== 'string') { - to = from; +cu.copyDescriptor = function copyDescriptor(receiver, provider, name) { + if (!cu.isObject(receiver)) { + throw new TypeError('expected receiving object to be an object.'); } - if (typeof from !== 'string') { - throw new TypeError('expected key to be a string'); + if (!cu.isObject(provider)) { + throw new TypeError('expected providing object to be an object.'); } - - if (!(from in provider)) { - throw new Error('property "' + from + '" does not exist'); + if (typeof name !== 'string') { + throw new TypeError('expected name to be a string.'); } - var val = Object.getOwnPropertyDescriptor(provider, from); - if (val) Object.defineProperty(receiver, to, val); + var val = cu.getDescriptor(provider, name); + if (val) Object.defineProperty(receiver, name, val); }; -function isObject(val) { - return {}.toString.call(val) === '[object Object]'; -} - - - -/***/ }), -/* 603 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -var use = __webpack_require__(604); -var define = __webpack_require__(593); -var debug = __webpack_require__(606)('snapdragon:compiler'); -var utils = __webpack_require__(612); - -/** - * Create a new `Compiler` with the given `options`. - * @param {Object} `options` - */ - -function Compiler(options, state) { - debug('initializing', __filename); - this.options = utils.extend({source: 'string'}, options); - this.state = state || {}; - this.compilers = {}; - this.output = ''; - this.set('eos', function(node) { - return this.emit(node.val, node); - }); - this.set('noop', function(node) { - return this.emit(node.val, node); - }); - this.set('bos', function(node) { - return this.emit(node.val, node); - }); - use(this); -} - /** - * Prototype methods + * Copy static properties, prototype properties, and descriptors + * from one object to another. + * + * @param {Object} `receiver` + * @param {Object} `provider` + * @param {String|Array} `omit` One or more properties to omit + * @return {Object} + * @api public */ -Compiler.prototype = { - - /** - * Throw an error message with details including the cursor position. - * @param {String} `msg` Message to use in the Error. - */ - - error: function(msg, node) { - var pos = node.position || {start: {column: 0}}; - var message = this.options.source + ' column:' + pos.start.column + ': ' + msg; - - var err = new Error(message); - err.reason = msg; - err.column = pos.start.column; - err.source = this.pattern; - - if (this.options.silent) { - this.errors.push(err); - } else { - throw err; - } - }, - - /** - * Define a non-enumberable property on the `Compiler` instance. - * - * ```js - * compiler.define('foo', 'bar'); - * ``` - * @name .define - * @param {String} `key` propery name - * @param {any} `val` property value - * @return {Object} Returns the Compiler instance for chaining. - * @api public - */ - - define: function(key, val) { - define(this, key, val); - return this; - }, - - /** - * Emit `node.val` - */ - - emit: function(str, node) { - this.output += str; - return str; - }, - - /** - * Add a compiler `fn` with the given `name` - */ - - set: function(name, fn) { - this.compilers[name] = fn; - return this; - }, - - /** - * Get compiler `name`. - */ - - get: function(name) { - return this.compilers[name]; - }, - - /** - * Get the previous AST node. - */ - - prev: function(n) { - return this.ast.nodes[this.idx - (n || 1)] || { type: 'bos', val: '' }; - }, - - /** - * Get the next AST node. - */ - - next: function(n) { - return this.ast.nodes[this.idx + (n || 1)] || { type: 'eos', val: '' }; - }, - - /** - * Visit `node`. - */ - - visit: function(node, nodes, i) { - var fn = this.compilers[node.type]; - this.idx = i; - - if (typeof fn !== 'function') { - throw this.error('compiler "' + node.type + '" is not registered', node); - } - return fn.call(this, node, nodes, i); - }, - - /** - * Map visit over array of `nodes`. - */ - - mapVisit: function(nodes) { - if (!Array.isArray(nodes)) { - throw new TypeError('expected an array'); - } - var len = nodes.length; - var idx = -1; - while (++idx < len) { - this.visit(nodes[idx], nodes, idx); - } - return this; - }, - - /** - * Compile `ast`. - */ - - compile: function(ast, options) { - var opts = utils.extend({}, this.options, options); - this.ast = ast; - this.parsingErrors = this.ast.errors; - this.output = ''; - - // source map support - if (opts.sourcemap) { - var sourcemaps = __webpack_require__(631); - sourcemaps(this); - this.mapVisit(this.ast.nodes); - this.applySourceMaps(); - this.map = opts.sourcemap === 'generator' ? this.map : this.map.toJSON(); - return this; - } - - this.mapVisit(this.ast.nodes); - return this; +cu.copy = function copy(receiver, provider, omit) { + if (!cu.isObject(receiver)) { + throw new TypeError('expected receiving object to be an object.'); } -}; - -/** - * Expose `Compiler` - */ - -module.exports = Compiler; - - -/***/ }), -/* 604 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; -/*! - * use - * - * Copyright (c) 2015, 2017, Jon Schlinkert. - * Released under the MIT License. - */ + if (!cu.isObject(provider)) { + throw new TypeError('expected providing object to be an object.'); + } + var props = Object.getOwnPropertyNames(provider); + var keys = Object.keys(provider); + var len = props.length, + key; + omit = cu.arrayify(omit); + while (len--) { + key = props[len]; + if (cu.has(keys, key)) { + utils.define(receiver, key, provider[key]); + } else if (!(key in receiver) && !cu.has(omit, key)) { + cu.copyDescriptor(receiver, provider, key); + } + } +}; -var utils = __webpack_require__(605); +/** + * Inherit the static properties, prototype properties, and descriptors + * from of an object. + * + * @param {Object} `receiver` + * @param {Object} `provider` + * @param {String|Array} `omit` One or more properties to omit + * @return {Object} + * @api public + */ -module.exports = function base(app, opts) { - if (!utils.isObject(app) && typeof app !== 'function') { - throw new TypeError('use: expect `app` be an object or function'); +cu.inherit = function inherit(receiver, provider, omit) { + if (!cu.isObject(receiver)) { + throw new TypeError('expected receiving object to be an object.'); } - - if (!utils.isObject(opts)) { - opts = {}; + if (!cu.isObject(provider)) { + throw new TypeError('expected providing object to be an object.'); } - var prop = utils.isString(opts.prop) ? opts.prop : 'fns'; - if (!Array.isArray(app[prop])) { - utils.define(app, prop, []); + var keys = []; + for (var key in provider) { + keys.push(key); + receiver[key] = provider[key]; } - /** - * Define a plugin function to be passed to use. The only - * parameter exposed to the plugin is `app`, the object or function. - * passed to `use(app)`. `app` is also exposed as `this` in plugins. - * - * Additionally, **if a plugin returns a function, the function will - * be pushed onto the `fns` array**, allowing the plugin to be - * called at a later point by the `run` method. - * - * ```js - * var use = require('use'); - * - * // define a plugin - * function foo(app) { - * // do stuff - * } - * - * var app = function(){}; - * use(app); - * - * // register plugins - * app.use(foo); - * app.use(bar); - * app.use(baz); - * ``` - * @name .use - * @param {Function} `fn` plugin function to call - * @api public - */ - - utils.define(app, 'use', use); - - /** - * Run all plugins on `fns`. Any plugin that returns a function - * when called by `use` is pushed onto the `fns` array. - * - * ```js - * var config = {}; - * app.run(config); - * ``` - * @name .run - * @param {Object} `value` Object to be modified by plugins. - * @return {Object} Returns the object passed to `run` - * @api public - */ - - utils.define(app, 'run', function(val) { - if (!utils.isObject(val)) return; - decorate(val); - - var self = this || app; - var fns = self[prop]; - var len = fns.length; - var idx = -1; + keys = keys.concat(cu.arrayify(omit)); - while (++idx < len) { - val.use(fns[idx]); - } - return val; - }); + var a = provider.prototype || provider; + var b = receiver.prototype || receiver; + cu.copy(b, a, keys); +}; - /** - * Call plugin `fn`. If a function is returned push it into the - * `fns` array to be called by the `run` method. - */ +/** + * Returns a function for extending the static properties, + * prototype properties, and descriptors from the `Parent` + * constructor onto `Child` constructors. + * + * ```js + * var extend = cu.extend(Parent); + * Parent.extend(Child); + * + * // optional methods + * Parent.extend(Child, { + * foo: function() {}, + * bar: function() {} + * }); + * ``` + * @param {Function} `Parent` Parent ctor + * @param {Function} `extend` Optional extend function to handle custom extensions. Useful when updating methods that require a specific prototype. + * @param {Function} `Child` Child ctor + * @param {Object} `proto` Optionally pass additional prototype properties to inherit. + * @return {Object} + * @api public + */ - function use(fn, options) { - if (typeof fn !== 'function') { - throw new TypeError('.use expects `fn` be a function'); - } +cu.extend = function() { + // keep it lazy, instead of assigning to `cu.extend` + return utils.staticExtend.apply(null, arguments); +}; - var self = this || app; - if (typeof opts.fn === 'function') { - opts.fn.call(self, self, options); - } +/** + * Bubble up events emitted from static methods on the Parent ctor. + * + * @param {Object} `Parent` + * @param {Array} `events` Event names to bubble up + * @api public + */ - var plugin = fn.call(self, self); - if (typeof plugin === 'function') { - var fns = self[prop]; - fns.push(plugin); +cu.bubble = function(Parent, events) { + events = events || []; + Parent.bubble = function(Child, arr) { + if (Array.isArray(arr)) { + events = utils.union([], events, arr); } - return self; - } - - /** - * Ensure the `.use` method exists on `val` - */ - - function decorate(val) { - if (!val.use || !val.run) { - base(val); + var len = events.length; + var idx = -1; + while (++idx < len) { + var name = events[idx]; + Parent.on(name, Child.emit.bind(Child, name)); } - } - - return app; + cu.bubble(Child, events); + }; }; /***/ }), -/* 605 */ +/* 595 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -69395,3290 +68458,3298 @@ var utils = {}; * Lazily required module dependencies */ -utils.define = __webpack_require__(593); -utils.isObject = __webpack_require__(544); +utils.union = __webpack_require__(579); +utils.define = __webpack_require__(596); +utils.isObj = __webpack_require__(534); +utils.staticExtend = __webpack_require__(603); -utils.isString = function(val) { - return val && typeof val === 'string'; -}; - /** - * Expose `utils` modules + * Expose `utils` */ module.exports = utils; /***/ }), -/* 606 */ -/***/ (function(module, exports, __webpack_require__) { - -/** - * Detect Electron renderer process, which is node, but we should - * treat as a browser. - */ - -if (typeof process !== 'undefined' && process.type === 'renderer') { - module.exports = __webpack_require__(607); -} else { - module.exports = __webpack_require__(610); -} - - -/***/ }), -/* 607 */ +/* 596 */ /***/ (function(module, exports, __webpack_require__) { -/** - * This is the web browser implementation of `debug()`. +"use strict"; +/*! + * define-property * - * Expose `debug()` as the module. + * Copyright (c) 2015, Jon Schlinkert. + * Licensed under the MIT License. */ -exports = module.exports = __webpack_require__(608); -exports.log = log; -exports.formatArgs = formatArgs; -exports.save = save; -exports.load = load; -exports.useColors = useColors; -exports.storage = 'undefined' != typeof chrome - && 'undefined' != typeof chrome.storage - ? chrome.storage.local - : localstorage(); - -/** - * Colors. - */ -exports.colors = [ - 'lightseagreen', - 'forestgreen', - 'goldenrod', - 'dodgerblue', - 'darkorchid', - 'crimson' -]; -/** - * Currently only WebKit-based Web Inspectors, Firefox >= v31, - * and the Firebug extension (any Firefox version) are known - * to support "%c" CSS customizations. - * - * TODO: add a `localStorage` variable to explicitly enable/disable colors - */ +var isDescriptor = __webpack_require__(597); -function useColors() { - // NB: In an Electron preload script, document will be defined but not fully - // initialized. Since we know we're in Chrome, we'll just detect this case - // explicitly - if (typeof window !== 'undefined' && window.process && window.process.type === 'renderer') { - return true; +module.exports = function defineProperty(obj, prop, val) { + if (typeof obj !== 'object' && typeof obj !== 'function') { + throw new TypeError('expected an object or function.'); } - // is webkit? http://stackoverflow.com/a/16459606/376773 - // document is undefined in react-native: https://github.com/facebook/react-native/pull/1632 - return (typeof document !== 'undefined' && document.documentElement && document.documentElement.style && document.documentElement.style.WebkitAppearance) || - // is firebug? http://stackoverflow.com/a/398120/376773 - (typeof window !== 'undefined' && window.console && (window.console.firebug || (window.console.exception && window.console.table))) || - // is firefox >= v31? - // https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages - (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/) && parseInt(RegExp.$1, 10) >= 31) || - // double check webkit in userAgent just in case we are in a worker - (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/applewebkit\/(\d+)/)); -} - -/** - * Map %j to `JSON.stringify()`, since no Web Inspectors do that by default. - */ + if (typeof prop !== 'string') { + throw new TypeError('expected `prop` to be a string.'); + } -exports.formatters.j = function(v) { - try { - return JSON.stringify(v); - } catch (err) { - return '[UnexpectedJSONParseError]: ' + err.message; + if (isDescriptor(val) && ('set' in val || 'get' in val)) { + return Object.defineProperty(obj, prop, val); } + + return Object.defineProperty(obj, prop, { + configurable: true, + enumerable: false, + writable: true, + value: val + }); }; -/** - * Colorize log arguments if enabled. +/***/ }), +/* 597 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +/*! + * is-descriptor * - * @api public + * Copyright (c) 2015-2017, Jon Schlinkert. + * Released under the MIT License. */ -function formatArgs(args) { - var useColors = this.useColors; - args[0] = (useColors ? '%c' : '') - + this.namespace - + (useColors ? ' %c' : ' ') - + args[0] - + (useColors ? '%c ' : ' ') - + '+' + exports.humanize(this.diff); - if (!useColors) return; +var typeOf = __webpack_require__(598); +var isAccessor = __webpack_require__(599); +var isData = __webpack_require__(601); - var c = 'color: ' + this.color; - args.splice(1, 0, c, 'color: inherit') +module.exports = function isDescriptor(obj, key) { + if (typeOf(obj) !== 'object') { + return false; + } + if ('get' in obj) { + return isAccessor(obj, key); + } + return isData(obj, key); +}; - // the final "%c" is somewhat tricky, because there could be other - // arguments passed either before or after the %c, so we need to - // figure out the correct index to insert the CSS into - var index = 0; - var lastC = 0; - args[0].replace(/%[a-zA-Z%]/g, function(match) { - if ('%%' === match) return; - index++; - if ('%c' === match) { - // we only are interested in the *last* %c - // (the user may have provided their own) - lastC = index; - } - }); - args.splice(lastC, 0, c); -} +/***/ }), +/* 598 */ +/***/ (function(module, exports) { + +var toString = Object.prototype.toString; /** - * Invokes `console.log()` when available. - * No-op when `console.log` is not a "function". + * Get the native `typeof` a value. * - * @api public + * @param {*} `val` + * @return {*} Native javascript type */ -function log() { - // this hackery is required for IE8/9, where - // the `console.log` function doesn't have 'apply' - return 'object' === typeof console - && console.log - && Function.prototype.apply.call(console.log, console, arguments); -} +module.exports = function kindOf(val) { + var type = typeof val; -/** - * Save `namespaces`. - * - * @param {String} namespaces - * @api private - */ + // primitivies + if (type === 'undefined') { + return 'undefined'; + } + if (val === null) { + return 'null'; + } + if (val === true || val === false || val instanceof Boolean) { + return 'boolean'; + } + if (type === 'string' || val instanceof String) { + return 'string'; + } + if (type === 'number' || val instanceof Number) { + return 'number'; + } -function save(namespaces) { - try { - if (null == namespaces) { - exports.storage.removeItem('debug'); - } else { - exports.storage.debug = namespaces; + // functions + if (type === 'function' || val instanceof Function) { + if (typeof val.constructor.name !== 'undefined' && val.constructor.name.slice(0, 9) === 'Generator') { + return 'generatorfunction'; } - } catch(e) {} -} + return 'function'; + } -/** - * Load `namespaces`. - * - * @return {String} returns the previously persisted debug modes - * @api private - */ + // array + if (typeof Array.isArray !== 'undefined' && Array.isArray(val)) { + return 'array'; + } -function load() { - var r; - try { - r = exports.storage.debug; - } catch(e) {} + // check for instances of RegExp and Date before calling `toString` + if (val instanceof RegExp) { + return 'regexp'; + } + if (val instanceof Date) { + return 'date'; + } - // If debug isn't set in LS, and we're in Electron, try to load $DEBUG - if (!r && typeof process !== 'undefined' && 'env' in process) { - r = process.env.DEBUG; + // other objects + type = toString.call(val); + + if (type === '[object RegExp]') { + return 'regexp'; + } + if (type === '[object Date]') { + return 'date'; + } + if (type === '[object Arguments]') { + return 'arguments'; + } + if (type === '[object Error]') { + return 'error'; + } + if (type === '[object Promise]') { + return 'promise'; } - return r; -} + // buffer + if (isBuffer(val)) { + return 'buffer'; + } -/** - * Enable namespaces listed in `localStorage.debug` initially. - */ + // es6: Map, WeakMap, Set, WeakSet + if (type === '[object Set]') { + return 'set'; + } + if (type === '[object WeakSet]') { + return 'weakset'; + } + if (type === '[object Map]') { + return 'map'; + } + if (type === '[object WeakMap]') { + return 'weakmap'; + } + if (type === '[object Symbol]') { + return 'symbol'; + } + + if (type === '[object Map Iterator]') { + return 'mapiterator'; + } + if (type === '[object Set Iterator]') { + return 'setiterator'; + } + if (type === '[object String Iterator]') { + return 'stringiterator'; + } + if (type === '[object Array Iterator]') { + return 'arrayiterator'; + } + + // typed arrays + if (type === '[object Int8Array]') { + return 'int8array'; + } + if (type === '[object Uint8Array]') { + return 'uint8array'; + } + if (type === '[object Uint8ClampedArray]') { + return 'uint8clampedarray'; + } + if (type === '[object Int16Array]') { + return 'int16array'; + } + if (type === '[object Uint16Array]') { + return 'uint16array'; + } + if (type === '[object Int32Array]') { + return 'int32array'; + } + if (type === '[object Uint32Array]') { + return 'uint32array'; + } + if (type === '[object Float32Array]') { + return 'float32array'; + } + if (type === '[object Float64Array]') { + return 'float64array'; + } -exports.enable(load()); + // must be a plain object + return 'object'; +}; /** - * Localstorage attempts to return the localstorage. - * - * This is necessary because safari throws - * when a user disables cookies/localstorage - * and you attempt to access it. - * - * @return {LocalStorage} - * @api private + * If you need to support Safari 5-7 (8-10 yr-old browser), + * take a look at https://github.com/feross/is-buffer */ -function localstorage() { - try { - return window.localStorage; - } catch (e) {} +function isBuffer(val) { + return val.constructor + && typeof val.constructor.isBuffer === 'function' + && val.constructor.isBuffer(val); } /***/ }), -/* 608 */ +/* 599 */ /***/ (function(module, exports, __webpack_require__) { - -/** - * This is the common logic for both the Node.js and web browser - * implementations of `debug()`. +"use strict"; +/*! + * is-accessor-descriptor * - * Expose `debug()` as the module. + * Copyright (c) 2015, Jon Schlinkert. + * Licensed under the MIT License. */ -exports = module.exports = createDebug.debug = createDebug['default'] = createDebug; -exports.coerce = coerce; -exports.disable = disable; -exports.enable = enable; -exports.enabled = enabled; -exports.humanize = __webpack_require__(609); -/** - * The currently active debug mode names, and names to skip. - */ -exports.names = []; -exports.skips = []; +var typeOf = __webpack_require__(600); -/** - * Map of special "%n" handling functions, for the debug "format" argument. - * - * Valid key names are a single, lower or upper-case letter, i.e. "n" and "N". - */ +// accessor descriptor properties +var accessor = { + get: 'function', + set: 'function', + configurable: 'boolean', + enumerable: 'boolean' +}; -exports.formatters = {}; +function isAccessorDescriptor(obj, prop) { + if (typeof prop === 'string') { + var val = Object.getOwnPropertyDescriptor(obj, prop); + return typeof val !== 'undefined'; + } -/** - * Previous log timestamp. - */ + if (typeOf(obj) !== 'object') { + return false; + } -var prevTime; + if (has(obj, 'value') || has(obj, 'writable')) { + return false; + } -/** - * Select a color. - * @param {String} namespace - * @return {Number} - * @api private - */ + if (!has(obj, 'get') || typeof obj.get !== 'function') { + return false; + } -function selectColor(namespace) { - var hash = 0, i; + // tldr: it's valid to have "set" be undefined + // "set" might be undefined if `Object.getOwnPropertyDescriptor` + // was used to get the value, and only `get` was defined by the user + if (has(obj, 'set') && typeof obj[key] !== 'function' && typeof obj[key] !== 'undefined') { + return false; + } - for (i in namespace) { - hash = ((hash << 5) - hash) + namespace.charCodeAt(i); - hash |= 0; // Convert to 32bit integer + for (var key in obj) { + if (!accessor.hasOwnProperty(key)) { + continue; + } + + if (typeOf(obj[key]) === accessor[key]) { + continue; + } + + if (typeof obj[key] !== 'undefined') { + return false; + } } + return true; +} - return exports.colors[Math.abs(hash) % exports.colors.length]; +function has(obj, key) { + return {}.hasOwnProperty.call(obj, key); } /** - * Create a debugger with the given `namespace`. - * - * @param {String} namespace - * @return {Function} - * @api public + * Expose `isAccessorDescriptor` */ -function createDebug(namespace) { +module.exports = isAccessorDescriptor; - function debug() { - // disabled? - if (!debug.enabled) return; - var self = debug; +/***/ }), +/* 600 */ +/***/ (function(module, exports, __webpack_require__) { - // set `diff` timestamp - var curr = +new Date(); - var ms = curr - (prevTime || curr); - self.diff = ms; - self.prev = prevTime; - self.curr = curr; - prevTime = curr; +var isBuffer = __webpack_require__(560); +var toString = Object.prototype.toString; - // turn the `arguments` into a proper Array - var args = new Array(arguments.length); - for (var i = 0; i < args.length; i++) { - args[i] = arguments[i]; - } +/** + * Get the native `typeof` a value. + * + * @param {*} `val` + * @return {*} Native javascript type + */ - args[0] = exports.coerce(args[0]); +module.exports = function kindOf(val) { + // primitivies + if (typeof val === 'undefined') { + return 'undefined'; + } + if (val === null) { + return 'null'; + } + if (val === true || val === false || val instanceof Boolean) { + return 'boolean'; + } + if (typeof val === 'string' || val instanceof String) { + return 'string'; + } + if (typeof val === 'number' || val instanceof Number) { + return 'number'; + } - if ('string' !== typeof args[0]) { - // anything else let's inspect with %O - args.unshift('%O'); - } + // functions + if (typeof val === 'function' || val instanceof Function) { + return 'function'; + } - // apply any `formatters` transformations - var index = 0; - args[0] = args[0].replace(/%([a-zA-Z%])/g, function(match, format) { - // if we encounter an escaped % then don't increase the array index - if (match === '%%') return match; - index++; - var formatter = exports.formatters[format]; - if ('function' === typeof formatter) { - var val = args[index]; - match = formatter.call(self, val); + // array + if (typeof Array.isArray !== 'undefined' && Array.isArray(val)) { + return 'array'; + } - // now we need to remove `args[index]` since it's inlined in the `format` - args.splice(index, 1); - index--; - } - return match; - }); + // check for instances of RegExp and Date before calling `toString` + if (val instanceof RegExp) { + return 'regexp'; + } + if (val instanceof Date) { + return 'date'; + } - // apply env-specific formatting (colors, etc.) - exports.formatArgs.call(self, args); + // other objects + var type = toString.call(val); - var logFn = debug.log || exports.log || console.log.bind(console); - logFn.apply(self, args); + if (type === '[object RegExp]') { + return 'regexp'; + } + if (type === '[object Date]') { + return 'date'; + } + if (type === '[object Arguments]') { + return 'arguments'; + } + if (type === '[object Error]') { + return 'error'; } - debug.namespace = namespace; - debug.enabled = exports.enabled(namespace); - debug.useColors = exports.useColors(); - debug.color = selectColor(namespace); + // buffer + if (isBuffer(val)) { + return 'buffer'; + } - // env-specific initialization logic for debug instances - if ('function' === typeof exports.init) { - exports.init(debug); + // es6: Map, WeakMap, Set, WeakSet + if (type === '[object Set]') { + return 'set'; + } + if (type === '[object WeakSet]') { + return 'weakset'; + } + if (type === '[object Map]') { + return 'map'; + } + if (type === '[object WeakMap]') { + return 'weakmap'; + } + if (type === '[object Symbol]') { + return 'symbol'; } - return debug; -} + // typed arrays + if (type === '[object Int8Array]') { + return 'int8array'; + } + if (type === '[object Uint8Array]') { + return 'uint8array'; + } + if (type === '[object Uint8ClampedArray]') { + return 'uint8clampedarray'; + } + if (type === '[object Int16Array]') { + return 'int16array'; + } + if (type === '[object Uint16Array]') { + return 'uint16array'; + } + if (type === '[object Int32Array]') { + return 'int32array'; + } + if (type === '[object Uint32Array]') { + return 'uint32array'; + } + if (type === '[object Float32Array]') { + return 'float32array'; + } + if (type === '[object Float64Array]') { + return 'float64array'; + } -/** - * Enables a debug mode by namespaces. This can include modes - * separated by a colon and wildcards. + // must be a plain object + return 'object'; +}; + + +/***/ }), +/* 601 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +/*! + * is-data-descriptor * - * @param {String} namespaces - * @api public + * Copyright (c) 2015, Jon Schlinkert. + * Licensed under the MIT License. */ -function enable(namespaces) { - exports.save(namespaces); - exports.names = []; - exports.skips = []; - var split = (typeof namespaces === 'string' ? namespaces : '').split(/[\s,]+/); - var len = split.length; +var typeOf = __webpack_require__(602); - for (var i = 0; i < len; i++) { - if (!split[i]) continue; // ignore empty strings - namespaces = split[i].replace(/\*/g, '.*?'); - if (namespaces[0] === '-') { - exports.skips.push(new RegExp('^' + namespaces.substr(1) + '$')); - } else { - exports.names.push(new RegExp('^' + namespaces + '$')); - } +// data descriptor properties +var data = { + configurable: 'boolean', + enumerable: 'boolean', + writable: 'boolean' +}; + +function isDataDescriptor(obj, prop) { + if (typeOf(obj) !== 'object') { + return false; } -} -/** - * Disable debug output. - * - * @api public - */ + if (typeof prop === 'string') { + var val = Object.getOwnPropertyDescriptor(obj, prop); + return typeof val !== 'undefined'; + } -function disable() { - exports.enable(''); -} + if (!('value' in obj) && !('writable' in obj)) { + return false; + } -/** - * Returns true if the given mode name is enabled, false otherwise. - * - * @param {String} name - * @return {Boolean} - * @api public - */ + for (var key in obj) { + if (key === 'value') continue; -function enabled(name) { - var i, len; - for (i = 0, len = exports.skips.length; i < len; i++) { - if (exports.skips[i].test(name)) { - return false; + if (!data.hasOwnProperty(key)) { + continue; } - } - for (i = 0, len = exports.names.length; i < len; i++) { - if (exports.names[i].test(name)) { - return true; + + if (typeOf(obj[key]) === data[key]) { + continue; + } + + if (typeof obj[key] !== 'undefined') { + return false; } } - return false; + return true; } /** - * Coerce `val`. - * - * @param {Mixed} val - * @return {Mixed} - * @api private + * Expose `isDataDescriptor` */ -function coerce(val) { - if (val instanceof Error) return val.stack || val.message; - return val; -} +module.exports = isDataDescriptor; /***/ }), -/* 609 */ -/***/ (function(module, exports) { - -/** - * Helpers. - */ +/* 602 */ +/***/ (function(module, exports, __webpack_require__) { -var s = 1000; -var m = s * 60; -var h = m * 60; -var d = h * 24; -var y = d * 365.25; +var isBuffer = __webpack_require__(560); +var toString = Object.prototype.toString; /** - * Parse or format the given `val`. - * - * Options: - * - * - `long` verbose formatting [false] + * Get the native `typeof` a value. * - * @param {String|Number} val - * @param {Object} [options] - * @throws {Error} throw an error if val is not a non-empty string or a number - * @return {String|Number} - * @api public + * @param {*} `val` + * @return {*} Native javascript type */ -module.exports = function(val, options) { - options = options || {}; - var type = typeof val; - if (type === 'string' && val.length > 0) { - return parse(val); - } else if (type === 'number' && isNaN(val) === false) { - return options.long ? fmtLong(val) : fmtShort(val); +module.exports = function kindOf(val) { + // primitivies + if (typeof val === 'undefined') { + return 'undefined'; + } + if (val === null) { + return 'null'; + } + if (val === true || val === false || val instanceof Boolean) { + return 'boolean'; + } + if (typeof val === 'string' || val instanceof String) { + return 'string'; + } + if (typeof val === 'number' || val instanceof Number) { + return 'number'; } - throw new Error( - 'val is not a non-empty string or a valid number. val=' + - JSON.stringify(val) - ); -}; -/** - * Parse the given `str` and return milliseconds. - * - * @param {String} str - * @return {Number} - * @api private - */ + // functions + if (typeof val === 'function' || val instanceof Function) { + return 'function'; + } -function parse(str) { - str = String(str); - if (str.length > 100) { - return; + // array + if (typeof Array.isArray !== 'undefined' && Array.isArray(val)) { + return 'array'; } - var match = /^((?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|years?|yrs?|y)?$/i.exec( - str - ); - if (!match) { - return; + + // check for instances of RegExp and Date before calling `toString` + if (val instanceof RegExp) { + return 'regexp'; } - var n = parseFloat(match[1]); - var type = (match[2] || 'ms').toLowerCase(); - switch (type) { - case 'years': - case 'year': - case 'yrs': - case 'yr': - case 'y': - return n * y; - case 'days': - case 'day': - case 'd': - return n * d; - case 'hours': - case 'hour': - case 'hrs': - case 'hr': - case 'h': - return n * h; - case 'minutes': - case 'minute': - case 'mins': - case 'min': - case 'm': - return n * m; - case 'seconds': - case 'second': - case 'secs': - case 'sec': - case 's': - return n * s; - case 'milliseconds': - case 'millisecond': - case 'msecs': - case 'msec': - case 'ms': - return n; - default: - return undefined; + if (val instanceof Date) { + return 'date'; } -} -/** - * Short format for `ms`. - * - * @param {Number} ms - * @return {String} - * @api private - */ + // other objects + var type = toString.call(val); + + if (type === '[object RegExp]') { + return 'regexp'; + } + if (type === '[object Date]') { + return 'date'; + } + if (type === '[object Arguments]') { + return 'arguments'; + } + if (type === '[object Error]') { + return 'error'; + } + + // buffer + if (isBuffer(val)) { + return 'buffer'; + } + + // es6: Map, WeakMap, Set, WeakSet + if (type === '[object Set]') { + return 'set'; + } + if (type === '[object WeakSet]') { + return 'weakset'; + } + if (type === '[object Map]') { + return 'map'; + } + if (type === '[object WeakMap]') { + return 'weakmap'; + } + if (type === '[object Symbol]') { + return 'symbol'; + } -function fmtShort(ms) { - if (ms >= d) { - return Math.round(ms / d) + 'd'; + // typed arrays + if (type === '[object Int8Array]') { + return 'int8array'; } - if (ms >= h) { - return Math.round(ms / h) + 'h'; + if (type === '[object Uint8Array]') { + return 'uint8array'; } - if (ms >= m) { - return Math.round(ms / m) + 'm'; + if (type === '[object Uint8ClampedArray]') { + return 'uint8clampedarray'; } - if (ms >= s) { - return Math.round(ms / s) + 's'; + if (type === '[object Int16Array]') { + return 'int16array'; } - return ms + 'ms'; -} - -/** - * Long format for `ms`. - * - * @param {Number} ms - * @return {String} - * @api private - */ - -function fmtLong(ms) { - return plural(ms, d, 'day') || - plural(ms, h, 'hour') || - plural(ms, m, 'minute') || - plural(ms, s, 'second') || - ms + ' ms'; -} - -/** - * Pluralization helper. - */ - -function plural(ms, n, name) { - if (ms < n) { - return; + if (type === '[object Uint16Array]') { + return 'uint16array'; } - if (ms < n * 1.5) { - return Math.floor(ms / n) + ' ' + name; + if (type === '[object Int32Array]') { + return 'int32array'; } - return Math.ceil(ms / n) + ' ' + name + 's'; -} + if (type === '[object Uint32Array]') { + return 'uint32array'; + } + if (type === '[object Float32Array]') { + return 'float32array'; + } + if (type === '[object Float64Array]') { + return 'float64array'; + } + + // must be a plain object + return 'object'; +}; /***/ }), -/* 610 */ +/* 603 */ /***/ (function(module, exports, __webpack_require__) { -/** - * Module dependencies. - */ - -var tty = __webpack_require__(121); -var util = __webpack_require__(111); - -/** - * This is the Node.js implementation of `debug()`. +"use strict"; +/*! + * static-extend * - * Expose `debug()` as the module. + * Copyright (c) 2016, Jon Schlinkert. + * Licensed under the MIT License. */ -exports = module.exports = __webpack_require__(608); -exports.init = init; -exports.log = log; -exports.formatArgs = formatArgs; -exports.save = save; -exports.load = load; -exports.useColors = useColors; -/** - * Colors. - */ -exports.colors = [6, 2, 3, 4, 5, 1]; +var copy = __webpack_require__(604); +var define = __webpack_require__(596); +var util = __webpack_require__(112); /** - * Build up the default `inspectOpts` object from the environment variables. + * Returns a function for extending the static properties, + * prototype properties, and descriptors from the `Parent` + * constructor onto `Child` constructors. * - * $ DEBUG_COLORS=no DEBUG_DEPTH=10 DEBUG_SHOW_HIDDEN=enabled node script.js + * ```js + * var extend = require('static-extend'); + * Parent.extend = extend(Parent); + * + * // optionally pass a custom merge function as the second arg + * Parent.extend = extend(Parent, function(Child) { + * Child.prototype.mixin = function(key, val) { + * Child.prototype[key] = val; + * }; + * }); + * + * // extend "child" constructors + * Parent.extend(Child); + * + * // optionally define prototype methods as the second arg + * Parent.extend(Child, { + * foo: function() {}, + * bar: function() {} + * }); + * ``` + * @param {Function} `Parent` Parent ctor + * @param {Function} `extendFn` Optional extend function for handling any necessary custom merging. Useful when updating methods that require a specific prototype. + * @param {Function} `Child` Child ctor + * @param {Object} `proto` Optionally pass additional prototype properties to inherit. + * @return {Object} + * @api public */ -exports.inspectOpts = Object.keys(process.env).filter(function (key) { - return /^debug_/i.test(key); -}).reduce(function (obj, key) { - // camel-case - var prop = key - .substring(6) - .toLowerCase() - .replace(/_([a-z])/g, function (_, k) { return k.toUpperCase() }); +function extend(Parent, extendFn) { + if (typeof Parent !== 'function') { + throw new TypeError('expected Parent to be a function.'); + } - // coerce string value into JS value - var val = process.env[key]; - if (/^(yes|on|true|enabled)$/i.test(val)) val = true; - else if (/^(no|off|false|disabled)$/i.test(val)) val = false; - else if (val === 'null') val = null; - else val = Number(val); + return function(Ctor, proto) { + if (typeof Ctor !== 'function') { + throw new TypeError('expected Ctor to be a function.'); + } - obj[prop] = val; - return obj; -}, {}); + util.inherits(Ctor, Parent); + copy(Ctor, Parent); -/** - * The file descriptor to write the `debug()` calls to. - * Set the `DEBUG_FD` env variable to override with another value. i.e.: - * - * $ DEBUG_FD=3 node script.js 3>debug.log - */ + // proto can be null or a plain object + if (typeof proto === 'object') { + var obj = Object.create(proto); -var fd = parseInt(process.env.DEBUG_FD, 10) || 2; + for (var k in obj) { + Ctor.prototype[k] = obj[k]; + } + } -if (1 !== fd && 2 !== fd) { - util.deprecate(function(){}, 'except for stderr(2) and stdout(1), any other usage of DEBUG_FD is deprecated. Override debug.log if you want to use a different log function (https://git.io/debug_fd)')() -} + // keep a reference to the parent prototype + define(Ctor.prototype, '_parent_', { + configurable: true, + set: function() {}, + get: function() { + return Parent.prototype; + } + }); -var stream = 1 === fd ? process.stdout : - 2 === fd ? process.stderr : - createWritableStdioStream(fd); + if (typeof extendFn === 'function') { + extendFn(Ctor, Parent); + } + + Ctor.extend = extend(Ctor, extendFn); + }; +}; /** - * Is stdout a TTY? Colored output is enabled when `true`. + * Expose `extend` */ -function useColors() { - return 'colors' in exports.inspectOpts - ? Boolean(exports.inspectOpts.colors) - : tty.isatty(fd); -} +module.exports = extend; -/** - * Map %o to `util.inspect()`, all on a single line. - */ -exports.formatters.o = function(v) { - this.inspectOpts.colors = this.useColors; - return util.inspect(v, this.inspectOpts) - .split('\n').map(function(str) { - return str.trim() - }).join(' '); -}; +/***/ }), +/* 604 */ +/***/ (function(module, exports, __webpack_require__) { -/** - * Map %o to `util.inspect()`, allowing multiple lines if needed. - */ +"use strict"; -exports.formatters.O = function(v) { - this.inspectOpts.colors = this.useColors; - return util.inspect(v, this.inspectOpts); -}; + +var typeOf = __webpack_require__(559); +var copyDescriptor = __webpack_require__(605); +var define = __webpack_require__(596); /** - * Adds ANSI color escape codes if enabled. + * Copy static properties, prototype properties, and descriptors from one object to another. + * + * ```js + * function App() {} + * var proto = App.prototype; + * App.prototype.set = function() {}; + * App.prototype.get = function() {}; * + * var obj = {}; + * copy(obj, proto); + * ``` + * @param {Object} `receiver` + * @param {Object} `provider` + * @param {String|Array} `omit` One or more properties to omit + * @return {Object} * @api public */ -function formatArgs(args) { - var name = this.namespace; - var useColors = this.useColors; +function copy(receiver, provider, omit) { + if (!isObject(receiver)) { + throw new TypeError('expected receiving object to be an object.'); + } + if (!isObject(provider)) { + throw new TypeError('expected providing object to be an object.'); + } - if (useColors) { - var c = this.color; - var prefix = ' \u001b[3' + c + ';1m' + name + ' ' + '\u001b[0m'; + var props = nativeKeys(provider); + var keys = Object.keys(provider); + var len = props.length; + omit = arrayify(omit); - args[0] = prefix + args[0].split('\n').join('\n' + prefix); - args.push('\u001b[3' + c + 'm+' + exports.humanize(this.diff) + '\u001b[0m'); - } else { - args[0] = new Date().toUTCString() - + ' ' + name + ' ' + args[0]; + while (len--) { + var key = props[len]; + + if (has(keys, key)) { + define(receiver, key, provider[key]); + } else if (!(key in receiver) && !has(omit, key)) { + copyDescriptor(receiver, provider, key); + } } -} +}; /** - * Invokes `util.format()` with the specified arguments and writes to `stream`. + * Return true if the given value is an object or function */ -function log() { - return stream.write(util.format.apply(util, arguments) + '\n'); +function isObject(val) { + return typeOf(val) === 'object' || typeof val === 'function'; } /** - * Save `namespaces`. + * Returns true if an array has any of the given elements, or an + * object has any of the give keys. * - * @param {String} namespaces - * @api private + * ```js + * has(['a', 'b', 'c'], 'c'); + * //=> true + * + * has(['a', 'b', 'c'], ['c', 'z']); + * //=> true + * + * has({a: 'b', c: 'd'}, ['c', 'z']); + * //=> true + * ``` + * @param {Object} `obj` + * @param {String|Array} `val` + * @return {Boolean} */ -function save(namespaces) { - if (null == namespaces) { - // If you set a process.env field to null or undefined, it gets cast to the - // string 'null' or 'undefined'. Just delete instead. - delete process.env.DEBUG; - } else { - process.env.DEBUG = namespaces; +function has(obj, val) { + val = arrayify(val); + var len = val.length; + + if (isObject(obj)) { + for (var key in obj) { + if (val.indexOf(key) > -1) { + return true; + } + } + + var keys = nativeKeys(obj); + return has(keys, val); + } + + if (Array.isArray(obj)) { + var arr = obj; + while (len--) { + if (arr.indexOf(val[len]) > -1) { + return true; + } + } + return false; } + + throw new TypeError('expected an array or object.'); } /** - * Load `namespaces`. + * Cast the given value to an array. * - * @return {String} returns the previously persisted debug modes - * @api private + * ```js + * arrayify('foo'); + * //=> ['foo'] + * + * arrayify(['foo']); + * //=> ['foo'] + * ``` + * + * @param {String|Array} `val` + * @return {Array} */ -function load() { - return process.env.DEBUG; +function arrayify(val) { + return val ? (Array.isArray(val) ? val : [val]) : []; } /** - * Copied from `node/src/node.js`. + * Returns true if a value has a `contructor` * - * XXX: It's lame that node doesn't expose this API out-of-the-box. It also - * relies on the undocumented `tty_wrap.guessHandleType()` which is also lame. + * ```js + * hasConstructor({}); + * //=> true + * + * hasConstructor(Object.create(null)); + * //=> false + * ``` + * @param {Object} `value` + * @return {Boolean} */ -function createWritableStdioStream (fd) { - var stream; - var tty_wrap = process.binding('tty_wrap'); +function hasConstructor(val) { + return isObject(val) && typeof val.constructor !== 'undefined'; +} - // Note stream._type is used for test-module-load-list.js +/** + * Get the native `ownPropertyNames` from the constructor of the + * given `object`. An empty array is returned if the object does + * not have a constructor. + * + * ```js + * nativeKeys({a: 'b', b: 'c', c: 'd'}) + * //=> ['a', 'b', 'c'] + * + * nativeKeys(function(){}) + * //=> ['length', 'caller'] + * ``` + * + * @param {Object} `obj` Object that has a `constructor`. + * @return {Array} Array of keys. + */ - switch (tty_wrap.guessHandleType(fd)) { - case 'TTY': - stream = new tty.WriteStream(fd); - stream._type = 'tty'; +function nativeKeys(val) { + if (!hasConstructor(val)) return []; + return Object.getOwnPropertyNames(val); +} - // Hack to have stream not keep the event loop alive. - // See https://github.com/joyent/node/issues/1726 - if (stream._handle && stream._handle.unref) { - stream._handle.unref(); - } - break; +/** + * Expose `copy` + */ - case 'FILE': - var fs = __webpack_require__(133); - stream = new fs.SyncWriteStream(fd, { autoClose: false }); - stream._type = 'fs'; - break; +module.exports = copy; - case 'PIPE': - case 'TCP': - var net = __webpack_require__(611); - stream = new net.Socket({ - fd: fd, - readable: false, - writable: true - }); +/** + * Expose `copy.has` for tests + */ - // FIXME Should probably have an option in net.Socket to create a - // stream from an existing fd which is writable only. But for now - // we'll just add this hack and set the `readable` member to false. - // Test: ./node test/fixtures/echo.js < /etc/passwd - stream.readable = false; - stream.read = null; - stream._type = 'pipe'; +module.exports.has = has; - // FIXME Hack to have stream not keep the event loop alive. - // See https://github.com/joyent/node/issues/1726 - if (stream._handle && stream._handle.unref) { - stream._handle.unref(); - } - break; - default: - // Probably an error on in uv_guess_handle() - throw new Error('Implement me. Unknown stream file type!'); - } +/***/ }), +/* 605 */ +/***/ (function(module, exports, __webpack_require__) { - // For supporting legacy API we put the FD here. - stream.fd = fd; +"use strict"; +/*! + * copy-descriptor + * + * Copyright (c) 2015, Jon Schlinkert. + * Licensed under the MIT License. + */ - stream._isStdio = true; - return stream; -} /** - * Init logic for `debug` instances. + * Copy a descriptor from one object to another. * - * Create a new `inspectOpts` object in case `useColors` is set - * differently for a particular `debug` instance. + * ```js + * function App() { + * this.cache = {}; + * } + * App.prototype.set = function(key, val) { + * this.cache[key] = val; + * return this; + * }; + * Object.defineProperty(App.prototype, 'count', { + * get: function() { + * return Object.keys(this.cache).length; + * } + * }); + * + * copy(App.prototype, 'count', 'len'); + * + * // create an instance + * var app = new App(); + * + * app.set('a', true); + * app.set('b', true); + * app.set('c', true); + * + * console.log(app.count); + * //=> 3 + * console.log(app.len); + * //=> 3 + * ``` + * @name copy + * @param {Object} `receiver` The target object + * @param {Object} `provider` The provider object + * @param {String} `from` The key to copy on provider. + * @param {String} `to` Optionally specify a new key name to use. + * @return {Object} + * @api public */ -function init (debug) { - debug.inspectOpts = {}; +module.exports = function copyDescriptor(receiver, provider, from, to) { + if (!isObject(provider) && typeof provider !== 'function') { + to = from; + from = provider; + provider = receiver; + } + if (!isObject(receiver) && typeof receiver !== 'function') { + throw new TypeError('expected the first argument to be an object'); + } + if (!isObject(provider) && typeof provider !== 'function') { + throw new TypeError('expected provider to be an object'); + } - var keys = Object.keys(exports.inspectOpts); - for (var i = 0; i < keys.length; i++) { - debug.inspectOpts[keys[i]] = exports.inspectOpts[keys[i]]; + if (typeof to !== 'string') { + to = from; + } + if (typeof from !== 'string') { + throw new TypeError('expected key to be a string'); } -} -/** - * Enable namespaces listed in `process.env.DEBUG` initially. - */ + if (!(from in provider)) { + throw new Error('property "' + from + '" does not exist'); + } -exports.enable(load()); + var val = Object.getOwnPropertyDescriptor(provider, from); + if (val) Object.defineProperty(receiver, to, val); +}; +function isObject(val) { + return {}.toString.call(val) === '[object Object]'; +} -/***/ }), -/* 611 */ -/***/ (function(module, exports) { -module.exports = require("net"); /***/ }), -/* 612 */ +/* 606 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -/** - * Module dependencies - */ - -exports.extend = __webpack_require__(535); -exports.SourceMap = __webpack_require__(613); -exports.sourceMapResolve = __webpack_require__(624); +var use = __webpack_require__(607); +var define = __webpack_require__(596); +var debug = __webpack_require__(609)('snapdragon:compiler'); +var utils = __webpack_require__(615); /** - * Convert backslash in the given string to forward slashes + * Create a new `Compiler` with the given `options`. + * @param {Object} `options` */ -exports.unixify = function(fp) { - return fp.split(/\\+/).join('/'); -}; +function Compiler(options, state) { + debug('initializing', __filename); + this.options = utils.extend({source: 'string'}, options); + this.state = state || {}; + this.compilers = {}; + this.output = ''; + this.set('eos', function(node) { + return this.emit(node.val, node); + }); + this.set('noop', function(node) { + return this.emit(node.val, node); + }); + this.set('bos', function(node) { + return this.emit(node.val, node); + }); + use(this); +} /** - * Return true if `val` is a non-empty string - * - * @param {String} `str` - * @return {Boolean} + * Prototype methods */ -exports.isString = function(str) { - return str && typeof str === 'string'; -}; - -/** - * Cast `val` to an array - * @return {Array} - */ +Compiler.prototype = { -exports.arrayify = function(val) { - if (typeof val === 'string') return [val]; - return val ? (Array.isArray(val) ? val : [val]) : []; -}; + /** + * Throw an error message with details including the cursor position. + * @param {String} `msg` Message to use in the Error. + */ -/** - * Get the last `n` element from the given `array` - * @param {Array} `array` - * @return {*} - */ + error: function(msg, node) { + var pos = node.position || {start: {column: 0}}; + var message = this.options.source + ' column:' + pos.start.column + ': ' + msg; -exports.last = function(arr, n) { - return arr[arr.length - (n || 1)]; -}; + var err = new Error(message); + err.reason = msg; + err.column = pos.start.column; + err.source = this.pattern; + if (this.options.silent) { + this.errors.push(err); + } else { + throw err; + } + }, -/***/ }), -/* 613 */ -/***/ (function(module, exports, __webpack_require__) { + /** + * Define a non-enumberable property on the `Compiler` instance. + * + * ```js + * compiler.define('foo', 'bar'); + * ``` + * @name .define + * @param {String} `key` propery name + * @param {any} `val` property value + * @return {Object} Returns the Compiler instance for chaining. + * @api public + */ -/* - * Copyright 2009-2011 Mozilla Foundation and contributors - * Licensed under the New BSD license. See LICENSE.txt or: - * http://opensource.org/licenses/BSD-3-Clause - */ -exports.SourceMapGenerator = __webpack_require__(614).SourceMapGenerator; -exports.SourceMapConsumer = __webpack_require__(620).SourceMapConsumer; -exports.SourceNode = __webpack_require__(623).SourceNode; + define: function(key, val) { + define(this, key, val); + return this; + }, + /** + * Emit `node.val` + */ -/***/ }), -/* 614 */ -/***/ (function(module, exports, __webpack_require__) { + emit: function(str, node) { + this.output += str; + return str; + }, -/* -*- Mode: js; js-indent-level: 2; -*- */ -/* - * Copyright 2011 Mozilla Foundation and contributors - * Licensed under the New BSD license. See LICENSE or: - * http://opensource.org/licenses/BSD-3-Clause - */ + /** + * Add a compiler `fn` with the given `name` + */ -var base64VLQ = __webpack_require__(615); -var util = __webpack_require__(617); -var ArraySet = __webpack_require__(618).ArraySet; -var MappingList = __webpack_require__(619).MappingList; + set: function(name, fn) { + this.compilers[name] = fn; + return this; + }, -/** - * An instance of the SourceMapGenerator represents a source map which is - * being built incrementally. You may pass an object with the following - * properties: - * - * - file: The filename of the generated source. - * - sourceRoot: A root for all relative URLs in this source map. - */ -function SourceMapGenerator(aArgs) { - if (!aArgs) { - aArgs = {}; - } - this._file = util.getArg(aArgs, 'file', null); - this._sourceRoot = util.getArg(aArgs, 'sourceRoot', null); - this._skipValidation = util.getArg(aArgs, 'skipValidation', false); - this._sources = new ArraySet(); - this._names = new ArraySet(); - this._mappings = new MappingList(); - this._sourcesContents = null; -} + /** + * Get compiler `name`. + */ -SourceMapGenerator.prototype._version = 3; + get: function(name) { + return this.compilers[name]; + }, -/** - * Creates a new SourceMapGenerator based on a SourceMapConsumer - * - * @param aSourceMapConsumer The SourceMap. - */ -SourceMapGenerator.fromSourceMap = - function SourceMapGenerator_fromSourceMap(aSourceMapConsumer) { - var sourceRoot = aSourceMapConsumer.sourceRoot; - var generator = new SourceMapGenerator({ - file: aSourceMapConsumer.file, - sourceRoot: sourceRoot - }); - aSourceMapConsumer.eachMapping(function (mapping) { - var newMapping = { - generated: { - line: mapping.generatedLine, - column: mapping.generatedColumn - } - }; + /** + * Get the previous AST node. + */ - if (mapping.source != null) { - newMapping.source = mapping.source; - if (sourceRoot != null) { - newMapping.source = util.relative(sourceRoot, newMapping.source); - } + prev: function(n) { + return this.ast.nodes[this.idx - (n || 1)] || { type: 'bos', val: '' }; + }, - newMapping.original = { - line: mapping.originalLine, - column: mapping.originalColumn - }; + /** + * Get the next AST node. + */ - if (mapping.name != null) { - newMapping.name = mapping.name; - } - } + next: function(n) { + return this.ast.nodes[this.idx + (n || 1)] || { type: 'eos', val: '' }; + }, - generator.addMapping(newMapping); - }); - aSourceMapConsumer.sources.forEach(function (sourceFile) { - var content = aSourceMapConsumer.sourceContentFor(sourceFile); - if (content != null) { - generator.setSourceContent(sourceFile, content); - } - }); - return generator; - }; + /** + * Visit `node`. + */ -/** - * Add a single mapping from original source line and column to the generated - * source's line and column for this source map being created. The mapping - * object should have the following properties: - * - * - generated: An object with the generated line and column positions. - * - original: An object with the original line and column positions. - * - source: The original source file (relative to the sourceRoot). - * - name: An optional original token name for this mapping. - */ -SourceMapGenerator.prototype.addMapping = - function SourceMapGenerator_addMapping(aArgs) { - var generated = util.getArg(aArgs, 'generated'); - var original = util.getArg(aArgs, 'original', null); - var source = util.getArg(aArgs, 'source', null); - var name = util.getArg(aArgs, 'name', null); + visit: function(node, nodes, i) { + var fn = this.compilers[node.type]; + this.idx = i; - if (!this._skipValidation) { - this._validateMapping(generated, original, source, name); + if (typeof fn !== 'function') { + throw this.error('compiler "' + node.type + '" is not registered', node); } + return fn.call(this, node, nodes, i); + }, - if (source != null) { - source = String(source); - if (!this._sources.has(source)) { - this._sources.add(source); - } - } + /** + * Map visit over array of `nodes`. + */ - if (name != null) { - name = String(name); - if (!this._names.has(name)) { - this._names.add(name); - } + mapVisit: function(nodes) { + if (!Array.isArray(nodes)) { + throw new TypeError('expected an array'); + } + var len = nodes.length; + var idx = -1; + while (++idx < len) { + this.visit(nodes[idx], nodes, idx); } + return this; + }, - this._mappings.add({ - generatedLine: generated.line, - generatedColumn: generated.column, - originalLine: original != null && original.line, - originalColumn: original != null && original.column, - source: source, - name: name - }); - }; + /** + * Compile `ast`. + */ -/** - * Set the source content for a source file. - */ -SourceMapGenerator.prototype.setSourceContent = - function SourceMapGenerator_setSourceContent(aSourceFile, aSourceContent) { - var source = aSourceFile; - if (this._sourceRoot != null) { - source = util.relative(this._sourceRoot, source); - } + compile: function(ast, options) { + var opts = utils.extend({}, this.options, options); + this.ast = ast; + this.parsingErrors = this.ast.errors; + this.output = ''; - if (aSourceContent != null) { - // Add the source content to the _sourcesContents map. - // Create a new _sourcesContents map if the property is null. - if (!this._sourcesContents) { - this._sourcesContents = Object.create(null); - } - this._sourcesContents[util.toSetString(source)] = aSourceContent; - } else if (this._sourcesContents) { - // Remove the source file from the _sourcesContents map. - // If the _sourcesContents map is empty, set the property to null. - delete this._sourcesContents[util.toSetString(source)]; - if (Object.keys(this._sourcesContents).length === 0) { - this._sourcesContents = null; - } + // source map support + if (opts.sourcemap) { + var sourcemaps = __webpack_require__(634); + sourcemaps(this); + this.mapVisit(this.ast.nodes); + this.applySourceMaps(); + this.map = opts.sourcemap === 'generator' ? this.map : this.map.toJSON(); + return this; } - }; + + this.mapVisit(this.ast.nodes); + return this; + } +}; /** - * Applies the mappings of a sub-source-map for a specific source file to the - * source map being generated. Each mapping to the supplied source file is - * rewritten using the supplied source map. Note: The resolution for the - * resulting mappings is the minimium of this map and the supplied map. - * - * @param aSourceMapConsumer The source map to be applied. - * @param aSourceFile Optional. The filename of the source file. - * If omitted, SourceMapConsumer's file property will be used. - * @param aSourceMapPath Optional. The dirname of the path to the source map - * to be applied. If relative, it is relative to the SourceMapConsumer. - * This parameter is needed when the two source maps aren't in the same - * directory, and the source map to be applied contains relative source - * paths. If so, those relative source paths need to be rewritten - * relative to the SourceMapGenerator. + * Expose `Compiler` */ -SourceMapGenerator.prototype.applySourceMap = - function SourceMapGenerator_applySourceMap(aSourceMapConsumer, aSourceFile, aSourceMapPath) { - var sourceFile = aSourceFile; - // If aSourceFile is omitted, we will use the file property of the SourceMap - if (aSourceFile == null) { - if (aSourceMapConsumer.file == null) { - throw new Error( - 'SourceMapGenerator.prototype.applySourceMap requires either an explicit source file, ' + - 'or the source map\'s "file" property. Both were omitted.' - ); - } - sourceFile = aSourceMapConsumer.file; - } - var sourceRoot = this._sourceRoot; - // Make "sourceFile" relative if an absolute Url is passed. - if (sourceRoot != null) { - sourceFile = util.relative(sourceRoot, sourceFile); - } - // Applying the SourceMap can add and remove items from the sources and - // the names array. - var newSources = new ArraySet(); - var newNames = new ArraySet(); - - // Find mappings for the "sourceFile" - this._mappings.unsortedForEach(function (mapping) { - if (mapping.source === sourceFile && mapping.originalLine != null) { - // Check if it can be mapped by the source map, then update the mapping. - var original = aSourceMapConsumer.originalPositionFor({ - line: mapping.originalLine, - column: mapping.originalColumn - }); - if (original.source != null) { - // Copy mapping - mapping.source = original.source; - if (aSourceMapPath != null) { - mapping.source = util.join(aSourceMapPath, mapping.source) - } - if (sourceRoot != null) { - mapping.source = util.relative(sourceRoot, mapping.source); - } - mapping.originalLine = original.line; - mapping.originalColumn = original.column; - if (original.name != null) { - mapping.name = original.name; - } - } - } - - var source = mapping.source; - if (source != null && !newSources.has(source)) { - newSources.add(source); - } - var name = mapping.name; - if (name != null && !newNames.has(name)) { - newNames.add(name); - } +module.exports = Compiler; - }, this); - this._sources = newSources; - this._names = newNames; - // Copy sourcesContents of applied map. - aSourceMapConsumer.sources.forEach(function (sourceFile) { - var content = aSourceMapConsumer.sourceContentFor(sourceFile); - if (content != null) { - if (aSourceMapPath != null) { - sourceFile = util.join(aSourceMapPath, sourceFile); - } - if (sourceRoot != null) { - sourceFile = util.relative(sourceRoot, sourceFile); - } - this.setSourceContent(sourceFile, content); - } - }, this); - }; +/***/ }), +/* 607 */ +/***/ (function(module, exports, __webpack_require__) { -/** - * A mapping can have one of the three levels of data: - * - * 1. Just the generated position. - * 2. The Generated position, original position, and original source. - * 3. Generated and original position, original source, as well as a name - * token. +"use strict"; +/*! + * use * - * To maintain consistency, we validate that any new mapping being added falls - * in to one of these categories. + * Copyright (c) 2015, 2017, Jon Schlinkert. + * Released under the MIT License. */ -SourceMapGenerator.prototype._validateMapping = - function SourceMapGenerator_validateMapping(aGenerated, aOriginal, aSource, - aName) { - // When aOriginal is truthy but has empty values for .line and .column, - // it is most likely a programmer error. In this case we throw a very - // specific error message to try to guide them the right way. - // For example: https://github.com/Polymer/polymer-bundler/pull/519 - if (aOriginal && typeof aOriginal.line !== 'number' && typeof aOriginal.column !== 'number') { - throw new Error( - 'original.line and original.column are not numbers -- you probably meant to omit ' + - 'the original mapping entirely and only map the generated position. If so, pass ' + - 'null for the original mapping instead of an object with empty or null values.' - ); - } - if (aGenerated && 'line' in aGenerated && 'column' in aGenerated - && aGenerated.line > 0 && aGenerated.column >= 0 - && !aOriginal && !aSource && !aName) { - // Case 1. - return; - } - else if (aGenerated && 'line' in aGenerated && 'column' in aGenerated - && aOriginal && 'line' in aOriginal && 'column' in aOriginal - && aGenerated.line > 0 && aGenerated.column >= 0 - && aOriginal.line > 0 && aOriginal.column >= 0 - && aSource) { - // Cases 2 and 3. - return; - } - else { - throw new Error('Invalid mapping: ' + JSON.stringify({ - generated: aGenerated, - source: aSource, - original: aOriginal, - name: aName - })); - } - }; -/** - * Serialize the accumulated mappings in to the stream of base 64 VLQs - * specified by the source map format. - */ -SourceMapGenerator.prototype._serializeMappings = - function SourceMapGenerator_serializeMappings() { - var previousGeneratedColumn = 0; - var previousGeneratedLine = 1; - var previousOriginalColumn = 0; - var previousOriginalLine = 0; - var previousName = 0; - var previousSource = 0; - var result = ''; - var next; - var mapping; - var nameIdx; - var sourceIdx; - var mappings = this._mappings.toArray(); - for (var i = 0, len = mappings.length; i < len; i++) { - mapping = mappings[i]; - next = '' +var utils = __webpack_require__(608); - if (mapping.generatedLine !== previousGeneratedLine) { - previousGeneratedColumn = 0; - while (mapping.generatedLine !== previousGeneratedLine) { - next += ';'; - previousGeneratedLine++; - } - } - else { - if (i > 0) { - if (!util.compareByGeneratedPositionsInflated(mapping, mappings[i - 1])) { - continue; - } - next += ','; - } - } +module.exports = function base(app, opts) { + if (!utils.isObject(app) && typeof app !== 'function') { + throw new TypeError('use: expect `app` be an object or function'); + } - next += base64VLQ.encode(mapping.generatedColumn - - previousGeneratedColumn); - previousGeneratedColumn = mapping.generatedColumn; + if (!utils.isObject(opts)) { + opts = {}; + } + + var prop = utils.isString(opts.prop) ? opts.prop : 'fns'; + if (!Array.isArray(app[prop])) { + utils.define(app, prop, []); + } + + /** + * Define a plugin function to be passed to use. The only + * parameter exposed to the plugin is `app`, the object or function. + * passed to `use(app)`. `app` is also exposed as `this` in plugins. + * + * Additionally, **if a plugin returns a function, the function will + * be pushed onto the `fns` array**, allowing the plugin to be + * called at a later point by the `run` method. + * + * ```js + * var use = require('use'); + * + * // define a plugin + * function foo(app) { + * // do stuff + * } + * + * var app = function(){}; + * use(app); + * + * // register plugins + * app.use(foo); + * app.use(bar); + * app.use(baz); + * ``` + * @name .use + * @param {Function} `fn` plugin function to call + * @api public + */ - if (mapping.source != null) { - sourceIdx = this._sources.indexOf(mapping.source); - next += base64VLQ.encode(sourceIdx - previousSource); - previousSource = sourceIdx; + utils.define(app, 'use', use); - // lines are stored 0-based in SourceMap spec version 3 - next += base64VLQ.encode(mapping.originalLine - 1 - - previousOriginalLine); - previousOriginalLine = mapping.originalLine - 1; + /** + * Run all plugins on `fns`. Any plugin that returns a function + * when called by `use` is pushed onto the `fns` array. + * + * ```js + * var config = {}; + * app.run(config); + * ``` + * @name .run + * @param {Object} `value` Object to be modified by plugins. + * @return {Object} Returns the object passed to `run` + * @api public + */ - next += base64VLQ.encode(mapping.originalColumn - - previousOriginalColumn); - previousOriginalColumn = mapping.originalColumn; + utils.define(app, 'run', function(val) { + if (!utils.isObject(val)) return; + decorate(val); - if (mapping.name != null) { - nameIdx = this._names.indexOf(mapping.name); - next += base64VLQ.encode(nameIdx - previousName); - previousName = nameIdx; - } - } + var self = this || app; + var fns = self[prop]; + var len = fns.length; + var idx = -1; - result += next; + while (++idx < len) { + val.use(fns[idx]); } + return val; + }); - return result; - }; - -SourceMapGenerator.prototype._generateSourcesContent = - function SourceMapGenerator_generateSourcesContent(aSources, aSourceRoot) { - return aSources.map(function (source) { - if (!this._sourcesContents) { - return null; - } - if (aSourceRoot != null) { - source = util.relative(aSourceRoot, source); - } - var key = util.toSetString(source); - return Object.prototype.hasOwnProperty.call(this._sourcesContents, key) - ? this._sourcesContents[key] - : null; - }, this); - }; + /** + * Call plugin `fn`. If a function is returned push it into the + * `fns` array to be called by the `run` method. + */ -/** - * Externalize the source map. - */ -SourceMapGenerator.prototype.toJSON = - function SourceMapGenerator_toJSON() { - var map = { - version: this._version, - sources: this._sources.toArray(), - names: this._names.toArray(), - mappings: this._serializeMappings() - }; - if (this._file != null) { - map.file = this._file; + function use(fn, options) { + if (typeof fn !== 'function') { + throw new TypeError('.use expects `fn` be a function'); } - if (this._sourceRoot != null) { - map.sourceRoot = this._sourceRoot; + + var self = this || app; + if (typeof opts.fn === 'function') { + opts.fn.call(self, self, options); } - if (this._sourcesContents) { - map.sourcesContent = this._generateSourcesContent(map.sources, map.sourceRoot); + + var plugin = fn.call(self, self); + if (typeof plugin === 'function') { + var fns = self[prop]; + fns.push(plugin); } + return self; + } - return map; - }; + /** + * Ensure the `.use` method exists on `val` + */ -/** - * Render the source map being generated to a string. - */ -SourceMapGenerator.prototype.toString = - function SourceMapGenerator_toString() { - return JSON.stringify(this.toJSON()); - }; + function decorate(val) { + if (!val.use || !val.run) { + base(val); + } + } -exports.SourceMapGenerator = SourceMapGenerator; + return app; +}; /***/ }), -/* 615 */ +/* 608 */ /***/ (function(module, exports, __webpack_require__) { -/* -*- Mode: js; js-indent-level: 2; -*- */ -/* - * Copyright 2011 Mozilla Foundation and contributors - * Licensed under the New BSD license. See LICENSE or: - * http://opensource.org/licenses/BSD-3-Clause - * - * Based on the Base 64 VLQ implementation in Closure Compiler: - * https://code.google.com/p/closure-compiler/source/browse/trunk/src/com/google/debugging/sourcemap/Base64VLQ.java - * - * Copyright 2011 The Closure Compiler Authors. All rights reserved. - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -var base64 = __webpack_require__(616); - -// A single base 64 digit can contain 6 bits of data. For the base 64 variable -// length quantities we use in the source map spec, the first bit is the sign, -// the next four bits are the actual value, and the 6th bit is the -// continuation bit. The continuation bit tells us whether there are more -// digits in this value following this digit. -// -// Continuation -// | Sign -// | | -// V V -// 101011 - -var VLQ_BASE_SHIFT = 5; - -// binary: 100000 -var VLQ_BASE = 1 << VLQ_BASE_SHIFT; +"use strict"; -// binary: 011111 -var VLQ_BASE_MASK = VLQ_BASE - 1; -// binary: 100000 -var VLQ_CONTINUATION_BIT = VLQ_BASE; +var utils = {}; -/** - * Converts from a two-complement value to a value where the sign bit is - * placed in the least significant bit. For example, as decimals: - * 1 becomes 2 (10 binary), -1 becomes 3 (11 binary) - * 2 becomes 4 (100 binary), -2 becomes 5 (101 binary) - */ -function toVLQSigned(aValue) { - return aValue < 0 - ? ((-aValue) << 1) + 1 - : (aValue << 1) + 0; -} -/** - * Converts to a two-complement value from a value where the sign bit is - * placed in the least significant bit. For example, as decimals: - * 2 (10 binary) becomes 1, 3 (11 binary) becomes -1 - * 4 (100 binary) becomes 2, 5 (101 binary) becomes -2 - */ -function fromVLQSigned(aValue) { - var isNegative = (aValue & 1) === 1; - var shifted = aValue >> 1; - return isNegative - ? -shifted - : shifted; -} /** - * Returns the base 64 VLQ encoded value. + * Lazily required module dependencies */ -exports.encode = function base64VLQ_encode(aValue) { - var encoded = ""; - var digit; - var vlq = toVLQSigned(aValue); +utils.define = __webpack_require__(596); +utils.isObject = __webpack_require__(534); - do { - digit = vlq & VLQ_BASE_MASK; - vlq >>>= VLQ_BASE_SHIFT; - if (vlq > 0) { - // There are still more digits in this value, so we must make sure the - // continuation bit is marked. - digit |= VLQ_CONTINUATION_BIT; - } - encoded += base64.encode(digit); - } while (vlq > 0); - return encoded; +utils.isString = function(val) { + return val && typeof val === 'string'; }; /** - * Decodes the next base 64 VLQ value from the given string and returns the - * value and the rest of the string via the out parameter. + * Expose `utils` modules */ -exports.decode = function base64VLQ_decode(aStr, aIndex, aOutParam) { - var strLen = aStr.length; - var result = 0; - var shift = 0; - var continuation, digit; - do { - if (aIndex >= strLen) { - throw new Error("Expected more digits in base 64 VLQ value."); - } +module.exports = utils; - digit = base64.decode(aStr.charCodeAt(aIndex++)); - if (digit === -1) { - throw new Error("Invalid base64 digit: " + aStr.charAt(aIndex - 1)); - } - continuation = !!(digit & VLQ_CONTINUATION_BIT); - digit &= VLQ_BASE_MASK; - result = result + (digit << shift); - shift += VLQ_BASE_SHIFT; - } while (continuation); +/***/ }), +/* 609 */ +/***/ (function(module, exports, __webpack_require__) { - aOutParam.value = fromVLQSigned(result); - aOutParam.rest = aIndex; -}; +/** + * Detect Electron renderer process, which is node, but we should + * treat as a browser. + */ + +if (typeof process !== 'undefined' && process.type === 'renderer') { + module.exports = __webpack_require__(610); +} else { + module.exports = __webpack_require__(613); +} /***/ }), -/* 616 */ -/***/ (function(module, exports) { +/* 610 */ +/***/ (function(module, exports, __webpack_require__) { -/* -*- Mode: js; js-indent-level: 2; -*- */ -/* - * Copyright 2011 Mozilla Foundation and contributors - * Licensed under the New BSD license. See LICENSE or: - * http://opensource.org/licenses/BSD-3-Clause +/** + * This is the web browser implementation of `debug()`. + * + * Expose `debug()` as the module. */ -var intToCharMap = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'.split(''); +exports = module.exports = __webpack_require__(611); +exports.log = log; +exports.formatArgs = formatArgs; +exports.save = save; +exports.load = load; +exports.useColors = useColors; +exports.storage = 'undefined' != typeof chrome + && 'undefined' != typeof chrome.storage + ? chrome.storage.local + : localstorage(); /** - * Encode an integer in the range of 0 to 63 to a single base 64 digit. + * Colors. */ -exports.encode = function (number) { - if (0 <= number && number < intToCharMap.length) { - return intToCharMap[number]; - } - throw new TypeError("Must be between 0 and 63: " + number); -}; + +exports.colors = [ + 'lightseagreen', + 'forestgreen', + 'goldenrod', + 'dodgerblue', + 'darkorchid', + 'crimson' +]; /** - * Decode a single base 64 character code digit to an integer. Returns -1 on - * failure. + * Currently only WebKit-based Web Inspectors, Firefox >= v31, + * and the Firebug extension (any Firefox version) are known + * to support "%c" CSS customizations. + * + * TODO: add a `localStorage` variable to explicitly enable/disable colors */ -exports.decode = function (charCode) { - var bigA = 65; // 'A' - var bigZ = 90; // 'Z' - - var littleA = 97; // 'a' - var littleZ = 122; // 'z' - var zero = 48; // '0' - var nine = 57; // '9' +function useColors() { + // NB: In an Electron preload script, document will be defined but not fully + // initialized. Since we know we're in Chrome, we'll just detect this case + // explicitly + if (typeof window !== 'undefined' && window.process && window.process.type === 'renderer') { + return true; + } - var plus = 43; // '+' - var slash = 47; // '/' + // is webkit? http://stackoverflow.com/a/16459606/376773 + // document is undefined in react-native: https://github.com/facebook/react-native/pull/1632 + return (typeof document !== 'undefined' && document.documentElement && document.documentElement.style && document.documentElement.style.WebkitAppearance) || + // is firebug? http://stackoverflow.com/a/398120/376773 + (typeof window !== 'undefined' && window.console && (window.console.firebug || (window.console.exception && window.console.table))) || + // is firefox >= v31? + // https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages + (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/) && parseInt(RegExp.$1, 10) >= 31) || + // double check webkit in userAgent just in case we are in a worker + (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/applewebkit\/(\d+)/)); +} - var littleOffset = 26; - var numberOffset = 52; +/** + * Map %j to `JSON.stringify()`, since no Web Inspectors do that by default. + */ - // 0 - 25: ABCDEFGHIJKLMNOPQRSTUVWXYZ - if (bigA <= charCode && charCode <= bigZ) { - return (charCode - bigA); +exports.formatters.j = function(v) { + try { + return JSON.stringify(v); + } catch (err) { + return '[UnexpectedJSONParseError]: ' + err.message; } +}; - // 26 - 51: abcdefghijklmnopqrstuvwxyz - if (littleA <= charCode && charCode <= littleZ) { - return (charCode - littleA + littleOffset); - } - // 52 - 61: 0123456789 - if (zero <= charCode && charCode <= nine) { - return (charCode - zero + numberOffset); - } +/** + * Colorize log arguments if enabled. + * + * @api public + */ - // 62: + - if (charCode == plus) { - return 62; - } +function formatArgs(args) { + var useColors = this.useColors; - // 63: / - if (charCode == slash) { - return 63; - } + args[0] = (useColors ? '%c' : '') + + this.namespace + + (useColors ? ' %c' : ' ') + + args[0] + + (useColors ? '%c ' : ' ') + + '+' + exports.humanize(this.diff); - // Invalid base64 digit. - return -1; -}; + if (!useColors) return; + var c = 'color: ' + this.color; + args.splice(1, 0, c, 'color: inherit') -/***/ }), -/* 617 */ -/***/ (function(module, exports) { + // the final "%c" is somewhat tricky, because there could be other + // arguments passed either before or after the %c, so we need to + // figure out the correct index to insert the CSS into + var index = 0; + var lastC = 0; + args[0].replace(/%[a-zA-Z%]/g, function(match) { + if ('%%' === match) return; + index++; + if ('%c' === match) { + // we only are interested in the *last* %c + // (the user may have provided their own) + lastC = index; + } + }); -/* -*- Mode: js; js-indent-level: 2; -*- */ -/* - * Copyright 2011 Mozilla Foundation and contributors - * Licensed under the New BSD license. See LICENSE or: - * http://opensource.org/licenses/BSD-3-Clause - */ + args.splice(lastC, 0, c); +} /** - * This is a helper function for getting values from parameter/options - * objects. + * Invokes `console.log()` when available. + * No-op when `console.log` is not a "function". * - * @param args The object we are extracting values from - * @param name The name of the property we are getting. - * @param defaultValue An optional value to return if the property is missing - * from the object. If this is not specified and the property is missing, an - * error will be thrown. + * @api public */ -function getArg(aArgs, aName, aDefaultValue) { - if (aName in aArgs) { - return aArgs[aName]; - } else if (arguments.length === 3) { - return aDefaultValue; - } else { - throw new Error('"' + aName + '" is a required argument.'); - } + +function log() { + // this hackery is required for IE8/9, where + // the `console.log` function doesn't have 'apply' + return 'object' === typeof console + && console.log + && Function.prototype.apply.call(console.log, console, arguments); } -exports.getArg = getArg; -var urlRegexp = /^(?:([\w+\-.]+):)?\/\/(?:(\w+:\w+)@)?([\w.]*)(?::(\d+))?(\S*)$/; -var dataUrlRegexp = /^data:.+\,.+$/; +/** + * Save `namespaces`. + * + * @param {String} namespaces + * @api private + */ -function urlParse(aUrl) { - var match = aUrl.match(urlRegexp); - if (!match) { - return null; - } - return { - scheme: match[1], - auth: match[2], - host: match[3], - port: match[4], - path: match[5] - }; +function save(namespaces) { + try { + if (null == namespaces) { + exports.storage.removeItem('debug'); + } else { + exports.storage.debug = namespaces; + } + } catch(e) {} } -exports.urlParse = urlParse; -function urlGenerate(aParsedUrl) { - var url = ''; - if (aParsedUrl.scheme) { - url += aParsedUrl.scheme + ':'; - } - url += '//'; - if (aParsedUrl.auth) { - url += aParsedUrl.auth + '@'; - } - if (aParsedUrl.host) { - url += aParsedUrl.host; - } - if (aParsedUrl.port) { - url += ":" + aParsedUrl.port - } - if (aParsedUrl.path) { - url += aParsedUrl.path; +/** + * Load `namespaces`. + * + * @return {String} returns the previously persisted debug modes + * @api private + */ + +function load() { + var r; + try { + r = exports.storage.debug; + } catch(e) {} + + // If debug isn't set in LS, and we're in Electron, try to load $DEBUG + if (!r && typeof process !== 'undefined' && 'env' in process) { + r = process.env.DEBUG; } - return url; + + return r; } -exports.urlGenerate = urlGenerate; /** - * Normalizes a path, or the path portion of a URL: - * - * - Replaces consecutive slashes with one slash. - * - Removes unnecessary '.' parts. - * - Removes unnecessary '
/..' parts. + * Enable namespaces listed in `localStorage.debug` initially. + */ + +exports.enable(load()); + +/** + * Localstorage attempts to return the localstorage. * - * Based on code in the Node.js 'path' core module. + * This is necessary because safari throws + * when a user disables cookies/localstorage + * and you attempt to access it. * - * @param aPath The path or url to normalize. + * @return {LocalStorage} + * @api private */ -function normalize(aPath) { - var path = aPath; - var url = urlParse(aPath); - if (url) { - if (!url.path) { - return aPath; - } - path = url.path; - } - var isAbsolute = exports.isAbsolute(path); - var parts = path.split(/\/+/); - for (var part, up = 0, i = parts.length - 1; i >= 0; i--) { - part = parts[i]; - if (part === '.') { - parts.splice(i, 1); - } else if (part === '..') { - up++; - } else if (up > 0) { - if (part === '') { - // The first part is blank if the path is absolute. Trying to go - // above the root is a no-op. Therefore we can remove all '..' parts - // directly after the root. - parts.splice(i + 1, up); - up = 0; - } else { - parts.splice(i, 2); - up--; - } - } - } - path = parts.join('/'); +function localstorage() { + try { + return window.localStorage; + } catch (e) {} +} - if (path === '') { - path = isAbsolute ? '/' : '.'; - } - if (url) { - url.path = path; - return urlGenerate(url); - } - return path; -} -exports.normalize = normalize; +/***/ }), +/* 611 */ +/***/ (function(module, exports, __webpack_require__) { + /** - * Joins two paths/URLs. + * This is the common logic for both the Node.js and web browser + * implementations of `debug()`. * - * @param aRoot The root path or URL. - * @param aPath The path or URL to be joined with the root. + * Expose `debug()` as the module. + */ + +exports = module.exports = createDebug.debug = createDebug['default'] = createDebug; +exports.coerce = coerce; +exports.disable = disable; +exports.enable = enable; +exports.enabled = enabled; +exports.humanize = __webpack_require__(612); + +/** + * The currently active debug mode names, and names to skip. + */ + +exports.names = []; +exports.skips = []; + +/** + * Map of special "%n" handling functions, for the debug "format" argument. * - * - If aPath is a URL or a data URI, aPath is returned, unless aPath is a - * scheme-relative URL: Then the scheme of aRoot, if any, is prepended - * first. - * - Otherwise aPath is a path. If aRoot is a URL, then its path portion - * is updated with the result and aRoot is returned. Otherwise the result - * is returned. - * - If aPath is absolute, the result is aPath. - * - Otherwise the two paths are joined with a slash. - * - Joining for example 'http://' and 'www.example.com' is also supported. + * Valid key names are a single, lower or upper-case letter, i.e. "n" and "N". */ -function join(aRoot, aPath) { - if (aRoot === "") { - aRoot = "."; - } - if (aPath === "") { - aPath = "."; - } - var aPathUrl = urlParse(aPath); - var aRootUrl = urlParse(aRoot); - if (aRootUrl) { - aRoot = aRootUrl.path || '/'; - } - // `join(foo, '//www.example.org')` - if (aPathUrl && !aPathUrl.scheme) { - if (aRootUrl) { - aPathUrl.scheme = aRootUrl.scheme; - } - return urlGenerate(aPathUrl); - } +exports.formatters = {}; - if (aPathUrl || aPath.match(dataUrlRegexp)) { - return aPath; - } +/** + * Previous log timestamp. + */ - // `join('http://', 'www.example.com')` - if (aRootUrl && !aRootUrl.host && !aRootUrl.path) { - aRootUrl.host = aPath; - return urlGenerate(aRootUrl); - } +var prevTime; - var joined = aPath.charAt(0) === '/' - ? aPath - : normalize(aRoot.replace(/\/+$/, '') + '/' + aPath); +/** + * Select a color. + * @param {String} namespace + * @return {Number} + * @api private + */ - if (aRootUrl) { - aRootUrl.path = joined; - return urlGenerate(aRootUrl); +function selectColor(namespace) { + var hash = 0, i; + + for (i in namespace) { + hash = ((hash << 5) - hash) + namespace.charCodeAt(i); + hash |= 0; // Convert to 32bit integer } - return joined; -} -exports.join = join; -exports.isAbsolute = function (aPath) { - return aPath.charAt(0) === '/' || !!aPath.match(urlRegexp); -}; + return exports.colors[Math.abs(hash) % exports.colors.length]; +} /** - * Make a path relative to a URL or another path. + * Create a debugger with the given `namespace`. * - * @param aRoot The root path or URL. - * @param aPath The path or URL to be made relative to aRoot. + * @param {String} namespace + * @return {Function} + * @api public */ -function relative(aRoot, aPath) { - if (aRoot === "") { - aRoot = "."; - } - aRoot = aRoot.replace(/\/$/, ''); +function createDebug(namespace) { - // It is possible for the path to be above the root. In this case, simply - // checking whether the root is a prefix of the path won't work. Instead, we - // need to remove components from the root one by one, until either we find - // a prefix that fits, or we run out of components to remove. - var level = 0; - while (aPath.indexOf(aRoot + '/') !== 0) { - var index = aRoot.lastIndexOf("/"); - if (index < 0) { - return aPath; + function debug() { + // disabled? + if (!debug.enabled) return; + + var self = debug; + + // set `diff` timestamp + var curr = +new Date(); + var ms = curr - (prevTime || curr); + self.diff = ms; + self.prev = prevTime; + self.curr = curr; + prevTime = curr; + + // turn the `arguments` into a proper Array + var args = new Array(arguments.length); + for (var i = 0; i < args.length; i++) { + args[i] = arguments[i]; } - // If the only part of the root that is left is the scheme (i.e. http://, - // file:///, etc.), one or more slashes (/), or simply nothing at all, we - // have exhausted all components, so the path is not relative to the root. - aRoot = aRoot.slice(0, index); - if (aRoot.match(/^([^\/]+:\/)?\/*$/)) { - return aPath; + args[0] = exports.coerce(args[0]); + + if ('string' !== typeof args[0]) { + // anything else let's inspect with %O + args.unshift('%O'); } - ++level; + // apply any `formatters` transformations + var index = 0; + args[0] = args[0].replace(/%([a-zA-Z%])/g, function(match, format) { + // if we encounter an escaped % then don't increase the array index + if (match === '%%') return match; + index++; + var formatter = exports.formatters[format]; + if ('function' === typeof formatter) { + var val = args[index]; + match = formatter.call(self, val); + + // now we need to remove `args[index]` since it's inlined in the `format` + args.splice(index, 1); + index--; + } + return match; + }); + + // apply env-specific formatting (colors, etc.) + exports.formatArgs.call(self, args); + + var logFn = debug.log || exports.log || console.log.bind(console); + logFn.apply(self, args); } - // Make sure we add a "../" for each component we removed from the root. - return Array(level + 1).join("../") + aPath.substr(aRoot.length + 1); -} -exports.relative = relative; + debug.namespace = namespace; + debug.enabled = exports.enabled(namespace); + debug.useColors = exports.useColors(); + debug.color = selectColor(namespace); -var supportsNullProto = (function () { - var obj = Object.create(null); - return !('__proto__' in obj); -}()); + // env-specific initialization logic for debug instances + if ('function' === typeof exports.init) { + exports.init(debug); + } -function identity (s) { - return s; + return debug; } /** - * Because behavior goes wacky when you set `__proto__` on objects, we - * have to prefix all the strings in our set with an arbitrary character. - * - * See https://github.com/mozilla/source-map/pull/31 and - * https://github.com/mozilla/source-map/issues/30 + * Enables a debug mode by namespaces. This can include modes + * separated by a colon and wildcards. * - * @param String aStr + * @param {String} namespaces + * @api public */ -function toSetString(aStr) { - if (isProtoString(aStr)) { - return '$' + aStr; - } - return aStr; -} -exports.toSetString = supportsNullProto ? identity : toSetString; +function enable(namespaces) { + exports.save(namespaces); -function fromSetString(aStr) { - if (isProtoString(aStr)) { - return aStr.slice(1); - } + exports.names = []; + exports.skips = []; - return aStr; -} -exports.fromSetString = supportsNullProto ? identity : fromSetString; + var split = (typeof namespaces === 'string' ? namespaces : '').split(/[\s,]+/); + var len = split.length; -function isProtoString(s) { - if (!s) { - return false; + for (var i = 0; i < len; i++) { + if (!split[i]) continue; // ignore empty strings + namespaces = split[i].replace(/\*/g, '.*?'); + if (namespaces[0] === '-') { + exports.skips.push(new RegExp('^' + namespaces.substr(1) + '$')); + } else { + exports.names.push(new RegExp('^' + namespaces + '$')); + } } +} - var length = s.length; +/** + * Disable debug output. + * + * @api public + */ - if (length < 9 /* "__proto__".length */) { - return false; - } +function disable() { + exports.enable(''); +} - if (s.charCodeAt(length - 1) !== 95 /* '_' */ || - s.charCodeAt(length - 2) !== 95 /* '_' */ || - s.charCodeAt(length - 3) !== 111 /* 'o' */ || - s.charCodeAt(length - 4) !== 116 /* 't' */ || - s.charCodeAt(length - 5) !== 111 /* 'o' */ || - s.charCodeAt(length - 6) !== 114 /* 'r' */ || - s.charCodeAt(length - 7) !== 112 /* 'p' */ || - s.charCodeAt(length - 8) !== 95 /* '_' */ || - s.charCodeAt(length - 9) !== 95 /* '_' */) { - return false; - } +/** + * Returns true if the given mode name is enabled, false otherwise. + * + * @param {String} name + * @return {Boolean} + * @api public + */ - for (var i = length - 10; i >= 0; i--) { - if (s.charCodeAt(i) !== 36 /* '$' */) { +function enabled(name) { + var i, len; + for (i = 0, len = exports.skips.length; i < len; i++) { + if (exports.skips[i].test(name)) { return false; } } - - return true; + for (i = 0, len = exports.names.length; i < len; i++) { + if (exports.names[i].test(name)) { + return true; + } + } + return false; } /** - * Comparator between two mappings where the original positions are compared. + * Coerce `val`. * - * Optionally pass in `true` as `onlyCompareGenerated` to consider two - * mappings with the same original source/line/column, but different generated - * line and column the same. Useful when searching for a mapping with a - * stubbed out mapping. + * @param {Mixed} val + * @return {Mixed} + * @api private */ -function compareByOriginalPositions(mappingA, mappingB, onlyCompareOriginal) { - var cmp = mappingA.source - mappingB.source; - if (cmp !== 0) { - return cmp; - } - cmp = mappingA.originalLine - mappingB.originalLine; - if (cmp !== 0) { - return cmp; - } +function coerce(val) { + if (val instanceof Error) return val.stack || val.message; + return val; +} - cmp = mappingA.originalColumn - mappingB.originalColumn; - if (cmp !== 0 || onlyCompareOriginal) { - return cmp; - } - cmp = mappingA.generatedColumn - mappingB.generatedColumn; - if (cmp !== 0) { - return cmp; - } +/***/ }), +/* 612 */ +/***/ (function(module, exports) { - cmp = mappingA.generatedLine - mappingB.generatedLine; - if (cmp !== 0) { - return cmp; - } +/** + * Helpers. + */ - return mappingA.name - mappingB.name; -} -exports.compareByOriginalPositions = compareByOriginalPositions; +var s = 1000; +var m = s * 60; +var h = m * 60; +var d = h * 24; +var y = d * 365.25; /** - * Comparator between two mappings with deflated source and name indices where - * the generated positions are compared. + * Parse or format the given `val`. * - * Optionally pass in `true` as `onlyCompareGenerated` to consider two - * mappings with the same generated line and column, but different - * source/name/original line and column the same. Useful when searching for a - * mapping with a stubbed out mapping. + * Options: + * + * - `long` verbose formatting [false] + * + * @param {String|Number} val + * @param {Object} [options] + * @throws {Error} throw an error if val is not a non-empty string or a number + * @return {String|Number} + * @api public */ -function compareByGeneratedPositionsDeflated(mappingA, mappingB, onlyCompareGenerated) { - var cmp = mappingA.generatedLine - mappingB.generatedLine; - if (cmp !== 0) { - return cmp; - } - cmp = mappingA.generatedColumn - mappingB.generatedColumn; - if (cmp !== 0 || onlyCompareGenerated) { - return cmp; +module.exports = function(val, options) { + options = options || {}; + var type = typeof val; + if (type === 'string' && val.length > 0) { + return parse(val); + } else if (type === 'number' && isNaN(val) === false) { + return options.long ? fmtLong(val) : fmtShort(val); } + throw new Error( + 'val is not a non-empty string or a valid number. val=' + + JSON.stringify(val) + ); +}; - cmp = mappingA.source - mappingB.source; - if (cmp !== 0) { - return cmp; - } +/** + * Parse the given `str` and return milliseconds. + * + * @param {String} str + * @return {Number} + * @api private + */ - cmp = mappingA.originalLine - mappingB.originalLine; - if (cmp !== 0) { - return cmp; +function parse(str) { + str = String(str); + if (str.length > 100) { + return; } - - cmp = mappingA.originalColumn - mappingB.originalColumn; - if (cmp !== 0) { - return cmp; + var match = /^((?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|years?|yrs?|y)?$/i.exec( + str + ); + if (!match) { + return; + } + var n = parseFloat(match[1]); + var type = (match[2] || 'ms').toLowerCase(); + switch (type) { + case 'years': + case 'year': + case 'yrs': + case 'yr': + case 'y': + return n * y; + case 'days': + case 'day': + case 'd': + return n * d; + case 'hours': + case 'hour': + case 'hrs': + case 'hr': + case 'h': + return n * h; + case 'minutes': + case 'minute': + case 'mins': + case 'min': + case 'm': + return n * m; + case 'seconds': + case 'second': + case 'secs': + case 'sec': + case 's': + return n * s; + case 'milliseconds': + case 'millisecond': + case 'msecs': + case 'msec': + case 'ms': + return n; + default: + return undefined; } - - return mappingA.name - mappingB.name; } -exports.compareByGeneratedPositionsDeflated = compareByGeneratedPositionsDeflated; -function strcmp(aStr1, aStr2) { - if (aStr1 === aStr2) { - return 0; +/** + * Short format for `ms`. + * + * @param {Number} ms + * @return {String} + * @api private + */ + +function fmtShort(ms) { + if (ms >= d) { + return Math.round(ms / d) + 'd'; } - - if (aStr1 > aStr2) { - return 1; + if (ms >= h) { + return Math.round(ms / h) + 'h'; } - - return -1; + if (ms >= m) { + return Math.round(ms / m) + 'm'; + } + if (ms >= s) { + return Math.round(ms / s) + 's'; + } + return ms + 'ms'; } /** - * Comparator between two mappings with inflated source and name strings where - * the generated positions are compared. + * Long format for `ms`. + * + * @param {Number} ms + * @return {String} + * @api private */ -function compareByGeneratedPositionsInflated(mappingA, mappingB) { - var cmp = mappingA.generatedLine - mappingB.generatedLine; - if (cmp !== 0) { - return cmp; - } - cmp = mappingA.generatedColumn - mappingB.generatedColumn; - if (cmp !== 0) { - return cmp; - } +function fmtLong(ms) { + return plural(ms, d, 'day') || + plural(ms, h, 'hour') || + plural(ms, m, 'minute') || + plural(ms, s, 'second') || + ms + ' ms'; +} - cmp = strcmp(mappingA.source, mappingB.source); - if (cmp !== 0) { - return cmp; - } +/** + * Pluralization helper. + */ - cmp = mappingA.originalLine - mappingB.originalLine; - if (cmp !== 0) { - return cmp; +function plural(ms, n, name) { + if (ms < n) { + return; } - - cmp = mappingA.originalColumn - mappingB.originalColumn; - if (cmp !== 0) { - return cmp; + if (ms < n * 1.5) { + return Math.floor(ms / n) + ' ' + name; } - - return strcmp(mappingA.name, mappingB.name); + return Math.ceil(ms / n) + ' ' + name + 's'; } -exports.compareByGeneratedPositionsInflated = compareByGeneratedPositionsInflated; /***/ }), -/* 618 */ +/* 613 */ /***/ (function(module, exports, __webpack_require__) { -/* -*- Mode: js; js-indent-level: 2; -*- */ -/* - * Copyright 2011 Mozilla Foundation and contributors - * Licensed under the New BSD license. See LICENSE or: - * http://opensource.org/licenses/BSD-3-Clause +/** + * Module dependencies. */ -var util = __webpack_require__(617); -var has = Object.prototype.hasOwnProperty; -var hasNativeMap = typeof Map !== "undefined"; +var tty = __webpack_require__(122); +var util = __webpack_require__(112); /** - * A data structure which is a combination of an array and a set. Adding a new - * member is O(1), testing for membership is O(1), and finding the index of an - * element is O(1). Removing elements from the set is not supported. Only - * strings are supported for membership. + * This is the Node.js implementation of `debug()`. + * + * Expose `debug()` as the module. */ -function ArraySet() { - this._array = []; - this._set = hasNativeMap ? new Map() : Object.create(null); -} + +exports = module.exports = __webpack_require__(611); +exports.init = init; +exports.log = log; +exports.formatArgs = formatArgs; +exports.save = save; +exports.load = load; +exports.useColors = useColors; /** - * Static method for creating ArraySet instances from an existing array. + * Colors. */ -ArraySet.fromArray = function ArraySet_fromArray(aArray, aAllowDuplicates) { - var set = new ArraySet(); - for (var i = 0, len = aArray.length; i < len; i++) { - set.add(aArray[i], aAllowDuplicates); - } - return set; -}; + +exports.colors = [6, 2, 3, 4, 5, 1]; /** - * Return how many unique items are in this ArraySet. If duplicates have been - * added, than those do not count towards the size. + * Build up the default `inspectOpts` object from the environment variables. * - * @returns Number + * $ DEBUG_COLORS=no DEBUG_DEPTH=10 DEBUG_SHOW_HIDDEN=enabled node script.js */ -ArraySet.prototype.size = function ArraySet_size() { - return hasNativeMap ? this._set.size : Object.getOwnPropertyNames(this._set).length; -}; + +exports.inspectOpts = Object.keys(process.env).filter(function (key) { + return /^debug_/i.test(key); +}).reduce(function (obj, key) { + // camel-case + var prop = key + .substring(6) + .toLowerCase() + .replace(/_([a-z])/g, function (_, k) { return k.toUpperCase() }); + + // coerce string value into JS value + var val = process.env[key]; + if (/^(yes|on|true|enabled)$/i.test(val)) val = true; + else if (/^(no|off|false|disabled)$/i.test(val)) val = false; + else if (val === 'null') val = null; + else val = Number(val); + + obj[prop] = val; + return obj; +}, {}); /** - * Add the given string to this set. + * The file descriptor to write the `debug()` calls to. + * Set the `DEBUG_FD` env variable to override with another value. i.e.: * - * @param String aStr + * $ DEBUG_FD=3 node script.js 3>debug.log */ -ArraySet.prototype.add = function ArraySet_add(aStr, aAllowDuplicates) { - var sStr = hasNativeMap ? aStr : util.toSetString(aStr); - var isDuplicate = hasNativeMap ? this.has(aStr) : has.call(this._set, sStr); - var idx = this._array.length; - if (!isDuplicate || aAllowDuplicates) { - this._array.push(aStr); - } - if (!isDuplicate) { - if (hasNativeMap) { - this._set.set(aStr, idx); - } else { - this._set[sStr] = idx; - } - } -}; + +var fd = parseInt(process.env.DEBUG_FD, 10) || 2; + +if (1 !== fd && 2 !== fd) { + util.deprecate(function(){}, 'except for stderr(2) and stdout(1), any other usage of DEBUG_FD is deprecated. Override debug.log if you want to use a different log function (https://git.io/debug_fd)')() +} + +var stream = 1 === fd ? process.stdout : + 2 === fd ? process.stderr : + createWritableStdioStream(fd); /** - * Is the given string a member of this set? - * - * @param String aStr + * Is stdout a TTY? Colored output is enabled when `true`. */ -ArraySet.prototype.has = function ArraySet_has(aStr) { - if (hasNativeMap) { - return this._set.has(aStr); - } else { - var sStr = util.toSetString(aStr); - return has.call(this._set, sStr); - } -}; + +function useColors() { + return 'colors' in exports.inspectOpts + ? Boolean(exports.inspectOpts.colors) + : tty.isatty(fd); +} /** - * What is the index of the given string in the array? - * - * @param String aStr + * Map %o to `util.inspect()`, all on a single line. */ -ArraySet.prototype.indexOf = function ArraySet_indexOf(aStr) { - if (hasNativeMap) { - var idx = this._set.get(aStr); - if (idx >= 0) { - return idx; - } - } else { - var sStr = util.toSetString(aStr); - if (has.call(this._set, sStr)) { - return this._set[sStr]; - } - } - throw new Error('"' + aStr + '" is not in the set.'); +exports.formatters.o = function(v) { + this.inspectOpts.colors = this.useColors; + return util.inspect(v, this.inspectOpts) + .split('\n').map(function(str) { + return str.trim() + }).join(' '); }; /** - * What is the element at the given index? - * - * @param Number aIdx + * Map %o to `util.inspect()`, allowing multiple lines if needed. */ -ArraySet.prototype.at = function ArraySet_at(aIdx) { - if (aIdx >= 0 && aIdx < this._array.length) { - return this._array[aIdx]; - } - throw new Error('No element indexed by ' + aIdx); + +exports.formatters.O = function(v) { + this.inspectOpts.colors = this.useColors; + return util.inspect(v, this.inspectOpts); }; /** - * Returns the array representation of this set (which has the proper indices - * indicated by indexOf). Note that this is a copy of the internal array used - * for storing the members so that no one can mess with internal state. + * Adds ANSI color escape codes if enabled. + * + * @api public */ -ArraySet.prototype.toArray = function ArraySet_toArray() { - return this._array.slice(); -}; -exports.ArraySet = ArraySet; +function formatArgs(args) { + var name = this.namespace; + var useColors = this.useColors; + if (useColors) { + var c = this.color; + var prefix = ' \u001b[3' + c + ';1m' + name + ' ' + '\u001b[0m'; -/***/ }), -/* 619 */ -/***/ (function(module, exports, __webpack_require__) { + args[0] = prefix + args[0].split('\n').join('\n' + prefix); + args.push('\u001b[3' + c + 'm+' + exports.humanize(this.diff) + '\u001b[0m'); + } else { + args[0] = new Date().toUTCString() + + ' ' + name + ' ' + args[0]; + } +} -/* -*- Mode: js; js-indent-level: 2; -*- */ -/* - * Copyright 2014 Mozilla Foundation and contributors - * Licensed under the New BSD license. See LICENSE or: - * http://opensource.org/licenses/BSD-3-Clause +/** + * Invokes `util.format()` with the specified arguments and writes to `stream`. */ -var util = __webpack_require__(617); +function log() { + return stream.write(util.format.apply(util, arguments) + '\n'); +} /** - * Determine whether mappingB is after mappingA with respect to generated - * position. + * Save `namespaces`. + * + * @param {String} namespaces + * @api private */ -function generatedPositionAfter(mappingA, mappingB) { - // Optimized for most common case - var lineA = mappingA.generatedLine; - var lineB = mappingB.generatedLine; - var columnA = mappingA.generatedColumn; - var columnB = mappingB.generatedColumn; - return lineB > lineA || lineB == lineA && columnB >= columnA || - util.compareByGeneratedPositionsInflated(mappingA, mappingB) <= 0; + +function save(namespaces) { + if (null == namespaces) { + // If you set a process.env field to null or undefined, it gets cast to the + // string 'null' or 'undefined'. Just delete instead. + delete process.env.DEBUG; + } else { + process.env.DEBUG = namespaces; + } } /** - * A data structure to provide a sorted view of accumulated mappings in a - * performance conscious manner. It trades a neglibable overhead in general - * case for a large speedup in case of mappings being added in order. + * Load `namespaces`. + * + * @return {String} returns the previously persisted debug modes + * @api private */ -function MappingList() { - this._array = []; - this._sorted = true; - // Serves as infimum - this._last = {generatedLine: -1, generatedColumn: 0}; + +function load() { + return process.env.DEBUG; } /** - * Iterate through internal items. This method takes the same arguments that - * `Array.prototype.forEach` takes. + * Copied from `node/src/node.js`. * - * NOTE: The order of the mappings is NOT guaranteed. + * XXX: It's lame that node doesn't expose this API out-of-the-box. It also + * relies on the undocumented `tty_wrap.guessHandleType()` which is also lame. */ -MappingList.prototype.unsortedForEach = - function MappingList_forEach(aCallback, aThisArg) { - this._array.forEach(aCallback, aThisArg); - }; + +function createWritableStdioStream (fd) { + var stream; + var tty_wrap = process.binding('tty_wrap'); + + // Note stream._type is used for test-module-load-list.js + + switch (tty_wrap.guessHandleType(fd)) { + case 'TTY': + stream = new tty.WriteStream(fd); + stream._type = 'tty'; + + // Hack to have stream not keep the event loop alive. + // See https://github.com/joyent/node/issues/1726 + if (stream._handle && stream._handle.unref) { + stream._handle.unref(); + } + break; + + case 'FILE': + var fs = __webpack_require__(134); + stream = new fs.SyncWriteStream(fd, { autoClose: false }); + stream._type = 'fs'; + break; + + case 'PIPE': + case 'TCP': + var net = __webpack_require__(614); + stream = new net.Socket({ + fd: fd, + readable: false, + writable: true + }); + + // FIXME Should probably have an option in net.Socket to create a + // stream from an existing fd which is writable only. But for now + // we'll just add this hack and set the `readable` member to false. + // Test: ./node test/fixtures/echo.js < /etc/passwd + stream.readable = false; + stream.read = null; + stream._type = 'pipe'; + + // FIXME Hack to have stream not keep the event loop alive. + // See https://github.com/joyent/node/issues/1726 + if (stream._handle && stream._handle.unref) { + stream._handle.unref(); + } + break; + + default: + // Probably an error on in uv_guess_handle() + throw new Error('Implement me. Unknown stream file type!'); + } + + // For supporting legacy API we put the FD here. + stream.fd = fd; + + stream._isStdio = true; + + return stream; +} /** - * Add the given source mapping. + * Init logic for `debug` instances. * - * @param Object aMapping + * Create a new `inspectOpts` object in case `useColors` is set + * differently for a particular `debug` instance. */ -MappingList.prototype.add = function MappingList_add(aMapping) { - if (generatedPositionAfter(this._last, aMapping)) { - this._last = aMapping; - this._array.push(aMapping); - } else { - this._sorted = false; - this._array.push(aMapping); + +function init (debug) { + debug.inspectOpts = {}; + + var keys = Object.keys(exports.inspectOpts); + for (var i = 0; i < keys.length; i++) { + debug.inspectOpts[keys[i]] = exports.inspectOpts[keys[i]]; } -}; +} /** - * Returns the flat, sorted array of mappings. The mappings are sorted by - * generated position. - * - * WARNING: This method returns internal data without copying, for - * performance. The return value must NOT be mutated, and should be treated as - * an immutable borrow. If you want to take ownership, you must make your own - * copy. + * Enable namespaces listed in `process.env.DEBUG` initially. */ -MappingList.prototype.toArray = function MappingList_toArray() { - if (!this._sorted) { - this._array.sort(util.compareByGeneratedPositionsInflated); - this._sorted = true; - } - return this._array; -}; -exports.MappingList = MappingList; +exports.enable(load()); /***/ }), -/* 620 */ -/***/ (function(module, exports, __webpack_require__) { - -/* -*- Mode: js; js-indent-level: 2; -*- */ -/* - * Copyright 2011 Mozilla Foundation and contributors - * Licensed under the New BSD license. See LICENSE or: - * http://opensource.org/licenses/BSD-3-Clause - */ +/* 614 */ +/***/ (function(module, exports) { -var util = __webpack_require__(617); -var binarySearch = __webpack_require__(621); -var ArraySet = __webpack_require__(618).ArraySet; -var base64VLQ = __webpack_require__(615); -var quickSort = __webpack_require__(622).quickSort; +module.exports = require("net"); -function SourceMapConsumer(aSourceMap) { - var sourceMap = aSourceMap; - if (typeof aSourceMap === 'string') { - sourceMap = JSON.parse(aSourceMap.replace(/^\)\]\}'/, '')); - } +/***/ }), +/* 615 */ +/***/ (function(module, exports, __webpack_require__) { - return sourceMap.sections != null - ? new IndexedSourceMapConsumer(sourceMap) - : new BasicSourceMapConsumer(sourceMap); -} +"use strict"; -SourceMapConsumer.fromSourceMap = function(aSourceMap) { - return BasicSourceMapConsumer.fromSourceMap(aSourceMap); -} /** - * The version of the source mapping spec that we are consuming. + * Module dependencies */ -SourceMapConsumer.prototype._version = 3; - -// `__generatedMappings` and `__originalMappings` are arrays that hold the -// parsed mapping coordinates from the source map's "mappings" attribute. They -// are lazily instantiated, accessed via the `_generatedMappings` and -// `_originalMappings` getters respectively, and we only parse the mappings -// and create these arrays once queried for a source location. We jump through -// these hoops because there can be many thousands of mappings, and parsing -// them is expensive, so we only want to do it if we must. -// -// Each object in the arrays is of the form: -// -// { -// generatedLine: The line number in the generated code, -// generatedColumn: The column number in the generated code, -// source: The path to the original source file that generated this -// chunk of code, -// originalLine: The line number in the original source that -// corresponds to this chunk of generated code, -// originalColumn: The column number in the original source that -// corresponds to this chunk of generated code, -// name: The name of the original symbol which generated this chunk of -// code. -// } -// -// All properties except for `generatedLine` and `generatedColumn` can be -// `null`. -// -// `_generatedMappings` is ordered by the generated positions. -// -// `_originalMappings` is ordered by the original positions. -SourceMapConsumer.prototype.__generatedMappings = null; -Object.defineProperty(SourceMapConsumer.prototype, '_generatedMappings', { - get: function () { - if (!this.__generatedMappings) { - this._parseMappings(this._mappings, this.sourceRoot); - } +exports.extend = __webpack_require__(549); +exports.SourceMap = __webpack_require__(616); +exports.sourceMapResolve = __webpack_require__(627); - return this.__generatedMappings; - } -}); +/** + * Convert backslash in the given string to forward slashes + */ -SourceMapConsumer.prototype.__originalMappings = null; -Object.defineProperty(SourceMapConsumer.prototype, '_originalMappings', { - get: function () { - if (!this.__originalMappings) { - this._parseMappings(this._mappings, this.sourceRoot); - } +exports.unixify = function(fp) { + return fp.split(/\\+/).join('/'); +}; - return this.__originalMappings; - } -}); +/** + * Return true if `val` is a non-empty string + * + * @param {String} `str` + * @return {Boolean} + */ -SourceMapConsumer.prototype._charIsMappingSeparator = - function SourceMapConsumer_charIsMappingSeparator(aStr, index) { - var c = aStr.charAt(index); - return c === ";" || c === ","; - }; +exports.isString = function(str) { + return str && typeof str === 'string'; +}; /** - * Parse the mappings in a string in to a data structure which we can easily - * query (the ordered arrays in the `this.__generatedMappings` and - * `this.__originalMappings` properties). + * Cast `val` to an array + * @return {Array} */ -SourceMapConsumer.prototype._parseMappings = - function SourceMapConsumer_parseMappings(aStr, aSourceRoot) { - throw new Error("Subclasses must implement _parseMappings"); - }; - -SourceMapConsumer.GENERATED_ORDER = 1; -SourceMapConsumer.ORIGINAL_ORDER = 2; -SourceMapConsumer.GREATEST_LOWER_BOUND = 1; -SourceMapConsumer.LEAST_UPPER_BOUND = 2; +exports.arrayify = function(val) { + if (typeof val === 'string') return [val]; + return val ? (Array.isArray(val) ? val : [val]) : []; +}; /** - * Iterate over each mapping between an original source/line/column and a - * generated line/column in this source map. - * - * @param Function aCallback - * The function that is called with each mapping. - * @param Object aContext - * Optional. If specified, this object will be the value of `this` every - * time that `aCallback` is called. - * @param aOrder - * Either `SourceMapConsumer.GENERATED_ORDER` or - * `SourceMapConsumer.ORIGINAL_ORDER`. Specifies whether you want to - * iterate over the mappings sorted by the generated file's line/column - * order or the original's source/line/column order, respectively. Defaults to - * `SourceMapConsumer.GENERATED_ORDER`. + * Get the last `n` element from the given `array` + * @param {Array} `array` + * @return {*} */ -SourceMapConsumer.prototype.eachMapping = - function SourceMapConsumer_eachMapping(aCallback, aContext, aOrder) { - var context = aContext || null; - var order = aOrder || SourceMapConsumer.GENERATED_ORDER; - var mappings; - switch (order) { - case SourceMapConsumer.GENERATED_ORDER: - mappings = this._generatedMappings; - break; - case SourceMapConsumer.ORIGINAL_ORDER: - mappings = this._originalMappings; - break; - default: - throw new Error("Unknown order of iteration."); - } +exports.last = function(arr, n) { + return arr[arr.length - (n || 1)]; +}; - var sourceRoot = this.sourceRoot; - mappings.map(function (mapping) { - var source = mapping.source === null ? null : this._sources.at(mapping.source); - if (source != null && sourceRoot != null) { - source = util.join(sourceRoot, source); - } - return { - source: source, - generatedLine: mapping.generatedLine, - generatedColumn: mapping.generatedColumn, - originalLine: mapping.originalLine, - originalColumn: mapping.originalColumn, - name: mapping.name === null ? null : this._names.at(mapping.name) - }; - }, this).forEach(aCallback, context); - }; -/** - * Returns all generated line and column information for the original source, - * line, and column provided. If no column is provided, returns all mappings - * corresponding to a either the line we are searching for or the next - * closest line that has any mappings. Otherwise, returns all mappings - * corresponding to the given line and either the column we are searching for - * or the next closest column that has any offsets. - * - * The only argument is an object with the following properties: - * - * - source: The filename of the original source. - * - line: The line number in the original source. - * - column: Optional. the column number in the original source. - * - * and an array of objects is returned, each with the following properties: - * - * - line: The line number in the generated source, or null. - * - column: The column number in the generated source, or null. +/***/ }), +/* 616 */ +/***/ (function(module, exports, __webpack_require__) { + +/* + * Copyright 2009-2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE.txt or: + * http://opensource.org/licenses/BSD-3-Clause */ -SourceMapConsumer.prototype.allGeneratedPositionsFor = - function SourceMapConsumer_allGeneratedPositionsFor(aArgs) { - var line = util.getArg(aArgs, 'line'); +exports.SourceMapGenerator = __webpack_require__(617).SourceMapGenerator; +exports.SourceMapConsumer = __webpack_require__(623).SourceMapConsumer; +exports.SourceNode = __webpack_require__(626).SourceNode; - // When there is no exact match, BasicSourceMapConsumer.prototype._findMapping - // returns the index of the closest mapping less than the needle. By - // setting needle.originalColumn to 0, we thus find the last mapping for - // the given line, provided such a mapping exists. - var needle = { - source: util.getArg(aArgs, 'source'), - originalLine: line, - originalColumn: util.getArg(aArgs, 'column', 0) - }; - if (this.sourceRoot != null) { - needle.source = util.relative(this.sourceRoot, needle.source); - } - if (!this._sources.has(needle.source)) { - return []; - } - needle.source = this._sources.indexOf(needle.source); +/***/ }), +/* 617 */ +/***/ (function(module, exports, __webpack_require__) { - var mappings = []; +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ - var index = this._findMapping(needle, - this._originalMappings, - "originalLine", - "originalColumn", - util.compareByOriginalPositions, - binarySearch.LEAST_UPPER_BOUND); - if (index >= 0) { - var mapping = this._originalMappings[index]; +var base64VLQ = __webpack_require__(618); +var util = __webpack_require__(620); +var ArraySet = __webpack_require__(621).ArraySet; +var MappingList = __webpack_require__(622).MappingList; - if (aArgs.column === undefined) { - var originalLine = mapping.originalLine; +/** + * An instance of the SourceMapGenerator represents a source map which is + * being built incrementally. You may pass an object with the following + * properties: + * + * - file: The filename of the generated source. + * - sourceRoot: A root for all relative URLs in this source map. + */ +function SourceMapGenerator(aArgs) { + if (!aArgs) { + aArgs = {}; + } + this._file = util.getArg(aArgs, 'file', null); + this._sourceRoot = util.getArg(aArgs, 'sourceRoot', null); + this._skipValidation = util.getArg(aArgs, 'skipValidation', false); + this._sources = new ArraySet(); + this._names = new ArraySet(); + this._mappings = new MappingList(); + this._sourcesContents = null; +} - // Iterate until either we run out of mappings, or we run into - // a mapping for a different line than the one we found. Since - // mappings are sorted, this is guaranteed to find all mappings for - // the line we found. - while (mapping && mapping.originalLine === originalLine) { - mappings.push({ - line: util.getArg(mapping, 'generatedLine', null), - column: util.getArg(mapping, 'generatedColumn', null), - lastColumn: util.getArg(mapping, 'lastGeneratedColumn', null) - }); +SourceMapGenerator.prototype._version = 3; - mapping = this._originalMappings[++index]; +/** + * Creates a new SourceMapGenerator based on a SourceMapConsumer + * + * @param aSourceMapConsumer The SourceMap. + */ +SourceMapGenerator.fromSourceMap = + function SourceMapGenerator_fromSourceMap(aSourceMapConsumer) { + var sourceRoot = aSourceMapConsumer.sourceRoot; + var generator = new SourceMapGenerator({ + file: aSourceMapConsumer.file, + sourceRoot: sourceRoot + }); + aSourceMapConsumer.eachMapping(function (mapping) { + var newMapping = { + generated: { + line: mapping.generatedLine, + column: mapping.generatedColumn } - } else { - var originalColumn = mapping.originalColumn; + }; - // Iterate until either we run out of mappings, or we run into - // a mapping for a different line than the one we were searching for. - // Since mappings are sorted, this is guaranteed to find all mappings for - // the line we are searching for. - while (mapping && - mapping.originalLine === line && - mapping.originalColumn == originalColumn) { - mappings.push({ - line: util.getArg(mapping, 'generatedLine', null), - column: util.getArg(mapping, 'generatedColumn', null), - lastColumn: util.getArg(mapping, 'lastGeneratedColumn', null) - }); + if (mapping.source != null) { + newMapping.source = mapping.source; + if (sourceRoot != null) { + newMapping.source = util.relative(sourceRoot, newMapping.source); + } - mapping = this._originalMappings[++index]; + newMapping.original = { + line: mapping.originalLine, + column: mapping.originalColumn + }; + + if (mapping.name != null) { + newMapping.name = mapping.name; } } - } - return mappings; + generator.addMapping(newMapping); + }); + aSourceMapConsumer.sources.forEach(function (sourceFile) { + var content = aSourceMapConsumer.sourceContentFor(sourceFile); + if (content != null) { + generator.setSourceContent(sourceFile, content); + } + }); + return generator; }; -exports.SourceMapConsumer = SourceMapConsumer; - /** - * A BasicSourceMapConsumer instance represents a parsed source map which we can - * query for information about the original file positions by giving it a file - * position in the generated source. - * - * The only parameter is the raw source map (either as a JSON string, or - * already parsed to an object). According to the spec, source maps have the - * following attributes: - * - * - version: Which version of the source map spec this map is following. - * - sources: An array of URLs to the original source files. - * - names: An array of identifiers which can be referrenced by individual mappings. - * - sourceRoot: Optional. The URL root from which all sources are relative. - * - sourcesContent: Optional. An array of contents of the original source files. - * - mappings: A string of base64 VLQs which contain the actual mappings. - * - file: Optional. The generated file this source map is associated with. - * - * Here is an example source map, taken from the source map spec[0]: - * - * { - * version : 3, - * file: "out.js", - * sourceRoot : "", - * sources: ["foo.js", "bar.js"], - * names: ["src", "maps", "are", "fun"], - * mappings: "AA,AB;;ABCDE;" - * } + * Add a single mapping from original source line and column to the generated + * source's line and column for this source map being created. The mapping + * object should have the following properties: * - * [0]: https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit?pli=1# + * - generated: An object with the generated line and column positions. + * - original: An object with the original line and column positions. + * - source: The original source file (relative to the sourceRoot). + * - name: An optional original token name for this mapping. */ -function BasicSourceMapConsumer(aSourceMap) { - var sourceMap = aSourceMap; - if (typeof aSourceMap === 'string') { - sourceMap = JSON.parse(aSourceMap.replace(/^\)\]\}'/, '')); - } +SourceMapGenerator.prototype.addMapping = + function SourceMapGenerator_addMapping(aArgs) { + var generated = util.getArg(aArgs, 'generated'); + var original = util.getArg(aArgs, 'original', null); + var source = util.getArg(aArgs, 'source', null); + var name = util.getArg(aArgs, 'name', null); - var version = util.getArg(sourceMap, 'version'); - var sources = util.getArg(sourceMap, 'sources'); - // Sass 3.3 leaves out the 'names' array, so we deviate from the spec (which - // requires the array) to play nice here. - var names = util.getArg(sourceMap, 'names', []); - var sourceRoot = util.getArg(sourceMap, 'sourceRoot', null); - var sourcesContent = util.getArg(sourceMap, 'sourcesContent', null); - var mappings = util.getArg(sourceMap, 'mappings'); - var file = util.getArg(sourceMap, 'file', null); + if (!this._skipValidation) { + this._validateMapping(generated, original, source, name); + } - // Once again, Sass deviates from the spec and supplies the version as a - // string rather than a number, so we use loose equality checking here. - if (version != this._version) { - throw new Error('Unsupported version: ' + version); - } + if (source != null) { + source = String(source); + if (!this._sources.has(source)) { + this._sources.add(source); + } + } - sources = sources - .map(String) - // Some source maps produce relative source paths like "./foo.js" instead of - // "foo.js". Normalize these first so that future comparisons will succeed. - // See bugzil.la/1090768. - .map(util.normalize) - // Always ensure that absolute sources are internally stored relative to - // the source root, if the source root is absolute. Not doing this would - // be particularly problematic when the source root is a prefix of the - // source (valid, but why??). See github issue #199 and bugzil.la/1188982. - .map(function (source) { - return sourceRoot && util.isAbsolute(sourceRoot) && util.isAbsolute(source) - ? util.relative(sourceRoot, source) - : source; - }); + if (name != null) { + name = String(name); + if (!this._names.has(name)) { + this._names.add(name); + } + } - // Pass `true` below to allow duplicate names and sources. While source maps - // are intended to be compressed and deduplicated, the TypeScript compiler - // sometimes generates source maps with duplicates in them. See Github issue - // #72 and bugzil.la/889492. - this._names = ArraySet.fromArray(names.map(String), true); - this._sources = ArraySet.fromArray(sources, true); + this._mappings.add({ + generatedLine: generated.line, + generatedColumn: generated.column, + originalLine: original != null && original.line, + originalColumn: original != null && original.column, + source: source, + name: name + }); + }; - this.sourceRoot = sourceRoot; - this.sourcesContent = sourcesContent; - this._mappings = mappings; - this.file = file; -} +/** + * Set the source content for a source file. + */ +SourceMapGenerator.prototype.setSourceContent = + function SourceMapGenerator_setSourceContent(aSourceFile, aSourceContent) { + var source = aSourceFile; + if (this._sourceRoot != null) { + source = util.relative(this._sourceRoot, source); + } -BasicSourceMapConsumer.prototype = Object.create(SourceMapConsumer.prototype); -BasicSourceMapConsumer.prototype.consumer = SourceMapConsumer; + if (aSourceContent != null) { + // Add the source content to the _sourcesContents map. + // Create a new _sourcesContents map if the property is null. + if (!this._sourcesContents) { + this._sourcesContents = Object.create(null); + } + this._sourcesContents[util.toSetString(source)] = aSourceContent; + } else if (this._sourcesContents) { + // Remove the source file from the _sourcesContents map. + // If the _sourcesContents map is empty, set the property to null. + delete this._sourcesContents[util.toSetString(source)]; + if (Object.keys(this._sourcesContents).length === 0) { + this._sourcesContents = null; + } + } + }; /** - * Create a BasicSourceMapConsumer from a SourceMapGenerator. + * Applies the mappings of a sub-source-map for a specific source file to the + * source map being generated. Each mapping to the supplied source file is + * rewritten using the supplied source map. Note: The resolution for the + * resulting mappings is the minimium of this map and the supplied map. * - * @param SourceMapGenerator aSourceMap - * The source map that will be consumed. - * @returns BasicSourceMapConsumer + * @param aSourceMapConsumer The source map to be applied. + * @param aSourceFile Optional. The filename of the source file. + * If omitted, SourceMapConsumer's file property will be used. + * @param aSourceMapPath Optional. The dirname of the path to the source map + * to be applied. If relative, it is relative to the SourceMapConsumer. + * This parameter is needed when the two source maps aren't in the same + * directory, and the source map to be applied contains relative source + * paths. If so, those relative source paths need to be rewritten + * relative to the SourceMapGenerator. */ -BasicSourceMapConsumer.fromSourceMap = - function SourceMapConsumer_fromSourceMap(aSourceMap) { - var smc = Object.create(BasicSourceMapConsumer.prototype); - - var names = smc._names = ArraySet.fromArray(aSourceMap._names.toArray(), true); - var sources = smc._sources = ArraySet.fromArray(aSourceMap._sources.toArray(), true); - smc.sourceRoot = aSourceMap._sourceRoot; - smc.sourcesContent = aSourceMap._generateSourcesContent(smc._sources.toArray(), - smc.sourceRoot); - smc.file = aSourceMap._file; +SourceMapGenerator.prototype.applySourceMap = + function SourceMapGenerator_applySourceMap(aSourceMapConsumer, aSourceFile, aSourceMapPath) { + var sourceFile = aSourceFile; + // If aSourceFile is omitted, we will use the file property of the SourceMap + if (aSourceFile == null) { + if (aSourceMapConsumer.file == null) { + throw new Error( + 'SourceMapGenerator.prototype.applySourceMap requires either an explicit source file, ' + + 'or the source map\'s "file" property. Both were omitted.' + ); + } + sourceFile = aSourceMapConsumer.file; + } + var sourceRoot = this._sourceRoot; + // Make "sourceFile" relative if an absolute Url is passed. + if (sourceRoot != null) { + sourceFile = util.relative(sourceRoot, sourceFile); + } + // Applying the SourceMap can add and remove items from the sources and + // the names array. + var newSources = new ArraySet(); + var newNames = new ArraySet(); - // Because we are modifying the entries (by converting string sources and - // names to indices into the sources and names ArraySets), we have to make - // a copy of the entry or else bad things happen. Shared mutable state - // strikes again! See github issue #191. + // Find mappings for the "sourceFile" + this._mappings.unsortedForEach(function (mapping) { + if (mapping.source === sourceFile && mapping.originalLine != null) { + // Check if it can be mapped by the source map, then update the mapping. + var original = aSourceMapConsumer.originalPositionFor({ + line: mapping.originalLine, + column: mapping.originalColumn + }); + if (original.source != null) { + // Copy mapping + mapping.source = original.source; + if (aSourceMapPath != null) { + mapping.source = util.join(aSourceMapPath, mapping.source) + } + if (sourceRoot != null) { + mapping.source = util.relative(sourceRoot, mapping.source); + } + mapping.originalLine = original.line; + mapping.originalColumn = original.column; + if (original.name != null) { + mapping.name = original.name; + } + } + } - var generatedMappings = aSourceMap._mappings.toArray().slice(); - var destGeneratedMappings = smc.__generatedMappings = []; - var destOriginalMappings = smc.__originalMappings = []; + var source = mapping.source; + if (source != null && !newSources.has(source)) { + newSources.add(source); + } - for (var i = 0, length = generatedMappings.length; i < length; i++) { - var srcMapping = generatedMappings[i]; - var destMapping = new Mapping; - destMapping.generatedLine = srcMapping.generatedLine; - destMapping.generatedColumn = srcMapping.generatedColumn; + var name = mapping.name; + if (name != null && !newNames.has(name)) { + newNames.add(name); + } - if (srcMapping.source) { - destMapping.source = sources.indexOf(srcMapping.source); - destMapping.originalLine = srcMapping.originalLine; - destMapping.originalColumn = srcMapping.originalColumn; + }, this); + this._sources = newSources; + this._names = newNames; - if (srcMapping.name) { - destMapping.name = names.indexOf(srcMapping.name); + // Copy sourcesContents of applied map. + aSourceMapConsumer.sources.forEach(function (sourceFile) { + var content = aSourceMapConsumer.sourceContentFor(sourceFile); + if (content != null) { + if (aSourceMapPath != null) { + sourceFile = util.join(aSourceMapPath, sourceFile); } - - destOriginalMappings.push(destMapping); + if (sourceRoot != null) { + sourceFile = util.relative(sourceRoot, sourceFile); + } + this.setSourceContent(sourceFile, content); } + }, this); + }; - destGeneratedMappings.push(destMapping); +/** + * A mapping can have one of the three levels of data: + * + * 1. Just the generated position. + * 2. The Generated position, original position, and original source. + * 3. Generated and original position, original source, as well as a name + * token. + * + * To maintain consistency, we validate that any new mapping being added falls + * in to one of these categories. + */ +SourceMapGenerator.prototype._validateMapping = + function SourceMapGenerator_validateMapping(aGenerated, aOriginal, aSource, + aName) { + // When aOriginal is truthy but has empty values for .line and .column, + // it is most likely a programmer error. In this case we throw a very + // specific error message to try to guide them the right way. + // For example: https://github.com/Polymer/polymer-bundler/pull/519 + if (aOriginal && typeof aOriginal.line !== 'number' && typeof aOriginal.column !== 'number') { + throw new Error( + 'original.line and original.column are not numbers -- you probably meant to omit ' + + 'the original mapping entirely and only map the generated position. If so, pass ' + + 'null for the original mapping instead of an object with empty or null values.' + ); + } + + if (aGenerated && 'line' in aGenerated && 'column' in aGenerated + && aGenerated.line > 0 && aGenerated.column >= 0 + && !aOriginal && !aSource && !aName) { + // Case 1. + return; + } + else if (aGenerated && 'line' in aGenerated && 'column' in aGenerated + && aOriginal && 'line' in aOriginal && 'column' in aOriginal + && aGenerated.line > 0 && aGenerated.column >= 0 + && aOriginal.line > 0 && aOriginal.column >= 0 + && aSource) { + // Cases 2 and 3. + return; + } + else { + throw new Error('Invalid mapping: ' + JSON.stringify({ + generated: aGenerated, + source: aSource, + original: aOriginal, + name: aName + })); } - - quickSort(smc.__originalMappings, util.compareByOriginalPositions); - - return smc; }; /** - * The version of the source mapping spec that we are consuming. - */ -BasicSourceMapConsumer.prototype._version = 3; - -/** - * The list of original sources. - */ -Object.defineProperty(BasicSourceMapConsumer.prototype, 'sources', { - get: function () { - return this._sources.toArray().map(function (s) { - return this.sourceRoot != null ? util.join(this.sourceRoot, s) : s; - }, this); - } -}); - -/** - * Provide the JIT with a nice shape / hidden class. - */ -function Mapping() { - this.generatedLine = 0; - this.generatedColumn = 0; - this.source = null; - this.originalLine = null; - this.originalColumn = null; - this.name = null; -} - -/** - * Parse the mappings in a string in to a data structure which we can easily - * query (the ordered arrays in the `this.__generatedMappings` and - * `this.__originalMappings` properties). + * Serialize the accumulated mappings in to the stream of base 64 VLQs + * specified by the source map format. */ -BasicSourceMapConsumer.prototype._parseMappings = - function SourceMapConsumer_parseMappings(aStr, aSourceRoot) { - var generatedLine = 1; +SourceMapGenerator.prototype._serializeMappings = + function SourceMapGenerator_serializeMappings() { var previousGeneratedColumn = 0; - var previousOriginalLine = 0; + var previousGeneratedLine = 1; var previousOriginalColumn = 0; - var previousSource = 0; + var previousOriginalLine = 0; var previousName = 0; - var length = aStr.length; - var index = 0; - var cachedSegments = {}; - var temp = {}; - var originalMappings = []; - var generatedMappings = []; - var mapping, str, segment, end, value; + var previousSource = 0; + var result = ''; + var next; + var mapping; + var nameIdx; + var sourceIdx; - while (index < length) { - if (aStr.charAt(index) === ';') { - generatedLine++; - index++; + var mappings = this._mappings.toArray(); + for (var i = 0, len = mappings.length; i < len; i++) { + mapping = mappings[i]; + next = '' + + if (mapping.generatedLine !== previousGeneratedLine) { previousGeneratedColumn = 0; - } - else if (aStr.charAt(index) === ',') { - index++; + while (mapping.generatedLine !== previousGeneratedLine) { + next += ';'; + previousGeneratedLine++; + } } else { - mapping = new Mapping(); - mapping.generatedLine = generatedLine; - - // Because each offset is encoded relative to the previous one, - // many segments often have the same encoding. We can exploit this - // fact by caching the parsed variable length fields of each segment, - // allowing us to avoid a second parse if we encounter the same - // segment again. - for (end = index; end < length; end++) { - if (this._charIsMappingSeparator(aStr, end)) { - break; - } - } - str = aStr.slice(index, end); - - segment = cachedSegments[str]; - if (segment) { - index += str.length; - } else { - segment = []; - while (index < end) { - base64VLQ.decode(aStr, index, temp); - value = temp.value; - index = temp.rest; - segment.push(value); - } - - if (segment.length === 2) { - throw new Error('Found a source, but no line and column'); - } - - if (segment.length === 3) { - throw new Error('Found a source and line, but no column'); + if (i > 0) { + if (!util.compareByGeneratedPositionsInflated(mapping, mappings[i - 1])) { + continue; } - - cachedSegments[str] = segment; + next += ','; } + } - // Generated column. - mapping.generatedColumn = previousGeneratedColumn + segment[0]; - previousGeneratedColumn = mapping.generatedColumn; - - if (segment.length > 1) { - // Original source. - mapping.source = previousSource + segment[1]; - previousSource += segment[1]; + next += base64VLQ.encode(mapping.generatedColumn + - previousGeneratedColumn); + previousGeneratedColumn = mapping.generatedColumn; - // Original line. - mapping.originalLine = previousOriginalLine + segment[2]; - previousOriginalLine = mapping.originalLine; - // Lines are stored 0-based - mapping.originalLine += 1; + if (mapping.source != null) { + sourceIdx = this._sources.indexOf(mapping.source); + next += base64VLQ.encode(sourceIdx - previousSource); + previousSource = sourceIdx; - // Original column. - mapping.originalColumn = previousOriginalColumn + segment[3]; - previousOriginalColumn = mapping.originalColumn; + // lines are stored 0-based in SourceMap spec version 3 + next += base64VLQ.encode(mapping.originalLine - 1 + - previousOriginalLine); + previousOriginalLine = mapping.originalLine - 1; - if (segment.length > 4) { - // Original name. - mapping.name = previousName + segment[4]; - previousName += segment[4]; - } - } + next += base64VLQ.encode(mapping.originalColumn + - previousOriginalColumn); + previousOriginalColumn = mapping.originalColumn; - generatedMappings.push(mapping); - if (typeof mapping.originalLine === 'number') { - originalMappings.push(mapping); + if (mapping.name != null) { + nameIdx = this._names.indexOf(mapping.name); + next += base64VLQ.encode(nameIdx - previousName); + previousName = nameIdx; } } + + result += next; } - quickSort(generatedMappings, util.compareByGeneratedPositionsDeflated); - this.__generatedMappings = generatedMappings; + return result; + }; - quickSort(originalMappings, util.compareByOriginalPositions); - this.__originalMappings = originalMappings; +SourceMapGenerator.prototype._generateSourcesContent = + function SourceMapGenerator_generateSourcesContent(aSources, aSourceRoot) { + return aSources.map(function (source) { + if (!this._sourcesContents) { + return null; + } + if (aSourceRoot != null) { + source = util.relative(aSourceRoot, source); + } + var key = util.toSetString(source); + return Object.prototype.hasOwnProperty.call(this._sourcesContents, key) + ? this._sourcesContents[key] + : null; + }, this); }; /** - * Find the mapping that best matches the hypothetical "needle" mapping that - * we are searching for in the given "haystack" of mappings. + * Externalize the source map. */ -BasicSourceMapConsumer.prototype._findMapping = - function SourceMapConsumer_findMapping(aNeedle, aMappings, aLineName, - aColumnName, aComparator, aBias) { - // To return the position we are searching for, we must first find the - // mapping for the given position and then return the opposite position it - // points to. Because the mappings are sorted, we can use binary search to - // find the best mapping. - - if (aNeedle[aLineName] <= 0) { - throw new TypeError('Line must be greater than or equal to 1, got ' - + aNeedle[aLineName]); +SourceMapGenerator.prototype.toJSON = + function SourceMapGenerator_toJSON() { + var map = { + version: this._version, + sources: this._sources.toArray(), + names: this._names.toArray(), + mappings: this._serializeMappings() + }; + if (this._file != null) { + map.file = this._file; } - if (aNeedle[aColumnName] < 0) { - throw new TypeError('Column must be greater than or equal to 0, got ' - + aNeedle[aColumnName]); + if (this._sourceRoot != null) { + map.sourceRoot = this._sourceRoot; + } + if (this._sourcesContents) { + map.sourcesContent = this._generateSourcesContent(map.sources, map.sourceRoot); } - return binarySearch.search(aNeedle, aMappings, aComparator, aBias); + return map; }; /** - * Compute the last column for each generated mapping. The last column is - * inclusive. + * Render the source map being generated to a string. */ -BasicSourceMapConsumer.prototype.computeColumnSpans = - function SourceMapConsumer_computeColumnSpans() { - for (var index = 0; index < this._generatedMappings.length; ++index) { - var mapping = this._generatedMappings[index]; +SourceMapGenerator.prototype.toString = + function SourceMapGenerator_toString() { + return JSON.stringify(this.toJSON()); + }; - // Mappings do not contain a field for the last generated columnt. We - // can come up with an optimistic estimate, however, by assuming that - // mappings are contiguous (i.e. given two consecutive mappings, the - // first mapping ends where the second one starts). - if (index + 1 < this._generatedMappings.length) { - var nextMapping = this._generatedMappings[index + 1]; +exports.SourceMapGenerator = SourceMapGenerator; - if (mapping.generatedLine === nextMapping.generatedLine) { - mapping.lastGeneratedColumn = nextMapping.generatedColumn - 1; - continue; - } - } - // The last mapping for each line spans the entire line. - mapping.lastGeneratedColumn = Infinity; - } - }; +/***/ }), +/* 618 */ +/***/ (function(module, exports, __webpack_require__) { -/** - * Returns the original source, line, and column information for the generated - * source's line and column positions provided. The only argument is an object - * with the following properties: +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause * - * - line: The line number in the generated source. - * - column: The column number in the generated source. - * - bias: Either 'SourceMapConsumer.GREATEST_LOWER_BOUND' or - * 'SourceMapConsumer.LEAST_UPPER_BOUND'. Specifies whether to return the - * closest element that is smaller than or greater than the one we are - * searching for, respectively, if the exact element cannot be found. - * Defaults to 'SourceMapConsumer.GREATEST_LOWER_BOUND'. + * Based on the Base 64 VLQ implementation in Closure Compiler: + * https://code.google.com/p/closure-compiler/source/browse/trunk/src/com/google/debugging/sourcemap/Base64VLQ.java * - * and an object is returned with the following properties: + * Copyright 2011 The Closure Compiler Authors. All rights reserved. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: * - * - source: The original source file, or null. - * - line: The line number in the original source, or null. - * - column: The column number in the original source, or null. - * - name: The original identifier, or null. + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -BasicSourceMapConsumer.prototype.originalPositionFor = - function SourceMapConsumer_originalPositionFor(aArgs) { - var needle = { - generatedLine: util.getArg(aArgs, 'line'), - generatedColumn: util.getArg(aArgs, 'column') - }; - var index = this._findMapping( - needle, - this._generatedMappings, - "generatedLine", - "generatedColumn", - util.compareByGeneratedPositionsDeflated, - util.getArg(aArgs, 'bias', SourceMapConsumer.GREATEST_LOWER_BOUND) - ); +var base64 = __webpack_require__(619); - if (index >= 0) { - var mapping = this._generatedMappings[index]; +// A single base 64 digit can contain 6 bits of data. For the base 64 variable +// length quantities we use in the source map spec, the first bit is the sign, +// the next four bits are the actual value, and the 6th bit is the +// continuation bit. The continuation bit tells us whether there are more +// digits in this value following this digit. +// +// Continuation +// | Sign +// | | +// V V +// 101011 - if (mapping.generatedLine === needle.generatedLine) { - var source = util.getArg(mapping, 'source', null); - if (source !== null) { - source = this._sources.at(source); - if (this.sourceRoot != null) { - source = util.join(this.sourceRoot, source); - } - } - var name = util.getArg(mapping, 'name', null); - if (name !== null) { - name = this._names.at(name); - } - return { - source: source, - line: util.getArg(mapping, 'originalLine', null), - column: util.getArg(mapping, 'originalColumn', null), - name: name - }; - } - } +var VLQ_BASE_SHIFT = 5; - return { - source: null, - line: null, - column: null, - name: null - }; - }; +// binary: 100000 +var VLQ_BASE = 1 << VLQ_BASE_SHIFT; + +// binary: 011111 +var VLQ_BASE_MASK = VLQ_BASE - 1; + +// binary: 100000 +var VLQ_CONTINUATION_BIT = VLQ_BASE; /** - * Return true if we have the source content for every source in the source - * map, false otherwise. + * Converts from a two-complement value to a value where the sign bit is + * placed in the least significant bit. For example, as decimals: + * 1 becomes 2 (10 binary), -1 becomes 3 (11 binary) + * 2 becomes 4 (100 binary), -2 becomes 5 (101 binary) */ -BasicSourceMapConsumer.prototype.hasContentsOfAllSources = - function BasicSourceMapConsumer_hasContentsOfAllSources() { - if (!this.sourcesContent) { - return false; +function toVLQSigned(aValue) { + return aValue < 0 + ? ((-aValue) << 1) + 1 + : (aValue << 1) + 0; +} + +/** + * Converts to a two-complement value from a value where the sign bit is + * placed in the least significant bit. For example, as decimals: + * 2 (10 binary) becomes 1, 3 (11 binary) becomes -1 + * 4 (100 binary) becomes 2, 5 (101 binary) becomes -2 + */ +function fromVLQSigned(aValue) { + var isNegative = (aValue & 1) === 1; + var shifted = aValue >> 1; + return isNegative + ? -shifted + : shifted; +} + +/** + * Returns the base 64 VLQ encoded value. + */ +exports.encode = function base64VLQ_encode(aValue) { + var encoded = ""; + var digit; + + var vlq = toVLQSigned(aValue); + + do { + digit = vlq & VLQ_BASE_MASK; + vlq >>>= VLQ_BASE_SHIFT; + if (vlq > 0) { + // There are still more digits in this value, so we must make sure the + // continuation bit is marked. + digit |= VLQ_CONTINUATION_BIT; } - return this.sourcesContent.length >= this._sources.size() && - !this.sourcesContent.some(function (sc) { return sc == null; }); - }; + encoded += base64.encode(digit); + } while (vlq > 0); + + return encoded; +}; /** - * Returns the original source content. The only argument is the url of the - * original source file. Returns null if no original source content is - * available. + * Decodes the next base 64 VLQ value from the given string and returns the + * value and the rest of the string via the out parameter. */ -BasicSourceMapConsumer.prototype.sourceContentFor = - function SourceMapConsumer_sourceContentFor(aSource, nullOnMissing) { - if (!this.sourcesContent) { - return null; +exports.decode = function base64VLQ_decode(aStr, aIndex, aOutParam) { + var strLen = aStr.length; + var result = 0; + var shift = 0; + var continuation, digit; + + do { + if (aIndex >= strLen) { + throw new Error("Expected more digits in base 64 VLQ value."); + } + + digit = base64.decode(aStr.charCodeAt(aIndex++)); + if (digit === -1) { + throw new Error("Invalid base64 digit: " + aStr.charAt(aIndex - 1)); } - if (this.sourceRoot != null) { - aSource = util.relative(this.sourceRoot, aSource); - } + continuation = !!(digit & VLQ_CONTINUATION_BIT); + digit &= VLQ_BASE_MASK; + result = result + (digit << shift); + shift += VLQ_BASE_SHIFT; + } while (continuation); + + aOutParam.value = fromVLQSigned(result); + aOutParam.rest = aIndex; +}; + + +/***/ }), +/* 619 */ +/***/ (function(module, exports) { + +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ + +var intToCharMap = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'.split(''); + +/** + * Encode an integer in the range of 0 to 63 to a single base 64 digit. + */ +exports.encode = function (number) { + if (0 <= number && number < intToCharMap.length) { + return intToCharMap[number]; + } + throw new TypeError("Must be between 0 and 63: " + number); +}; + +/** + * Decode a single base 64 character code digit to an integer. Returns -1 on + * failure. + */ +exports.decode = function (charCode) { + var bigA = 65; // 'A' + var bigZ = 90; // 'Z' + + var littleA = 97; // 'a' + var littleZ = 122; // 'z' + + var zero = 48; // '0' + var nine = 57; // '9' + + var plus = 43; // '+' + var slash = 47; // '/' + + var littleOffset = 26; + var numberOffset = 52; + + // 0 - 25: ABCDEFGHIJKLMNOPQRSTUVWXYZ + if (bigA <= charCode && charCode <= bigZ) { + return (charCode - bigA); + } + + // 26 - 51: abcdefghijklmnopqrstuvwxyz + if (littleA <= charCode && charCode <= littleZ) { + return (charCode - littleA + littleOffset); + } + + // 52 - 61: 0123456789 + if (zero <= charCode && charCode <= nine) { + return (charCode - zero + numberOffset); + } + + // 62: + + if (charCode == plus) { + return 62; + } + + // 63: / + if (charCode == slash) { + return 63; + } + + // Invalid base64 digit. + return -1; +}; - if (this._sources.has(aSource)) { - return this.sourcesContent[this._sources.indexOf(aSource)]; - } - var url; - if (this.sourceRoot != null - && (url = util.urlParse(this.sourceRoot))) { - // XXX: file:// URIs and absolute paths lead to unexpected behavior for - // many users. We can help them out when they expect file:// URIs to - // behave like it would if they were running a local HTTP server. See - // https://bugzilla.mozilla.org/show_bug.cgi?id=885597. - var fileUriAbsPath = aSource.replace(/^file:\/\//, ""); - if (url.scheme == "file" - && this._sources.has(fileUriAbsPath)) { - return this.sourcesContent[this._sources.indexOf(fileUriAbsPath)] - } +/***/ }), +/* 620 */ +/***/ (function(module, exports) { - if ((!url.path || url.path == "/") - && this._sources.has("/" + aSource)) { - return this.sourcesContent[this._sources.indexOf("/" + aSource)]; - } - } +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ - // This function is used recursively from - // IndexedSourceMapConsumer.prototype.sourceContentFor. In that case, we - // don't want to throw if we can't find the source - we just want to - // return null, so we provide a flag to exit gracefully. - if (nullOnMissing) { - return null; - } - else { - throw new Error('"' + aSource + '" is not in the SourceMap.'); - } +/** + * This is a helper function for getting values from parameter/options + * objects. + * + * @param args The object we are extracting values from + * @param name The name of the property we are getting. + * @param defaultValue An optional value to return if the property is missing + * from the object. If this is not specified and the property is missing, an + * error will be thrown. + */ +function getArg(aArgs, aName, aDefaultValue) { + if (aName in aArgs) { + return aArgs[aName]; + } else if (arguments.length === 3) { + return aDefaultValue; + } else { + throw new Error('"' + aName + '" is a required argument.'); + } +} +exports.getArg = getArg; + +var urlRegexp = /^(?:([\w+\-.]+):)?\/\/(?:(\w+:\w+)@)?([\w.]*)(?::(\d+))?(\S*)$/; +var dataUrlRegexp = /^data:.+\,.+$/; + +function urlParse(aUrl) { + var match = aUrl.match(urlRegexp); + if (!match) { + return null; + } + return { + scheme: match[1], + auth: match[2], + host: match[3], + port: match[4], + path: match[5] }; +} +exports.urlParse = urlParse; + +function urlGenerate(aParsedUrl) { + var url = ''; + if (aParsedUrl.scheme) { + url += aParsedUrl.scheme + ':'; + } + url += '//'; + if (aParsedUrl.auth) { + url += aParsedUrl.auth + '@'; + } + if (aParsedUrl.host) { + url += aParsedUrl.host; + } + if (aParsedUrl.port) { + url += ":" + aParsedUrl.port + } + if (aParsedUrl.path) { + url += aParsedUrl.path; + } + return url; +} +exports.urlGenerate = urlGenerate; /** - * Returns the generated line and column information for the original source, - * line, and column positions provided. The only argument is an object with - * the following properties: + * Normalizes a path, or the path portion of a URL: * - * - source: The filename of the original source. - * - line: The line number in the original source. - * - column: The column number in the original source. - * - bias: Either 'SourceMapConsumer.GREATEST_LOWER_BOUND' or - * 'SourceMapConsumer.LEAST_UPPER_BOUND'. Specifies whether to return the - * closest element that is smaller than or greater than the one we are - * searching for, respectively, if the exact element cannot be found. - * Defaults to 'SourceMapConsumer.GREATEST_LOWER_BOUND'. + * - Replaces consecutive slashes with one slash. + * - Removes unnecessary '.' parts. + * - Removes unnecessary '/..' parts. * - * and an object is returned with the following properties: + * Based on code in the Node.js 'path' core module. * - * - line: The line number in the generated source, or null. - * - column: The column number in the generated source, or null. + * @param aPath The path or url to normalize. */ -BasicSourceMapConsumer.prototype.generatedPositionFor = - function SourceMapConsumer_generatedPositionFor(aArgs) { - var source = util.getArg(aArgs, 'source'); - if (this.sourceRoot != null) { - source = util.relative(this.sourceRoot, source); - } - if (!this._sources.has(source)) { - return { - line: null, - column: null, - lastColumn: null - }; +function normalize(aPath) { + var path = aPath; + var url = urlParse(aPath); + if (url) { + if (!url.path) { + return aPath; } - source = this._sources.indexOf(source); - - var needle = { - source: source, - originalLine: util.getArg(aArgs, 'line'), - originalColumn: util.getArg(aArgs, 'column') - }; - - var index = this._findMapping( - needle, - this._originalMappings, - "originalLine", - "originalColumn", - util.compareByOriginalPositions, - util.getArg(aArgs, 'bias', SourceMapConsumer.GREATEST_LOWER_BOUND) - ); - - if (index >= 0) { - var mapping = this._originalMappings[index]; + path = url.path; + } + var isAbsolute = exports.isAbsolute(path); - if (mapping.source === needle.source) { - return { - line: util.getArg(mapping, 'generatedLine', null), - column: util.getArg(mapping, 'generatedColumn', null), - lastColumn: util.getArg(mapping, 'lastGeneratedColumn', null) - }; + var parts = path.split(/\/+/); + for (var part, up = 0, i = parts.length - 1; i >= 0; i--) { + part = parts[i]; + if (part === '.') { + parts.splice(i, 1); + } else if (part === '..') { + up++; + } else if (up > 0) { + if (part === '') { + // The first part is blank if the path is absolute. Trying to go + // above the root is a no-op. Therefore we can remove all '..' parts + // directly after the root. + parts.splice(i + 1, up); + up = 0; + } else { + parts.splice(i, 2); + up--; } } + } + path = parts.join('/'); - return { - line: null, - column: null, - lastColumn: null - }; - }; + if (path === '') { + path = isAbsolute ? '/' : '.'; + } -exports.BasicSourceMapConsumer = BasicSourceMapConsumer; + if (url) { + url.path = path; + return urlGenerate(url); + } + return path; +} +exports.normalize = normalize; /** - * An IndexedSourceMapConsumer instance represents a parsed source map which - * we can query for information. It differs from BasicSourceMapConsumer in - * that it takes "indexed" source maps (i.e. ones with a "sections" field) as - * input. - * - * The only parameter is a raw source map (either as a JSON string, or already - * parsed to an object). According to the spec for indexed source maps, they - * have the following attributes: - * - * - version: Which version of the source map spec this map is following. - * - file: Optional. The generated file this source map is associated with. - * - sections: A list of section definitions. - * - * Each value under the "sections" field has two fields: - * - offset: The offset into the original specified at which this section - * begins to apply, defined as an object with a "line" and "column" - * field. - * - map: A source map definition. This source map could also be indexed, - * but doesn't have to be. - * - * Instead of the "map" field, it's also possible to have a "url" field - * specifying a URL to retrieve a source map from, but that's currently - * unsupported. - * - * Here's an example source map, taken from the source map spec[0], but - * modified to omit a section which uses the "url" field. + * Joins two paths/URLs. * - * { - * version : 3, - * file: "app.js", - * sections: [{ - * offset: {line:100, column:10}, - * map: { - * version : 3, - * file: "section.js", - * sources: ["foo.js", "bar.js"], - * names: ["src", "maps", "are", "fun"], - * mappings: "AAAA,E;;ABCDE;" - * } - * }], - * } + * @param aRoot The root path or URL. + * @param aPath The path or URL to be joined with the root. * - * [0]: https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit#heading=h.535es3xeprgt + * - If aPath is a URL or a data URI, aPath is returned, unless aPath is a + * scheme-relative URL: Then the scheme of aRoot, if any, is prepended + * first. + * - Otherwise aPath is a path. If aRoot is a URL, then its path portion + * is updated with the result and aRoot is returned. Otherwise the result + * is returned. + * - If aPath is absolute, the result is aPath. + * - Otherwise the two paths are joined with a slash. + * - Joining for example 'http://' and 'www.example.com' is also supported. */ -function IndexedSourceMapConsumer(aSourceMap) { - var sourceMap = aSourceMap; - if (typeof aSourceMap === 'string') { - sourceMap = JSON.parse(aSourceMap.replace(/^\)\]\}'/, '')); +function join(aRoot, aPath) { + if (aRoot === "") { + aRoot = "."; + } + if (aPath === "") { + aPath = "."; + } + var aPathUrl = urlParse(aPath); + var aRootUrl = urlParse(aRoot); + if (aRootUrl) { + aRoot = aRootUrl.path || '/'; } - var version = util.getArg(sourceMap, 'version'); - var sections = util.getArg(sourceMap, 'sections'); - - if (version != this._version) { - throw new Error('Unsupported version: ' + version); + // `join(foo, '//www.example.org')` + if (aPathUrl && !aPathUrl.scheme) { + if (aRootUrl) { + aPathUrl.scheme = aRootUrl.scheme; + } + return urlGenerate(aPathUrl); } - this._sources = new ArraySet(); - this._names = new ArraySet(); + if (aPathUrl || aPath.match(dataUrlRegexp)) { + return aPath; + } - var lastOffset = { - line: -1, - column: 0 - }; - this._sections = sections.map(function (s) { - if (s.url) { - // The url field will require support for asynchronicity. - // See https://github.com/mozilla/source-map/issues/16 - throw new Error('Support for url field in sections not implemented.'); - } - var offset = util.getArg(s, 'offset'); - var offsetLine = util.getArg(offset, 'line'); - var offsetColumn = util.getArg(offset, 'column'); + // `join('http://', 'www.example.com')` + if (aRootUrl && !aRootUrl.host && !aRootUrl.path) { + aRootUrl.host = aPath; + return urlGenerate(aRootUrl); + } - if (offsetLine < lastOffset.line || - (offsetLine === lastOffset.line && offsetColumn < lastOffset.column)) { - throw new Error('Section offsets must be ordered and non-overlapping.'); - } - lastOffset = offset; + var joined = aPath.charAt(0) === '/' + ? aPath + : normalize(aRoot.replace(/\/+$/, '') + '/' + aPath); - return { - generatedOffset: { - // The offset fields are 0-based, but we use 1-based indices when - // encoding/decoding from VLQ. - generatedLine: offsetLine + 1, - generatedColumn: offsetColumn + 1 - }, - consumer: new SourceMapConsumer(util.getArg(s, 'map')) - } - }); + if (aRootUrl) { + aRootUrl.path = joined; + return urlGenerate(aRootUrl); + } + return joined; } +exports.join = join; -IndexedSourceMapConsumer.prototype = Object.create(SourceMapConsumer.prototype); -IndexedSourceMapConsumer.prototype.constructor = SourceMapConsumer; +exports.isAbsolute = function (aPath) { + return aPath.charAt(0) === '/' || !!aPath.match(urlRegexp); +}; /** - * The version of the source mapping spec that we are consuming. + * Make a path relative to a URL or another path. + * + * @param aRoot The root path or URL. + * @param aPath The path or URL to be made relative to aRoot. */ -IndexedSourceMapConsumer.prototype._version = 3; +function relative(aRoot, aPath) { + if (aRoot === "") { + aRoot = "."; + } -/** - * The list of original sources. - */ -Object.defineProperty(IndexedSourceMapConsumer.prototype, 'sources', { - get: function () { - var sources = []; - for (var i = 0; i < this._sections.length; i++) { - for (var j = 0; j < this._sections[i].consumer.sources.length; j++) { - sources.push(this._sections[i].consumer.sources[j]); - } + aRoot = aRoot.replace(/\/$/, ''); + + // It is possible for the path to be above the root. In this case, simply + // checking whether the root is a prefix of the path won't work. Instead, we + // need to remove components from the root one by one, until either we find + // a prefix that fits, or we run out of components to remove. + var level = 0; + while (aPath.indexOf(aRoot + '/') !== 0) { + var index = aRoot.lastIndexOf("/"); + if (index < 0) { + return aPath; } - return sources; + + // If the only part of the root that is left is the scheme (i.e. http://, + // file:///, etc.), one or more slashes (/), or simply nothing at all, we + // have exhausted all components, so the path is not relative to the root. + aRoot = aRoot.slice(0, index); + if (aRoot.match(/^([^\/]+:\/)?\/*$/)) { + return aPath; + } + + ++level; } -}); + + // Make sure we add a "../" for each component we removed from the root. + return Array(level + 1).join("../") + aPath.substr(aRoot.length + 1); +} +exports.relative = relative; + +var supportsNullProto = (function () { + var obj = Object.create(null); + return !('__proto__' in obj); +}()); + +function identity (s) { + return s; +} /** - * Returns the original source, line, and column information for the generated - * source's line and column positions provided. The only argument is an object - * with the following properties: - * - * - line: The line number in the generated source. - * - column: The column number in the generated source. + * Because behavior goes wacky when you set `__proto__` on objects, we + * have to prefix all the strings in our set with an arbitrary character. * - * and an object is returned with the following properties: + * See https://github.com/mozilla/source-map/pull/31 and + * https://github.com/mozilla/source-map/issues/30 * - * - source: The original source file, or null. - * - line: The line number in the original source, or null. - * - column: The column number in the original source, or null. - * - name: The original identifier, or null. + * @param String aStr */ -IndexedSourceMapConsumer.prototype.originalPositionFor = - function IndexedSourceMapConsumer_originalPositionFor(aArgs) { - var needle = { - generatedLine: util.getArg(aArgs, 'line'), - generatedColumn: util.getArg(aArgs, 'column') - }; +function toSetString(aStr) { + if (isProtoString(aStr)) { + return '$' + aStr; + } - // Find the section containing the generated position we're trying to map - // to an original position. - var sectionIndex = binarySearch.search(needle, this._sections, - function(needle, section) { - var cmp = needle.generatedLine - section.generatedOffset.generatedLine; - if (cmp) { - return cmp; - } + return aStr; +} +exports.toSetString = supportsNullProto ? identity : toSetString; - return (needle.generatedColumn - - section.generatedOffset.generatedColumn); - }); - var section = this._sections[sectionIndex]; +function fromSetString(aStr) { + if (isProtoString(aStr)) { + return aStr.slice(1); + } - if (!section) { - return { - source: null, - line: null, - column: null, - name: null - }; + return aStr; +} +exports.fromSetString = supportsNullProto ? identity : fromSetString; + +function isProtoString(s) { + if (!s) { + return false; + } + + var length = s.length; + + if (length < 9 /* "__proto__".length */) { + return false; + } + + if (s.charCodeAt(length - 1) !== 95 /* '_' */ || + s.charCodeAt(length - 2) !== 95 /* '_' */ || + s.charCodeAt(length - 3) !== 111 /* 'o' */ || + s.charCodeAt(length - 4) !== 116 /* 't' */ || + s.charCodeAt(length - 5) !== 111 /* 'o' */ || + s.charCodeAt(length - 6) !== 114 /* 'r' */ || + s.charCodeAt(length - 7) !== 112 /* 'p' */ || + s.charCodeAt(length - 8) !== 95 /* '_' */ || + s.charCodeAt(length - 9) !== 95 /* '_' */) { + return false; + } + + for (var i = length - 10; i >= 0; i--) { + if (s.charCodeAt(i) !== 36 /* '$' */) { + return false; } + } - return section.consumer.originalPositionFor({ - line: needle.generatedLine - - (section.generatedOffset.generatedLine - 1), - column: needle.generatedColumn - - (section.generatedOffset.generatedLine === needle.generatedLine - ? section.generatedOffset.generatedColumn - 1 - : 0), - bias: aArgs.bias - }); - }; + return true; +} /** - * Return true if we have the source content for every source in the source - * map, false otherwise. + * Comparator between two mappings where the original positions are compared. + * + * Optionally pass in `true` as `onlyCompareGenerated` to consider two + * mappings with the same original source/line/column, but different generated + * line and column the same. Useful when searching for a mapping with a + * stubbed out mapping. */ -IndexedSourceMapConsumer.prototype.hasContentsOfAllSources = - function IndexedSourceMapConsumer_hasContentsOfAllSources() { - return this._sections.every(function (s) { - return s.consumer.hasContentsOfAllSources(); - }); - }; +function compareByOriginalPositions(mappingA, mappingB, onlyCompareOriginal) { + var cmp = mappingA.source - mappingB.source; + if (cmp !== 0) { + return cmp; + } + + cmp = mappingA.originalLine - mappingB.originalLine; + if (cmp !== 0) { + return cmp; + } -/** - * Returns the original source content. The only argument is the url of the - * original source file. Returns null if no original source content is - * available. - */ -IndexedSourceMapConsumer.prototype.sourceContentFor = - function IndexedSourceMapConsumer_sourceContentFor(aSource, nullOnMissing) { - for (var i = 0; i < this._sections.length; i++) { - var section = this._sections[i]; + cmp = mappingA.originalColumn - mappingB.originalColumn; + if (cmp !== 0 || onlyCompareOriginal) { + return cmp; + } - var content = section.consumer.sourceContentFor(aSource, true); - if (content) { - return content; - } - } - if (nullOnMissing) { - return null; - } - else { - throw new Error('"' + aSource + '" is not in the SourceMap.'); - } - }; + cmp = mappingA.generatedColumn - mappingB.generatedColumn; + if (cmp !== 0) { + return cmp; + } + + cmp = mappingA.generatedLine - mappingB.generatedLine; + if (cmp !== 0) { + return cmp; + } + + return mappingA.name - mappingB.name; +} +exports.compareByOriginalPositions = compareByOriginalPositions; /** - * Returns the generated line and column information for the original source, - * line, and column positions provided. The only argument is an object with - * the following properties: - * - * - source: The filename of the original source. - * - line: The line number in the original source. - * - column: The column number in the original source. - * - * and an object is returned with the following properties: + * Comparator between two mappings with deflated source and name indices where + * the generated positions are compared. * - * - line: The line number in the generated source, or null. - * - column: The column number in the generated source, or null. + * Optionally pass in `true` as `onlyCompareGenerated` to consider two + * mappings with the same generated line and column, but different + * source/name/original line and column the same. Useful when searching for a + * mapping with a stubbed out mapping. */ -IndexedSourceMapConsumer.prototype.generatedPositionFor = - function IndexedSourceMapConsumer_generatedPositionFor(aArgs) { - for (var i = 0; i < this._sections.length; i++) { - var section = this._sections[i]; +function compareByGeneratedPositionsDeflated(mappingA, mappingB, onlyCompareGenerated) { + var cmp = mappingA.generatedLine - mappingB.generatedLine; + if (cmp !== 0) { + return cmp; + } - // Only consider this section if the requested source is in the list of - // sources of the consumer. - if (section.consumer.sources.indexOf(util.getArg(aArgs, 'source')) === -1) { - continue; - } - var generatedPosition = section.consumer.generatedPositionFor(aArgs); - if (generatedPosition) { - var ret = { - line: generatedPosition.line + - (section.generatedOffset.generatedLine - 1), - column: generatedPosition.column + - (section.generatedOffset.generatedLine === generatedPosition.line - ? section.generatedOffset.generatedColumn - 1 - : 0) - }; - return ret; - } - } + cmp = mappingA.generatedColumn - mappingB.generatedColumn; + if (cmp !== 0 || onlyCompareGenerated) { + return cmp; + } - return { - line: null, - column: null - }; - }; + cmp = mappingA.source - mappingB.source; + if (cmp !== 0) { + return cmp; + } + + cmp = mappingA.originalLine - mappingB.originalLine; + if (cmp !== 0) { + return cmp; + } + + cmp = mappingA.originalColumn - mappingB.originalColumn; + if (cmp !== 0) { + return cmp; + } + + return mappingA.name - mappingB.name; +} +exports.compareByGeneratedPositionsDeflated = compareByGeneratedPositionsDeflated; + +function strcmp(aStr1, aStr2) { + if (aStr1 === aStr2) { + return 0; + } + + if (aStr1 > aStr2) { + return 1; + } + + return -1; +} /** - * Parse the mappings in a string in to a data structure which we can easily - * query (the ordered arrays in the `this.__generatedMappings` and - * `this.__originalMappings` properties). + * Comparator between two mappings with inflated source and name strings where + * the generated positions are compared. */ -IndexedSourceMapConsumer.prototype._parseMappings = - function IndexedSourceMapConsumer_parseMappings(aStr, aSourceRoot) { - this.__generatedMappings = []; - this.__originalMappings = []; - for (var i = 0; i < this._sections.length; i++) { - var section = this._sections[i]; - var sectionMappings = section.consumer._generatedMappings; - for (var j = 0; j < sectionMappings.length; j++) { - var mapping = sectionMappings[j]; - - var source = section.consumer._sources.at(mapping.source); - if (section.consumer.sourceRoot !== null) { - source = util.join(section.consumer.sourceRoot, source); - } - this._sources.add(source); - source = this._sources.indexOf(source); +function compareByGeneratedPositionsInflated(mappingA, mappingB) { + var cmp = mappingA.generatedLine - mappingB.generatedLine; + if (cmp !== 0) { + return cmp; + } - var name = section.consumer._names.at(mapping.name); - this._names.add(name); - name = this._names.indexOf(name); + cmp = mappingA.generatedColumn - mappingB.generatedColumn; + if (cmp !== 0) { + return cmp; + } - // The mappings coming from the consumer for the section have - // generated positions relative to the start of the section, so we - // need to offset them to be relative to the start of the concatenated - // generated file. - var adjustedMapping = { - source: source, - generatedLine: mapping.generatedLine + - (section.generatedOffset.generatedLine - 1), - generatedColumn: mapping.generatedColumn + - (section.generatedOffset.generatedLine === mapping.generatedLine - ? section.generatedOffset.generatedColumn - 1 - : 0), - originalLine: mapping.originalLine, - originalColumn: mapping.originalColumn, - name: name - }; + cmp = strcmp(mappingA.source, mappingB.source); + if (cmp !== 0) { + return cmp; + } - this.__generatedMappings.push(adjustedMapping); - if (typeof adjustedMapping.originalLine === 'number') { - this.__originalMappings.push(adjustedMapping); - } - } - } + cmp = mappingA.originalLine - mappingB.originalLine; + if (cmp !== 0) { + return cmp; + } - quickSort(this.__generatedMappings, util.compareByGeneratedPositionsDeflated); - quickSort(this.__originalMappings, util.compareByOriginalPositions); - }; + cmp = mappingA.originalColumn - mappingB.originalColumn; + if (cmp !== 0) { + return cmp; + } -exports.IndexedSourceMapConsumer = IndexedSourceMapConsumer; + return strcmp(mappingA.name, mappingB.name); +} +exports.compareByGeneratedPositionsInflated = compareByGeneratedPositionsInflated; /***/ }), /* 621 */ -/***/ (function(module, exports) { +/***/ (function(module, exports, __webpack_require__) { /* -*- Mode: js; js-indent-level: 2; -*- */ /* @@ -72687,231 +71758,206 @@ exports.IndexedSourceMapConsumer = IndexedSourceMapConsumer; * http://opensource.org/licenses/BSD-3-Clause */ -exports.GREATEST_LOWER_BOUND = 1; -exports.LEAST_UPPER_BOUND = 2; +var util = __webpack_require__(620); +var has = Object.prototype.hasOwnProperty; +var hasNativeMap = typeof Map !== "undefined"; /** - * Recursive implementation of binary search. - * - * @param aLow Indices here and lower do not contain the needle. - * @param aHigh Indices here and higher do not contain the needle. - * @param aNeedle The element being searched for. - * @param aHaystack The non-empty array being searched. - * @param aCompare Function which takes two elements and returns -1, 0, or 1. - * @param aBias Either 'binarySearch.GREATEST_LOWER_BOUND' or - * 'binarySearch.LEAST_UPPER_BOUND'. Specifies whether to return the - * closest element that is smaller than or greater than the one we are - * searching for, respectively, if the exact element cannot be found. + * A data structure which is a combination of an array and a set. Adding a new + * member is O(1), testing for membership is O(1), and finding the index of an + * element is O(1). Removing elements from the set is not supported. Only + * strings are supported for membership. */ -function recursiveSearch(aLow, aHigh, aNeedle, aHaystack, aCompare, aBias) { - // This function terminates when one of the following is true: - // - // 1. We find the exact element we are looking for. - // - // 2. We did not find the exact element, but we can return the index of - // the next-closest element. - // - // 3. We did not find the exact element, and there is no next-closest - // element than the one we are searching for, so we return -1. - var mid = Math.floor((aHigh - aLow) / 2) + aLow; - var cmp = aCompare(aNeedle, aHaystack[mid], true); - if (cmp === 0) { - // Found the element we are looking for. - return mid; - } - else if (cmp > 0) { - // Our needle is greater than aHaystack[mid]. - if (aHigh - mid > 1) { - // The element is in the upper half. - return recursiveSearch(mid, aHigh, aNeedle, aHaystack, aCompare, aBias); - } +function ArraySet() { + this._array = []; + this._set = hasNativeMap ? new Map() : Object.create(null); +} - // The exact needle element was not found in this haystack. Determine if - // we are in termination case (3) or (2) and return the appropriate thing. - if (aBias == exports.LEAST_UPPER_BOUND) { - return aHigh < aHaystack.length ? aHigh : -1; - } else { - return mid; - } +/** + * Static method for creating ArraySet instances from an existing array. + */ +ArraySet.fromArray = function ArraySet_fromArray(aArray, aAllowDuplicates) { + var set = new ArraySet(); + for (var i = 0, len = aArray.length; i < len; i++) { + set.add(aArray[i], aAllowDuplicates); } - else { - // Our needle is less than aHaystack[mid]. - if (mid - aLow > 1) { - // The element is in the lower half. - return recursiveSearch(aLow, mid, aNeedle, aHaystack, aCompare, aBias); - } + return set; +}; - // we are in termination case (3) or (2) and return the appropriate thing. - if (aBias == exports.LEAST_UPPER_BOUND) { - return mid; +/** + * Return how many unique items are in this ArraySet. If duplicates have been + * added, than those do not count towards the size. + * + * @returns Number + */ +ArraySet.prototype.size = function ArraySet_size() { + return hasNativeMap ? this._set.size : Object.getOwnPropertyNames(this._set).length; +}; + +/** + * Add the given string to this set. + * + * @param String aStr + */ +ArraySet.prototype.add = function ArraySet_add(aStr, aAllowDuplicates) { + var sStr = hasNativeMap ? aStr : util.toSetString(aStr); + var isDuplicate = hasNativeMap ? this.has(aStr) : has.call(this._set, sStr); + var idx = this._array.length; + if (!isDuplicate || aAllowDuplicates) { + this._array.push(aStr); + } + if (!isDuplicate) { + if (hasNativeMap) { + this._set.set(aStr, idx); } else { - return aLow < 0 ? -1 : aLow; + this._set[sStr] = idx; } } -} +}; /** - * This is an implementation of binary search which will always try and return - * the index of the closest element if there is no exact hit. This is because - * mappings between original and generated line/col pairs are single points, - * and there is an implicit region between each of them, so a miss just means - * that you aren't on the very start of a region. + * Is the given string a member of this set? * - * @param aNeedle The element you are looking for. - * @param aHaystack The array that is being searched. - * @param aCompare A function which takes the needle and an element in the - * array and returns -1, 0, or 1 depending on whether the needle is less - * than, equal to, or greater than the element, respectively. - * @param aBias Either 'binarySearch.GREATEST_LOWER_BOUND' or - * 'binarySearch.LEAST_UPPER_BOUND'. Specifies whether to return the - * closest element that is smaller than or greater than the one we are - * searching for, respectively, if the exact element cannot be found. - * Defaults to 'binarySearch.GREATEST_LOWER_BOUND'. + * @param String aStr */ -exports.search = function search(aNeedle, aHaystack, aCompare, aBias) { - if (aHaystack.length === 0) { - return -1; +ArraySet.prototype.has = function ArraySet_has(aStr) { + if (hasNativeMap) { + return this._set.has(aStr); + } else { + var sStr = util.toSetString(aStr); + return has.call(this._set, sStr); } +}; - var index = recursiveSearch(-1, aHaystack.length, aNeedle, aHaystack, - aCompare, aBias || exports.GREATEST_LOWER_BOUND); - if (index < 0) { - return -1; +/** + * What is the index of the given string in the array? + * + * @param String aStr + */ +ArraySet.prototype.indexOf = function ArraySet_indexOf(aStr) { + if (hasNativeMap) { + var idx = this._set.get(aStr); + if (idx >= 0) { + return idx; + } + } else { + var sStr = util.toSetString(aStr); + if (has.call(this._set, sStr)) { + return this._set[sStr]; + } } - // We have found either the exact element, or the next-closest element than - // the one we are searching for. However, there may be more than one such - // element. Make sure we always return the smallest of these. - while (index - 1 >= 0) { - if (aCompare(aHaystack[index], aHaystack[index - 1], true) !== 0) { - break; - } - --index; + throw new Error('"' + aStr + '" is not in the set.'); +}; + +/** + * What is the element at the given index? + * + * @param Number aIdx + */ +ArraySet.prototype.at = function ArraySet_at(aIdx) { + if (aIdx >= 0 && aIdx < this._array.length) { + return this._array[aIdx]; } + throw new Error('No element indexed by ' + aIdx); +}; - return index; +/** + * Returns the array representation of this set (which has the proper indices + * indicated by indexOf). Note that this is a copy of the internal array used + * for storing the members so that no one can mess with internal state. + */ +ArraySet.prototype.toArray = function ArraySet_toArray() { + return this._array.slice(); }; +exports.ArraySet = ArraySet; + /***/ }), /* 622 */ -/***/ (function(module, exports) { +/***/ (function(module, exports, __webpack_require__) { /* -*- Mode: js; js-indent-level: 2; -*- */ /* - * Copyright 2011 Mozilla Foundation and contributors + * Copyright 2014 Mozilla Foundation and contributors * Licensed under the New BSD license. See LICENSE or: * http://opensource.org/licenses/BSD-3-Clause */ -// It turns out that some (most?) JavaScript engines don't self-host -// `Array.prototype.sort`. This makes sense because C++ will likely remain -// faster than JS when doing raw CPU-intensive sorting. However, when using a -// custom comparator function, calling back and forth between the VM's C++ and -// JIT'd JS is rather slow *and* loses JIT type information, resulting in -// worse generated code for the comparator function than would be optimal. In -// fact, when sorting with a comparator, these costs outweigh the benefits of -// sorting in C++. By using our own JS-implemented Quick Sort (below), we get -// a ~3500ms mean speed-up in `bench/bench.html`. +var util = __webpack_require__(620); /** - * Swap the elements indexed by `x` and `y` in the array `ary`. - * - * @param {Array} ary - * The array. - * @param {Number} x - * The index of the first item. - * @param {Number} y - * The index of the second item. + * Determine whether mappingB is after mappingA with respect to generated + * position. */ -function swap(ary, x, y) { - var temp = ary[x]; - ary[x] = ary[y]; - ary[y] = temp; +function generatedPositionAfter(mappingA, mappingB) { + // Optimized for most common case + var lineA = mappingA.generatedLine; + var lineB = mappingB.generatedLine; + var columnA = mappingA.generatedColumn; + var columnB = mappingB.generatedColumn; + return lineB > lineA || lineB == lineA && columnB >= columnA || + util.compareByGeneratedPositionsInflated(mappingA, mappingB) <= 0; } /** - * Returns a random integer within the range `low .. high` inclusive. - * - * @param {Number} low - * The lower bound on the range. - * @param {Number} high - * The upper bound on the range. + * A data structure to provide a sorted view of accumulated mappings in a + * performance conscious manner. It trades a neglibable overhead in general + * case for a large speedup in case of mappings being added in order. */ -function randomIntInRange(low, high) { - return Math.round(low + (Math.random() * (high - low))); +function MappingList() { + this._array = []; + this._sorted = true; + // Serves as infimum + this._last = {generatedLine: -1, generatedColumn: 0}; } /** - * The Quick Sort algorithm. + * Iterate through internal items. This method takes the same arguments that + * `Array.prototype.forEach` takes. * - * @param {Array} ary - * An array to sort. - * @param {function} comparator - * Function to use to compare two items. - * @param {Number} p - * Start index of the array - * @param {Number} r - * End index of the array + * NOTE: The order of the mappings is NOT guaranteed. */ -function doQuickSort(ary, comparator, p, r) { - // If our lower bound is less than our upper bound, we (1) partition the - // array into two pieces and (2) recurse on each half. If it is not, this is - // the empty array and our base case. - - if (p < r) { - // (1) Partitioning. - // - // The partitioning chooses a pivot between `p` and `r` and moves all - // elements that are less than or equal to the pivot to the before it, and - // all the elements that are greater than it after it. The effect is that - // once partition is done, the pivot is in the exact place it will be when - // the array is put in sorted order, and it will not need to be moved - // again. This runs in O(n) time. - - // Always choose a random pivot so that an input array which is reverse - // sorted does not cause O(n^2) running time. - var pivotIndex = randomIntInRange(p, r); - var i = p - 1; - - swap(ary, pivotIndex, r); - var pivot = ary[r]; - - // Immediately after `j` is incremented in this loop, the following hold - // true: - // - // * Every element in `ary[p .. i]` is less than or equal to the pivot. - // - // * Every element in `ary[i+1 .. j-1]` is greater than the pivot. - for (var j = p; j < r; j++) { - if (comparator(ary[j], pivot) <= 0) { - i += 1; - swap(ary, i, j); - } - } - - swap(ary, i + 1, j); - var q = i + 1; - - // (2) Recurse on each half. +MappingList.prototype.unsortedForEach = + function MappingList_forEach(aCallback, aThisArg) { + this._array.forEach(aCallback, aThisArg); + }; - doQuickSort(ary, comparator, p, q - 1); - doQuickSort(ary, comparator, q + 1, r); +/** + * Add the given source mapping. + * + * @param Object aMapping + */ +MappingList.prototype.add = function MappingList_add(aMapping) { + if (generatedPositionAfter(this._last, aMapping)) { + this._last = aMapping; + this._array.push(aMapping); + } else { + this._sorted = false; + this._array.push(aMapping); } -} +}; /** - * Sort the given array in-place with the given comparator function. + * Returns the flat, sorted array of mappings. The mappings are sorted by + * generated position. * - * @param {Array} ary - * An array to sort. - * @param {function} comparator - * Function to use to compare two items. - */ -exports.quickSort = function (ary, comparator) { - doQuickSort(ary, comparator, 0, ary.length - 1); + * WARNING: This method returns internal data without copying, for + * performance. The return value must NOT be mutated, and should be treated as + * an immutable borrow. If you want to take ownership, you must make your own + * copy. + */ +MappingList.prototype.toArray = function MappingList_toArray() { + if (!this._sorted) { + this._array.sort(util.compareByGeneratedPositionsInflated); + this._sorted = true; + } + return this._array; }; +exports.MappingList = MappingList; + /***/ }), /* 623 */ @@ -72924,2575 +71970,3112 @@ exports.quickSort = function (ary, comparator) { * http://opensource.org/licenses/BSD-3-Clause */ -var SourceMapGenerator = __webpack_require__(614).SourceMapGenerator; -var util = __webpack_require__(617); +var util = __webpack_require__(620); +var binarySearch = __webpack_require__(624); +var ArraySet = __webpack_require__(621).ArraySet; +var base64VLQ = __webpack_require__(618); +var quickSort = __webpack_require__(625).quickSort; -// Matches a Windows-style `\r\n` newline or a `\n` newline used by all other -// operating systems these days (capturing the result). -var REGEX_NEWLINE = /(\r?\n)/; +function SourceMapConsumer(aSourceMap) { + var sourceMap = aSourceMap; + if (typeof aSourceMap === 'string') { + sourceMap = JSON.parse(aSourceMap.replace(/^\)\]\}'/, '')); + } -// Newline character code for charCodeAt() comparisons -var NEWLINE_CODE = 10; + return sourceMap.sections != null + ? new IndexedSourceMapConsumer(sourceMap) + : new BasicSourceMapConsumer(sourceMap); +} -// Private symbol for identifying `SourceNode`s when multiple versions of -// the source-map library are loaded. This MUST NOT CHANGE across -// versions! -var isSourceNode = "$$$isSourceNode$$$"; +SourceMapConsumer.fromSourceMap = function(aSourceMap) { + return BasicSourceMapConsumer.fromSourceMap(aSourceMap); +} /** - * SourceNodes provide a way to abstract over interpolating/concatenating - * snippets of generated JavaScript source code while maintaining the line and - * column information associated with the original source code. - * - * @param aLine The original line number. - * @param aColumn The original column number. - * @param aSource The original source's filename. - * @param aChunks Optional. An array of strings which are snippets of - * generated JS, or other SourceNodes. - * @param aName The original identifier. + * The version of the source mapping spec that we are consuming. */ -function SourceNode(aLine, aColumn, aSource, aChunks, aName) { - this.children = []; - this.sourceContents = {}; - this.line = aLine == null ? null : aLine; - this.column = aColumn == null ? null : aColumn; - this.source = aSource == null ? null : aSource; - this.name = aName == null ? null : aName; - this[isSourceNode] = true; - if (aChunks != null) this.add(aChunks); -} +SourceMapConsumer.prototype._version = 3; + +// `__generatedMappings` and `__originalMappings` are arrays that hold the +// parsed mapping coordinates from the source map's "mappings" attribute. They +// are lazily instantiated, accessed via the `_generatedMappings` and +// `_originalMappings` getters respectively, and we only parse the mappings +// and create these arrays once queried for a source location. We jump through +// these hoops because there can be many thousands of mappings, and parsing +// them is expensive, so we only want to do it if we must. +// +// Each object in the arrays is of the form: +// +// { +// generatedLine: The line number in the generated code, +// generatedColumn: The column number in the generated code, +// source: The path to the original source file that generated this +// chunk of code, +// originalLine: The line number in the original source that +// corresponds to this chunk of generated code, +// originalColumn: The column number in the original source that +// corresponds to this chunk of generated code, +// name: The name of the original symbol which generated this chunk of +// code. +// } +// +// All properties except for `generatedLine` and `generatedColumn` can be +// `null`. +// +// `_generatedMappings` is ordered by the generated positions. +// +// `_originalMappings` is ordered by the original positions. + +SourceMapConsumer.prototype.__generatedMappings = null; +Object.defineProperty(SourceMapConsumer.prototype, '_generatedMappings', { + get: function () { + if (!this.__generatedMappings) { + this._parseMappings(this._mappings, this.sourceRoot); + } + + return this.__generatedMappings; + } +}); + +SourceMapConsumer.prototype.__originalMappings = null; +Object.defineProperty(SourceMapConsumer.prototype, '_originalMappings', { + get: function () { + if (!this.__originalMappings) { + this._parseMappings(this._mappings, this.sourceRoot); + } + + return this.__originalMappings; + } +}); + +SourceMapConsumer.prototype._charIsMappingSeparator = + function SourceMapConsumer_charIsMappingSeparator(aStr, index) { + var c = aStr.charAt(index); + return c === ";" || c === ","; + }; /** - * Creates a SourceNode from generated code and a SourceMapConsumer. + * Parse the mappings in a string in to a data structure which we can easily + * query (the ordered arrays in the `this.__generatedMappings` and + * `this.__originalMappings` properties). + */ +SourceMapConsumer.prototype._parseMappings = + function SourceMapConsumer_parseMappings(aStr, aSourceRoot) { + throw new Error("Subclasses must implement _parseMappings"); + }; + +SourceMapConsumer.GENERATED_ORDER = 1; +SourceMapConsumer.ORIGINAL_ORDER = 2; + +SourceMapConsumer.GREATEST_LOWER_BOUND = 1; +SourceMapConsumer.LEAST_UPPER_BOUND = 2; + +/** + * Iterate over each mapping between an original source/line/column and a + * generated line/column in this source map. * - * @param aGeneratedCode The generated code - * @param aSourceMapConsumer The SourceMap for the generated code - * @param aRelativePath Optional. The path that relative sources in the - * SourceMapConsumer should be relative to. + * @param Function aCallback + * The function that is called with each mapping. + * @param Object aContext + * Optional. If specified, this object will be the value of `this` every + * time that `aCallback` is called. + * @param aOrder + * Either `SourceMapConsumer.GENERATED_ORDER` or + * `SourceMapConsumer.ORIGINAL_ORDER`. Specifies whether you want to + * iterate over the mappings sorted by the generated file's line/column + * order or the original's source/line/column order, respectively. Defaults to + * `SourceMapConsumer.GENERATED_ORDER`. */ -SourceNode.fromStringWithSourceMap = - function SourceNode_fromStringWithSourceMap(aGeneratedCode, aSourceMapConsumer, aRelativePath) { - // The SourceNode we want to fill with the generated code - // and the SourceMap - var node = new SourceNode(); +SourceMapConsumer.prototype.eachMapping = + function SourceMapConsumer_eachMapping(aCallback, aContext, aOrder) { + var context = aContext || null; + var order = aOrder || SourceMapConsumer.GENERATED_ORDER; - // All even indices of this array are one line of the generated code, - // while all odd indices are the newlines between two adjacent lines - // (since `REGEX_NEWLINE` captures its match). - // Processed fragments are accessed by calling `shiftNextLine`. - var remainingLines = aGeneratedCode.split(REGEX_NEWLINE); - var remainingLinesIndex = 0; - var shiftNextLine = function() { - var lineContents = getNextLine(); - // The last line of a file might not have a newline. - var newLine = getNextLine() || ""; - return lineContents + newLine; + var mappings; + switch (order) { + case SourceMapConsumer.GENERATED_ORDER: + mappings = this._generatedMappings; + break; + case SourceMapConsumer.ORIGINAL_ORDER: + mappings = this._originalMappings; + break; + default: + throw new Error("Unknown order of iteration."); + } - function getNextLine() { - return remainingLinesIndex < remainingLines.length ? - remainingLines[remainingLinesIndex++] : undefined; + var sourceRoot = this.sourceRoot; + mappings.map(function (mapping) { + var source = mapping.source === null ? null : this._sources.at(mapping.source); + if (source != null && sourceRoot != null) { + source = util.join(sourceRoot, source); } - }; + return { + source: source, + generatedLine: mapping.generatedLine, + generatedColumn: mapping.generatedColumn, + originalLine: mapping.originalLine, + originalColumn: mapping.originalColumn, + name: mapping.name === null ? null : this._names.at(mapping.name) + }; + }, this).forEach(aCallback, context); + }; - // We need to remember the position of "remainingLines" - var lastGeneratedLine = 1, lastGeneratedColumn = 0; +/** + * Returns all generated line and column information for the original source, + * line, and column provided. If no column is provided, returns all mappings + * corresponding to a either the line we are searching for or the next + * closest line that has any mappings. Otherwise, returns all mappings + * corresponding to the given line and either the column we are searching for + * or the next closest column that has any offsets. + * + * The only argument is an object with the following properties: + * + * - source: The filename of the original source. + * - line: The line number in the original source. + * - column: Optional. the column number in the original source. + * + * and an array of objects is returned, each with the following properties: + * + * - line: The line number in the generated source, or null. + * - column: The column number in the generated source, or null. + */ +SourceMapConsumer.prototype.allGeneratedPositionsFor = + function SourceMapConsumer_allGeneratedPositionsFor(aArgs) { + var line = util.getArg(aArgs, 'line'); - // The generate SourceNodes we need a code range. - // To extract it current and last mapping is used. - // Here we store the last mapping. - var lastMapping = null; + // When there is no exact match, BasicSourceMapConsumer.prototype._findMapping + // returns the index of the closest mapping less than the needle. By + // setting needle.originalColumn to 0, we thus find the last mapping for + // the given line, provided such a mapping exists. + var needle = { + source: util.getArg(aArgs, 'source'), + originalLine: line, + originalColumn: util.getArg(aArgs, 'column', 0) + }; - aSourceMapConsumer.eachMapping(function (mapping) { - if (lastMapping !== null) { - // We add the code from "lastMapping" to "mapping": - // First check if there is a new line in between. - if (lastGeneratedLine < mapping.generatedLine) { - // Associate first line with "lastMapping" - addMappingWithCode(lastMapping, shiftNextLine()); - lastGeneratedLine++; - lastGeneratedColumn = 0; - // The remaining code is added without mapping - } else { - // There is no new line in between. - // Associate the code between "lastGeneratedColumn" and - // "mapping.generatedColumn" with "lastMapping" - var nextLine = remainingLines[remainingLinesIndex]; - var code = nextLine.substr(0, mapping.generatedColumn - - lastGeneratedColumn); - remainingLines[remainingLinesIndex] = nextLine.substr(mapping.generatedColumn - - lastGeneratedColumn); - lastGeneratedColumn = mapping.generatedColumn; - addMappingWithCode(lastMapping, code); - // No more remaining code, continue - lastMapping = mapping; - return; - } - } - // We add the generated code until the first mapping - // to the SourceNode without any mapping. - // Each line is added as separate string. - while (lastGeneratedLine < mapping.generatedLine) { - node.add(shiftNextLine()); - lastGeneratedLine++; - } - if (lastGeneratedColumn < mapping.generatedColumn) { - var nextLine = remainingLines[remainingLinesIndex]; - node.add(nextLine.substr(0, mapping.generatedColumn)); - remainingLines[remainingLinesIndex] = nextLine.substr(mapping.generatedColumn); - lastGeneratedColumn = mapping.generatedColumn; - } - lastMapping = mapping; - }, this); - // We have processed all mappings. - if (remainingLinesIndex < remainingLines.length) { - if (lastMapping) { - // Associate the remaining code in the current line with "lastMapping" - addMappingWithCode(lastMapping, shiftNextLine()); - } - // and add the remaining lines without any mapping - node.add(remainingLines.splice(remainingLinesIndex).join("")); + if (this.sourceRoot != null) { + needle.source = util.relative(this.sourceRoot, needle.source); + } + if (!this._sources.has(needle.source)) { + return []; } + needle.source = this._sources.indexOf(needle.source); - // Copy sourcesContent into SourceNode - aSourceMapConsumer.sources.forEach(function (sourceFile) { - var content = aSourceMapConsumer.sourceContentFor(sourceFile); - if (content != null) { - if (aRelativePath != null) { - sourceFile = util.join(aRelativePath, sourceFile); - } - node.setSourceContent(sourceFile, content); - } - }); + var mappings = []; - return node; + var index = this._findMapping(needle, + this._originalMappings, + "originalLine", + "originalColumn", + util.compareByOriginalPositions, + binarySearch.LEAST_UPPER_BOUND); + if (index >= 0) { + var mapping = this._originalMappings[index]; - function addMappingWithCode(mapping, code) { - if (mapping === null || mapping.source === undefined) { - node.add(code); + if (aArgs.column === undefined) { + var originalLine = mapping.originalLine; + + // Iterate until either we run out of mappings, or we run into + // a mapping for a different line than the one we found. Since + // mappings are sorted, this is guaranteed to find all mappings for + // the line we found. + while (mapping && mapping.originalLine === originalLine) { + mappings.push({ + line: util.getArg(mapping, 'generatedLine', null), + column: util.getArg(mapping, 'generatedColumn', null), + lastColumn: util.getArg(mapping, 'lastGeneratedColumn', null) + }); + + mapping = this._originalMappings[++index]; + } } else { - var source = aRelativePath - ? util.join(aRelativePath, mapping.source) - : mapping.source; - node.add(new SourceNode(mapping.originalLine, - mapping.originalColumn, - source, - code, - mapping.name)); + var originalColumn = mapping.originalColumn; + + // Iterate until either we run out of mappings, or we run into + // a mapping for a different line than the one we were searching for. + // Since mappings are sorted, this is guaranteed to find all mappings for + // the line we are searching for. + while (mapping && + mapping.originalLine === line && + mapping.originalColumn == originalColumn) { + mappings.push({ + line: util.getArg(mapping, 'generatedLine', null), + column: util.getArg(mapping, 'generatedColumn', null), + lastColumn: util.getArg(mapping, 'lastGeneratedColumn', null) + }); + + mapping = this._originalMappings[++index]; + } } } + + return mappings; }; -/** - * Add a chunk of generated JS to this source node. - * - * @param aChunk A string snippet of generated JS code, another instance of - * SourceNode, or an array where each member is one of those things. - */ -SourceNode.prototype.add = function SourceNode_add(aChunk) { - if (Array.isArray(aChunk)) { - aChunk.forEach(function (chunk) { - this.add(chunk); - }, this); - } - else if (aChunk[isSourceNode] || typeof aChunk === "string") { - if (aChunk) { - this.children.push(aChunk); - } - } - else { - throw new TypeError( - "Expected a SourceNode, string, or an array of SourceNodes and strings. Got " + aChunk - ); - } - return this; -}; +exports.SourceMapConsumer = SourceMapConsumer; /** - * Add a chunk of generated JS to the beginning of this source node. + * A BasicSourceMapConsumer instance represents a parsed source map which we can + * query for information about the original file positions by giving it a file + * position in the generated source. * - * @param aChunk A string snippet of generated JS code, another instance of - * SourceNode, or an array where each member is one of those things. + * The only parameter is the raw source map (either as a JSON string, or + * already parsed to an object). According to the spec, source maps have the + * following attributes: + * + * - version: Which version of the source map spec this map is following. + * - sources: An array of URLs to the original source files. + * - names: An array of identifiers which can be referrenced by individual mappings. + * - sourceRoot: Optional. The URL root from which all sources are relative. + * - sourcesContent: Optional. An array of contents of the original source files. + * - mappings: A string of base64 VLQs which contain the actual mappings. + * - file: Optional. The generated file this source map is associated with. + * + * Here is an example source map, taken from the source map spec[0]: + * + * { + * version : 3, + * file: "out.js", + * sourceRoot : "", + * sources: ["foo.js", "bar.js"], + * names: ["src", "maps", "are", "fun"], + * mappings: "AA,AB;;ABCDE;" + * } + * + * [0]: https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit?pli=1# */ -SourceNode.prototype.prepend = function SourceNode_prepend(aChunk) { - if (Array.isArray(aChunk)) { - for (var i = aChunk.length-1; i >= 0; i--) { - this.prepend(aChunk[i]); - } - } - else if (aChunk[isSourceNode] || typeof aChunk === "string") { - this.children.unshift(aChunk); +function BasicSourceMapConsumer(aSourceMap) { + var sourceMap = aSourceMap; + if (typeof aSourceMap === 'string') { + sourceMap = JSON.parse(aSourceMap.replace(/^\)\]\}'/, '')); } - else { - throw new TypeError( - "Expected a SourceNode, string, or an array of SourceNodes and strings. Got " + aChunk - ); + + var version = util.getArg(sourceMap, 'version'); + var sources = util.getArg(sourceMap, 'sources'); + // Sass 3.3 leaves out the 'names' array, so we deviate from the spec (which + // requires the array) to play nice here. + var names = util.getArg(sourceMap, 'names', []); + var sourceRoot = util.getArg(sourceMap, 'sourceRoot', null); + var sourcesContent = util.getArg(sourceMap, 'sourcesContent', null); + var mappings = util.getArg(sourceMap, 'mappings'); + var file = util.getArg(sourceMap, 'file', null); + + // Once again, Sass deviates from the spec and supplies the version as a + // string rather than a number, so we use loose equality checking here. + if (version != this._version) { + throw new Error('Unsupported version: ' + version); } - return this; -}; + + sources = sources + .map(String) + // Some source maps produce relative source paths like "./foo.js" instead of + // "foo.js". Normalize these first so that future comparisons will succeed. + // See bugzil.la/1090768. + .map(util.normalize) + // Always ensure that absolute sources are internally stored relative to + // the source root, if the source root is absolute. Not doing this would + // be particularly problematic when the source root is a prefix of the + // source (valid, but why??). See github issue #199 and bugzil.la/1188982. + .map(function (source) { + return sourceRoot && util.isAbsolute(sourceRoot) && util.isAbsolute(source) + ? util.relative(sourceRoot, source) + : source; + }); + + // Pass `true` below to allow duplicate names and sources. While source maps + // are intended to be compressed and deduplicated, the TypeScript compiler + // sometimes generates source maps with duplicates in them. See Github issue + // #72 and bugzil.la/889492. + this._names = ArraySet.fromArray(names.map(String), true); + this._sources = ArraySet.fromArray(sources, true); + + this.sourceRoot = sourceRoot; + this.sourcesContent = sourcesContent; + this._mappings = mappings; + this.file = file; +} + +BasicSourceMapConsumer.prototype = Object.create(SourceMapConsumer.prototype); +BasicSourceMapConsumer.prototype.consumer = SourceMapConsumer; /** - * Walk over the tree of JS snippets in this node and its children. The - * walking function is called once for each snippet of JS and is passed that - * snippet and the its original associated source's line/column location. + * Create a BasicSourceMapConsumer from a SourceMapGenerator. * - * @param aFn The traversal function. + * @param SourceMapGenerator aSourceMap + * The source map that will be consumed. + * @returns BasicSourceMapConsumer */ -SourceNode.prototype.walk = function SourceNode_walk(aFn) { - var chunk; - for (var i = 0, len = this.children.length; i < len; i++) { - chunk = this.children[i]; - if (chunk[isSourceNode]) { - chunk.walk(aFn); - } - else { - if (chunk !== '') { - aFn(chunk, { source: this.source, - line: this.line, - column: this.column, - name: this.name }); +BasicSourceMapConsumer.fromSourceMap = + function SourceMapConsumer_fromSourceMap(aSourceMap) { + var smc = Object.create(BasicSourceMapConsumer.prototype); + + var names = smc._names = ArraySet.fromArray(aSourceMap._names.toArray(), true); + var sources = smc._sources = ArraySet.fromArray(aSourceMap._sources.toArray(), true); + smc.sourceRoot = aSourceMap._sourceRoot; + smc.sourcesContent = aSourceMap._generateSourcesContent(smc._sources.toArray(), + smc.sourceRoot); + smc.file = aSourceMap._file; + + // Because we are modifying the entries (by converting string sources and + // names to indices into the sources and names ArraySets), we have to make + // a copy of the entry or else bad things happen. Shared mutable state + // strikes again! See github issue #191. + + var generatedMappings = aSourceMap._mappings.toArray().slice(); + var destGeneratedMappings = smc.__generatedMappings = []; + var destOriginalMappings = smc.__originalMappings = []; + + for (var i = 0, length = generatedMappings.length; i < length; i++) { + var srcMapping = generatedMappings[i]; + var destMapping = new Mapping; + destMapping.generatedLine = srcMapping.generatedLine; + destMapping.generatedColumn = srcMapping.generatedColumn; + + if (srcMapping.source) { + destMapping.source = sources.indexOf(srcMapping.source); + destMapping.originalLine = srcMapping.originalLine; + destMapping.originalColumn = srcMapping.originalColumn; + + if (srcMapping.name) { + destMapping.name = names.indexOf(srcMapping.name); + } + + destOriginalMappings.push(destMapping); } + + destGeneratedMappings.push(destMapping); } - } -}; + + quickSort(smc.__originalMappings, util.compareByOriginalPositions); + + return smc; + }; /** - * Like `String.prototype.join` except for SourceNodes. Inserts `aStr` between - * each of `this.children`. - * - * @param aSep The separator. + * The version of the source mapping spec that we are consuming. */ -SourceNode.prototype.join = function SourceNode_join(aSep) { - var newChildren; - var i; - var len = this.children.length; - if (len > 0) { - newChildren = []; - for (i = 0; i < len-1; i++) { - newChildren.push(this.children[i]); - newChildren.push(aSep); - } - newChildren.push(this.children[i]); - this.children = newChildren; - } - return this; -}; +BasicSourceMapConsumer.prototype._version = 3; /** - * Call String.prototype.replace on the very right-most source snippet. Useful - * for trimming whitespace from the end of a source node, etc. - * - * @param aPattern The pattern to replace. - * @param aReplacement The thing to replace the pattern with. + * The list of original sources. */ -SourceNode.prototype.replaceRight = function SourceNode_replaceRight(aPattern, aReplacement) { - var lastChild = this.children[this.children.length - 1]; - if (lastChild[isSourceNode]) { - lastChild.replaceRight(aPattern, aReplacement); - } - else if (typeof lastChild === 'string') { - this.children[this.children.length - 1] = lastChild.replace(aPattern, aReplacement); - } - else { - this.children.push(''.replace(aPattern, aReplacement)); +Object.defineProperty(BasicSourceMapConsumer.prototype, 'sources', { + get: function () { + return this._sources.toArray().map(function (s) { + return this.sourceRoot != null ? util.join(this.sourceRoot, s) : s; + }, this); } - return this; -}; +}); /** - * Set the source content for a source file. This will be added to the SourceMapGenerator - * in the sourcesContent field. - * - * @param aSourceFile The filename of the source file - * @param aSourceContent The content of the source file + * Provide the JIT with a nice shape / hidden class. */ -SourceNode.prototype.setSourceContent = - function SourceNode_setSourceContent(aSourceFile, aSourceContent) { - this.sourceContents[util.toSetString(aSourceFile)] = aSourceContent; - }; +function Mapping() { + this.generatedLine = 0; + this.generatedColumn = 0; + this.source = null; + this.originalLine = null; + this.originalColumn = null; + this.name = null; +} /** - * Walk over the tree of SourceNodes. The walking function is called for each - * source file content and is passed the filename and source content. - * - * @param aFn The traversal function. + * Parse the mappings in a string in to a data structure which we can easily + * query (the ordered arrays in the `this.__generatedMappings` and + * `this.__originalMappings` properties). */ -SourceNode.prototype.walkSourceContents = - function SourceNode_walkSourceContents(aFn) { - for (var i = 0, len = this.children.length; i < len; i++) { - if (this.children[i][isSourceNode]) { - this.children[i].walkSourceContents(aFn); +BasicSourceMapConsumer.prototype._parseMappings = + function SourceMapConsumer_parseMappings(aStr, aSourceRoot) { + var generatedLine = 1; + var previousGeneratedColumn = 0; + var previousOriginalLine = 0; + var previousOriginalColumn = 0; + var previousSource = 0; + var previousName = 0; + var length = aStr.length; + var index = 0; + var cachedSegments = {}; + var temp = {}; + var originalMappings = []; + var generatedMappings = []; + var mapping, str, segment, end, value; + + while (index < length) { + if (aStr.charAt(index) === ';') { + generatedLine++; + index++; + previousGeneratedColumn = 0; } - } + else if (aStr.charAt(index) === ',') { + index++; + } + else { + mapping = new Mapping(); + mapping.generatedLine = generatedLine; - var sources = Object.keys(this.sourceContents); - for (var i = 0, len = sources.length; i < len; i++) { - aFn(util.fromSetString(sources[i]), this.sourceContents[sources[i]]); + // Because each offset is encoded relative to the previous one, + // many segments often have the same encoding. We can exploit this + // fact by caching the parsed variable length fields of each segment, + // allowing us to avoid a second parse if we encounter the same + // segment again. + for (end = index; end < length; end++) { + if (this._charIsMappingSeparator(aStr, end)) { + break; + } + } + str = aStr.slice(index, end); + + segment = cachedSegments[str]; + if (segment) { + index += str.length; + } else { + segment = []; + while (index < end) { + base64VLQ.decode(aStr, index, temp); + value = temp.value; + index = temp.rest; + segment.push(value); + } + + if (segment.length === 2) { + throw new Error('Found a source, but no line and column'); + } + + if (segment.length === 3) { + throw new Error('Found a source and line, but no column'); + } + + cachedSegments[str] = segment; + } + + // Generated column. + mapping.generatedColumn = previousGeneratedColumn + segment[0]; + previousGeneratedColumn = mapping.generatedColumn; + + if (segment.length > 1) { + // Original source. + mapping.source = previousSource + segment[1]; + previousSource += segment[1]; + + // Original line. + mapping.originalLine = previousOriginalLine + segment[2]; + previousOriginalLine = mapping.originalLine; + // Lines are stored 0-based + mapping.originalLine += 1; + + // Original column. + mapping.originalColumn = previousOriginalColumn + segment[3]; + previousOriginalColumn = mapping.originalColumn; + + if (segment.length > 4) { + // Original name. + mapping.name = previousName + segment[4]; + previousName += segment[4]; + } + } + + generatedMappings.push(mapping); + if (typeof mapping.originalLine === 'number') { + originalMappings.push(mapping); + } + } } + + quickSort(generatedMappings, util.compareByGeneratedPositionsDeflated); + this.__generatedMappings = generatedMappings; + + quickSort(originalMappings, util.compareByOriginalPositions); + this.__originalMappings = originalMappings; }; /** - * Return the string representation of this source node. Walks over the tree - * and concatenates all the various snippets together to one string. + * Find the mapping that best matches the hypothetical "needle" mapping that + * we are searching for in the given "haystack" of mappings. */ -SourceNode.prototype.toString = function SourceNode_toString() { - var str = ""; - this.walk(function (chunk) { - str += chunk; - }); - return str; -}; +BasicSourceMapConsumer.prototype._findMapping = + function SourceMapConsumer_findMapping(aNeedle, aMappings, aLineName, + aColumnName, aComparator, aBias) { + // To return the position we are searching for, we must first find the + // mapping for the given position and then return the opposite position it + // points to. Because the mappings are sorted, we can use binary search to + // find the best mapping. + + if (aNeedle[aLineName] <= 0) { + throw new TypeError('Line must be greater than or equal to 1, got ' + + aNeedle[aLineName]); + } + if (aNeedle[aColumnName] < 0) { + throw new TypeError('Column must be greater than or equal to 0, got ' + + aNeedle[aColumnName]); + } + + return binarySearch.search(aNeedle, aMappings, aComparator, aBias); + }; /** - * Returns the string representation of this source node along with a source - * map. + * Compute the last column for each generated mapping. The last column is + * inclusive. */ -SourceNode.prototype.toStringWithSourceMap = function SourceNode_toStringWithSourceMap(aArgs) { - var generated = { - code: "", - line: 1, - column: 0 - }; - var map = new SourceMapGenerator(aArgs); - var sourceMappingActive = false; - var lastOriginalSource = null; - var lastOriginalLine = null; - var lastOriginalColumn = null; - var lastOriginalName = null; - this.walk(function (chunk, original) { - generated.code += chunk; - if (original.source !== null - && original.line !== null - && original.column !== null) { - if(lastOriginalSource !== original.source - || lastOriginalLine !== original.line - || lastOriginalColumn !== original.column - || lastOriginalName !== original.name) { - map.addMapping({ - source: original.source, - original: { - line: original.line, - column: original.column - }, - generated: { - line: generated.line, - column: generated.column - }, - name: original.name - }); - } - lastOriginalSource = original.source; - lastOriginalLine = original.line; - lastOriginalColumn = original.column; - lastOriginalName = original.name; - sourceMappingActive = true; - } else if (sourceMappingActive) { - map.addMapping({ - generated: { - line: generated.line, - column: generated.column - } - }); - lastOriginalSource = null; - sourceMappingActive = false; - } - for (var idx = 0, length = chunk.length; idx < length; idx++) { - if (chunk.charCodeAt(idx) === NEWLINE_CODE) { - generated.line++; - generated.column = 0; - // Mappings end at eol - if (idx + 1 === length) { - lastOriginalSource = null; - sourceMappingActive = false; - } else if (sourceMappingActive) { - map.addMapping({ - source: original.source, - original: { - line: original.line, - column: original.column - }, - generated: { - line: generated.line, - column: generated.column - }, - name: original.name - }); +BasicSourceMapConsumer.prototype.computeColumnSpans = + function SourceMapConsumer_computeColumnSpans() { + for (var index = 0; index < this._generatedMappings.length; ++index) { + var mapping = this._generatedMappings[index]; + + // Mappings do not contain a field for the last generated columnt. We + // can come up with an optimistic estimate, however, by assuming that + // mappings are contiguous (i.e. given two consecutive mappings, the + // first mapping ends where the second one starts). + if (index + 1 < this._generatedMappings.length) { + var nextMapping = this._generatedMappings[index + 1]; + + if (mapping.generatedLine === nextMapping.generatedLine) { + mapping.lastGeneratedColumn = nextMapping.generatedColumn - 1; + continue; } - } else { - generated.column++; } - } - }); - this.walkSourceContents(function (sourceFile, sourceContent) { - map.setSourceContent(sourceFile, sourceContent); - }); - return { code: generated.code, map: map }; -}; + // The last mapping for each line spans the entire line. + mapping.lastGeneratedColumn = Infinity; + } + }; -exports.SourceNode = SourceNode; +/** + * Returns the original source, line, and column information for the generated + * source's line and column positions provided. The only argument is an object + * with the following properties: + * + * - line: The line number in the generated source. + * - column: The column number in the generated source. + * - bias: Either 'SourceMapConsumer.GREATEST_LOWER_BOUND' or + * 'SourceMapConsumer.LEAST_UPPER_BOUND'. Specifies whether to return the + * closest element that is smaller than or greater than the one we are + * searching for, respectively, if the exact element cannot be found. + * Defaults to 'SourceMapConsumer.GREATEST_LOWER_BOUND'. + * + * and an object is returned with the following properties: + * + * - source: The original source file, or null. + * - line: The line number in the original source, or null. + * - column: The column number in the original source, or null. + * - name: The original identifier, or null. + */ +BasicSourceMapConsumer.prototype.originalPositionFor = + function SourceMapConsumer_originalPositionFor(aArgs) { + var needle = { + generatedLine: util.getArg(aArgs, 'line'), + generatedColumn: util.getArg(aArgs, 'column') + }; + var index = this._findMapping( + needle, + this._generatedMappings, + "generatedLine", + "generatedColumn", + util.compareByGeneratedPositionsDeflated, + util.getArg(aArgs, 'bias', SourceMapConsumer.GREATEST_LOWER_BOUND) + ); -/***/ }), -/* 624 */ -/***/ (function(module, exports, __webpack_require__) { + if (index >= 0) { + var mapping = this._generatedMappings[index]; -// Copyright 2014, 2015, 2016, 2017 Simon Lydell -// X11 (“MIT”) Licensed. (See LICENSE.) + if (mapping.generatedLine === needle.generatedLine) { + var source = util.getArg(mapping, 'source', null); + if (source !== null) { + source = this._sources.at(source); + if (this.sourceRoot != null) { + source = util.join(this.sourceRoot, source); + } + } + var name = util.getArg(mapping, 'name', null); + if (name !== null) { + name = this._names.at(name); + } + return { + source: source, + line: util.getArg(mapping, 'originalLine', null), + column: util.getArg(mapping, 'originalColumn', null), + name: name + }; + } + } -var sourceMappingURL = __webpack_require__(625) -var resolveUrl = __webpack_require__(626) -var decodeUriComponent = __webpack_require__(627) -var urix = __webpack_require__(629) -var atob = __webpack_require__(630) + return { + source: null, + line: null, + column: null, + name: null + }; + }; +/** + * Return true if we have the source content for every source in the source + * map, false otherwise. + */ +BasicSourceMapConsumer.prototype.hasContentsOfAllSources = + function BasicSourceMapConsumer_hasContentsOfAllSources() { + if (!this.sourcesContent) { + return false; + } + return this.sourcesContent.length >= this._sources.size() && + !this.sourcesContent.some(function (sc) { return sc == null; }); + }; +/** + * Returns the original source content. The only argument is the url of the + * original source file. Returns null if no original source content is + * available. + */ +BasicSourceMapConsumer.prototype.sourceContentFor = + function SourceMapConsumer_sourceContentFor(aSource, nullOnMissing) { + if (!this.sourcesContent) { + return null; + } -function callbackAsync(callback, error, result) { - setImmediate(function() { callback(error, result) }) -} + if (this.sourceRoot != null) { + aSource = util.relative(this.sourceRoot, aSource); + } -function parseMapToJSON(string, data) { - try { - return JSON.parse(string.replace(/^\)\]\}'/, "")) - } catch (error) { - error.sourceMapData = data - throw error - } -} + if (this._sources.has(aSource)) { + return this.sourcesContent[this._sources.indexOf(aSource)]; + } -function readSync(read, url, data) { - var readUrl = decodeUriComponent(url) - try { - return String(read(readUrl)) - } catch (error) { - error.sourceMapData = data - throw error - } -} + var url; + if (this.sourceRoot != null + && (url = util.urlParse(this.sourceRoot))) { + // XXX: file:// URIs and absolute paths lead to unexpected behavior for + // many users. We can help them out when they expect file:// URIs to + // behave like it would if they were running a local HTTP server. See + // https://bugzilla.mozilla.org/show_bug.cgi?id=885597. + var fileUriAbsPath = aSource.replace(/^file:\/\//, ""); + if (url.scheme == "file" + && this._sources.has(fileUriAbsPath)) { + return this.sourcesContent[this._sources.indexOf(fileUriAbsPath)] + } + if ((!url.path || url.path == "/") + && this._sources.has("/" + aSource)) { + return this.sourcesContent[this._sources.indexOf("/" + aSource)]; + } + } + // This function is used recursively from + // IndexedSourceMapConsumer.prototype.sourceContentFor. In that case, we + // don't want to throw if we can't find the source - we just want to + // return null, so we provide a flag to exit gracefully. + if (nullOnMissing) { + return null; + } + else { + throw new Error('"' + aSource + '" is not in the SourceMap.'); + } + }; -function resolveSourceMap(code, codeUrl, read, callback) { - var mapData - try { - mapData = resolveSourceMapHelper(code, codeUrl) - } catch (error) { - return callbackAsync(callback, error) - } - if (!mapData || mapData.map) { - return callbackAsync(callback, null, mapData) - } - var readUrl = decodeUriComponent(mapData.url) - read(readUrl, function(error, result) { - if (error) { - error.sourceMapData = mapData - return callback(error) +/** + * Returns the generated line and column information for the original source, + * line, and column positions provided. The only argument is an object with + * the following properties: + * + * - source: The filename of the original source. + * - line: The line number in the original source. + * - column: The column number in the original source. + * - bias: Either 'SourceMapConsumer.GREATEST_LOWER_BOUND' or + * 'SourceMapConsumer.LEAST_UPPER_BOUND'. Specifies whether to return the + * closest element that is smaller than or greater than the one we are + * searching for, respectively, if the exact element cannot be found. + * Defaults to 'SourceMapConsumer.GREATEST_LOWER_BOUND'. + * + * and an object is returned with the following properties: + * + * - line: The line number in the generated source, or null. + * - column: The column number in the generated source, or null. + */ +BasicSourceMapConsumer.prototype.generatedPositionFor = + function SourceMapConsumer_generatedPositionFor(aArgs) { + var source = util.getArg(aArgs, 'source'); + if (this.sourceRoot != null) { + source = util.relative(this.sourceRoot, source); } - mapData.map = String(result) - try { - mapData.map = parseMapToJSON(mapData.map, mapData) - } catch (error) { - return callback(error) + if (!this._sources.has(source)) { + return { + line: null, + column: null, + lastColumn: null + }; } - callback(null, mapData) - }) -} - -function resolveSourceMapSync(code, codeUrl, read) { - var mapData = resolveSourceMapHelper(code, codeUrl) - if (!mapData || mapData.map) { - return mapData - } - mapData.map = readSync(read, mapData.url, mapData) - mapData.map = parseMapToJSON(mapData.map, mapData) - return mapData -} + source = this._sources.indexOf(source); -var dataUriRegex = /^data:([^,;]*)(;[^,;]*)*(?:,(.*))?$/ -var jsonMimeTypeRegex = /^(?:application|text)\/json$/ + var needle = { + source: source, + originalLine: util.getArg(aArgs, 'line'), + originalColumn: util.getArg(aArgs, 'column') + }; -function resolveSourceMapHelper(code, codeUrl) { - codeUrl = urix(codeUrl) + var index = this._findMapping( + needle, + this._originalMappings, + "originalLine", + "originalColumn", + util.compareByOriginalPositions, + util.getArg(aArgs, 'bias', SourceMapConsumer.GREATEST_LOWER_BOUND) + ); - var url = sourceMappingURL.getFrom(code) - if (!url) { - return null - } + if (index >= 0) { + var mapping = this._originalMappings[index]; - var dataUri = url.match(dataUriRegex) - if (dataUri) { - var mimeType = dataUri[1] - var lastParameter = dataUri[2] || "" - var encoded = dataUri[3] || "" - var data = { - sourceMappingURL: url, - url: null, - sourcesRelativeTo: codeUrl, - map: encoded - } - if (!jsonMimeTypeRegex.test(mimeType)) { - var error = new Error("Unuseful data uri mime type: " + (mimeType || "text/plain")) - error.sourceMapData = data - throw error + if (mapping.source === needle.source) { + return { + line: util.getArg(mapping, 'generatedLine', null), + column: util.getArg(mapping, 'generatedColumn', null), + lastColumn: util.getArg(mapping, 'lastGeneratedColumn', null) + }; + } } - data.map = parseMapToJSON( - lastParameter === ";base64" ? atob(encoded) : decodeURIComponent(encoded), - data - ) - return data - } - - var mapUrl = resolveUrl(codeUrl, url) - return { - sourceMappingURL: url, - url: mapUrl, - sourcesRelativeTo: mapUrl, - map: null - } -} - + return { + line: null, + column: null, + lastColumn: null + }; + }; -function resolveSources(map, mapUrl, read, options, callback) { - if (typeof options === "function") { - callback = options - options = {} - } - var pending = map.sources ? map.sources.length : 0 - var result = { - sourcesResolved: [], - sourcesContent: [] - } - - if (pending === 0) { - callbackAsync(callback, null, result) - return - } +exports.BasicSourceMapConsumer = BasicSourceMapConsumer; - var done = function() { - pending-- - if (pending === 0) { - callback(null, result) - } +/** + * An IndexedSourceMapConsumer instance represents a parsed source map which + * we can query for information. It differs from BasicSourceMapConsumer in + * that it takes "indexed" source maps (i.e. ones with a "sections" field) as + * input. + * + * The only parameter is a raw source map (either as a JSON string, or already + * parsed to an object). According to the spec for indexed source maps, they + * have the following attributes: + * + * - version: Which version of the source map spec this map is following. + * - file: Optional. The generated file this source map is associated with. + * - sections: A list of section definitions. + * + * Each value under the "sections" field has two fields: + * - offset: The offset into the original specified at which this section + * begins to apply, defined as an object with a "line" and "column" + * field. + * - map: A source map definition. This source map could also be indexed, + * but doesn't have to be. + * + * Instead of the "map" field, it's also possible to have a "url" field + * specifying a URL to retrieve a source map from, but that's currently + * unsupported. + * + * Here's an example source map, taken from the source map spec[0], but + * modified to omit a section which uses the "url" field. + * + * { + * version : 3, + * file: "app.js", + * sections: [{ + * offset: {line:100, column:10}, + * map: { + * version : 3, + * file: "section.js", + * sources: ["foo.js", "bar.js"], + * names: ["src", "maps", "are", "fun"], + * mappings: "AAAA,E;;ABCDE;" + * } + * }], + * } + * + * [0]: https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit#heading=h.535es3xeprgt + */ +function IndexedSourceMapConsumer(aSourceMap) { + var sourceMap = aSourceMap; + if (typeof aSourceMap === 'string') { + sourceMap = JSON.parse(aSourceMap.replace(/^\)\]\}'/, '')); } - resolveSourcesHelper(map, mapUrl, options, function(fullUrl, sourceContent, index) { - result.sourcesResolved[index] = fullUrl - if (typeof sourceContent === "string") { - result.sourcesContent[index] = sourceContent - callbackAsync(done, null) - } else { - var readUrl = decodeUriComponent(fullUrl) - read(readUrl, function(error, source) { - result.sourcesContent[index] = error ? error : String(source) - done() - }) - } - }) -} + var version = util.getArg(sourceMap, 'version'); + var sections = util.getArg(sourceMap, 'sections'); -function resolveSourcesSync(map, mapUrl, read, options) { - var result = { - sourcesResolved: [], - sourcesContent: [] + if (version != this._version) { + throw new Error('Unsupported version: ' + version); } - if (!map.sources || map.sources.length === 0) { - return result - } + this._sources = new ArraySet(); + this._names = new ArraySet(); - resolveSourcesHelper(map, mapUrl, options, function(fullUrl, sourceContent, index) { - result.sourcesResolved[index] = fullUrl - if (read !== null) { - if (typeof sourceContent === "string") { - result.sourcesContent[index] = sourceContent - } else { - var readUrl = decodeUriComponent(fullUrl) - try { - result.sourcesContent[index] = String(read(readUrl)) - } catch (error) { - result.sourcesContent[index] = error - } - } + var lastOffset = { + line: -1, + column: 0 + }; + this._sections = sections.map(function (s) { + if (s.url) { + // The url field will require support for asynchronicity. + // See https://github.com/mozilla/source-map/issues/16 + throw new Error('Support for url field in sections not implemented.'); } - }) - - return result -} - -var endingSlash = /\/?$/ + var offset = util.getArg(s, 'offset'); + var offsetLine = util.getArg(offset, 'line'); + var offsetColumn = util.getArg(offset, 'column'); -function resolveSourcesHelper(map, mapUrl, options, fn) { - options = options || {} - mapUrl = urix(mapUrl) - var fullUrl - var sourceContent - var sourceRoot - for (var index = 0, len = map.sources.length; index < len; index++) { - sourceRoot = null - if (typeof options.sourceRoot === "string") { - sourceRoot = options.sourceRoot - } else if (typeof map.sourceRoot === "string" && options.sourceRoot !== false) { - sourceRoot = map.sourceRoot + if (offsetLine < lastOffset.line || + (offsetLine === lastOffset.line && offsetColumn < lastOffset.column)) { + throw new Error('Section offsets must be ordered and non-overlapping.'); } - // If the sourceRoot is the empty string, it is equivalent to not setting - // the property at all. - if (sourceRoot === null || sourceRoot === '') { - fullUrl = resolveUrl(mapUrl, map.sources[index]) - } else { - // Make sure that the sourceRoot ends with a slash, so that `/scripts/subdir` becomes - // `/scripts/subdir/`, not `/scripts/`. Pointing to a file as source root - // does not make sense. - fullUrl = resolveUrl(mapUrl, sourceRoot.replace(endingSlash, "/"), map.sources[index]) + lastOffset = offset; + + return { + generatedOffset: { + // The offset fields are 0-based, but we use 1-based indices when + // encoding/decoding from VLQ. + generatedLine: offsetLine + 1, + generatedColumn: offsetColumn + 1 + }, + consumer: new SourceMapConsumer(util.getArg(s, 'map')) } - sourceContent = (map.sourcesContent || [])[index] - fn(fullUrl, sourceContent, index) - } + }); } +IndexedSourceMapConsumer.prototype = Object.create(SourceMapConsumer.prototype); +IndexedSourceMapConsumer.prototype.constructor = SourceMapConsumer; +/** + * The version of the source mapping spec that we are consuming. + */ +IndexedSourceMapConsumer.prototype._version = 3; -function resolve(code, codeUrl, read, options, callback) { - if (typeof options === "function") { - callback = options - options = {} - } - if (code === null) { - var mapUrl = codeUrl - var data = { - sourceMappingURL: null, - url: mapUrl, - sourcesRelativeTo: mapUrl, - map: null - } - var readUrl = decodeUriComponent(mapUrl) - read(readUrl, function(error, result) { - if (error) { - error.sourceMapData = data - return callback(error) - } - data.map = String(result) - try { - data.map = parseMapToJSON(data.map, data) - } catch (error) { - return callback(error) - } - _resolveSources(data) - }) - } else { - resolveSourceMap(code, codeUrl, read, function(error, mapData) { - if (error) { - return callback(error) - } - if (!mapData) { - return callback(null, null) - } - _resolveSources(mapData) - }) - } - - function _resolveSources(mapData) { - resolveSources(mapData.map, mapData.sourcesRelativeTo, read, options, function(error, result) { - if (error) { - return callback(error) +/** + * The list of original sources. + */ +Object.defineProperty(IndexedSourceMapConsumer.prototype, 'sources', { + get: function () { + var sources = []; + for (var i = 0; i < this._sections.length; i++) { + for (var j = 0; j < this._sections[i].consumer.sources.length; j++) { + sources.push(this._sections[i].consumer.sources[j]); } - mapData.sourcesResolved = result.sourcesResolved - mapData.sourcesContent = result.sourcesContent - callback(null, mapData) - }) - } -} - -function resolveSync(code, codeUrl, read, options) { - var mapData - if (code === null) { - var mapUrl = codeUrl - mapData = { - sourceMappingURL: null, - url: mapUrl, - sourcesRelativeTo: mapUrl, - map: null - } - mapData.map = readSync(read, mapUrl, mapData) - mapData.map = parseMapToJSON(mapData.map, mapData) - } else { - mapData = resolveSourceMapSync(code, codeUrl, read) - if (!mapData) { - return null } + return sources; } - var result = resolveSourcesSync(mapData.map, mapData.sourcesRelativeTo, read, options) - mapData.sourcesResolved = result.sourcesResolved - mapData.sourcesContent = result.sourcesContent - return mapData -} +}); +/** + * Returns the original source, line, and column information for the generated + * source's line and column positions provided. The only argument is an object + * with the following properties: + * + * - line: The line number in the generated source. + * - column: The column number in the generated source. + * + * and an object is returned with the following properties: + * + * - source: The original source file, or null. + * - line: The line number in the original source, or null. + * - column: The column number in the original source, or null. + * - name: The original identifier, or null. + */ +IndexedSourceMapConsumer.prototype.originalPositionFor = + function IndexedSourceMapConsumer_originalPositionFor(aArgs) { + var needle = { + generatedLine: util.getArg(aArgs, 'line'), + generatedColumn: util.getArg(aArgs, 'column') + }; + // Find the section containing the generated position we're trying to map + // to an original position. + var sectionIndex = binarySearch.search(needle, this._sections, + function(needle, section) { + var cmp = needle.generatedLine - section.generatedOffset.generatedLine; + if (cmp) { + return cmp; + } -module.exports = { - resolveSourceMap: resolveSourceMap, - resolveSourceMapSync: resolveSourceMapSync, - resolveSources: resolveSources, - resolveSourcesSync: resolveSourcesSync, - resolve: resolve, - resolveSync: resolveSync, - parseMapToJSON: parseMapToJSON -} + return (needle.generatedColumn - + section.generatedOffset.generatedColumn); + }); + var section = this._sections[sectionIndex]; + if (!section) { + return { + source: null, + line: null, + column: null, + name: null + }; + } -/***/ }), -/* 625 */ -/***/ (function(module, exports, __webpack_require__) { + return section.consumer.originalPositionFor({ + line: needle.generatedLine - + (section.generatedOffset.generatedLine - 1), + column: needle.generatedColumn - + (section.generatedOffset.generatedLine === needle.generatedLine + ? section.generatedOffset.generatedColumn - 1 + : 0), + bias: aArgs.bias + }); + }; -var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_RESULT__;// Copyright 2014 Simon Lydell -// X11 (“MIT”) Licensed. (See LICENSE.) +/** + * Return true if we have the source content for every source in the source + * map, false otherwise. + */ +IndexedSourceMapConsumer.prototype.hasContentsOfAllSources = + function IndexedSourceMapConsumer_hasContentsOfAllSources() { + return this._sections.every(function (s) { + return s.consumer.hasContentsOfAllSources(); + }); + }; -void (function(root, factory) { - if (true) { - !(__WEBPACK_AMD_DEFINE_FACTORY__ = (factory), - __WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ? - (__WEBPACK_AMD_DEFINE_FACTORY__.call(exports, __webpack_require__, exports, module)) : - __WEBPACK_AMD_DEFINE_FACTORY__), - __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)) - } else {} -}(this, function() { +/** + * Returns the original source content. The only argument is the url of the + * original source file. Returns null if no original source content is + * available. + */ +IndexedSourceMapConsumer.prototype.sourceContentFor = + function IndexedSourceMapConsumer_sourceContentFor(aSource, nullOnMissing) { + for (var i = 0; i < this._sections.length; i++) { + var section = this._sections[i]; - var innerRegex = /[#@] sourceMappingURL=([^\s'"]*)/ + var content = section.consumer.sourceContentFor(aSource, true); + if (content) { + return content; + } + } + if (nullOnMissing) { + return null; + } + else { + throw new Error('"' + aSource + '" is not in the SourceMap.'); + } + }; - var regex = RegExp( - "(?:" + - "/\\*" + - "(?:\\s*\r?\n(?://)?)?" + - "(?:" + innerRegex.source + ")" + - "\\s*" + - "\\*/" + - "|" + - "//(?:" + innerRegex.source + ")" + - ")" + - "\\s*" - ) +/** + * Returns the generated line and column information for the original source, + * line, and column positions provided. The only argument is an object with + * the following properties: + * + * - source: The filename of the original source. + * - line: The line number in the original source. + * - column: The column number in the original source. + * + * and an object is returned with the following properties: + * + * - line: The line number in the generated source, or null. + * - column: The column number in the generated source, or null. + */ +IndexedSourceMapConsumer.prototype.generatedPositionFor = + function IndexedSourceMapConsumer_generatedPositionFor(aArgs) { + for (var i = 0; i < this._sections.length; i++) { + var section = this._sections[i]; - return { + // Only consider this section if the requested source is in the list of + // sources of the consumer. + if (section.consumer.sources.indexOf(util.getArg(aArgs, 'source')) === -1) { + continue; + } + var generatedPosition = section.consumer.generatedPositionFor(aArgs); + if (generatedPosition) { + var ret = { + line: generatedPosition.line + + (section.generatedOffset.generatedLine - 1), + column: generatedPosition.column + + (section.generatedOffset.generatedLine === generatedPosition.line + ? section.generatedOffset.generatedColumn - 1 + : 0) + }; + return ret; + } + } + + return { + line: null, + column: null + }; + }; - regex: regex, - _innerRegex: innerRegex, +/** + * Parse the mappings in a string in to a data structure which we can easily + * query (the ordered arrays in the `this.__generatedMappings` and + * `this.__originalMappings` properties). + */ +IndexedSourceMapConsumer.prototype._parseMappings = + function IndexedSourceMapConsumer_parseMappings(aStr, aSourceRoot) { + this.__generatedMappings = []; + this.__originalMappings = []; + for (var i = 0; i < this._sections.length; i++) { + var section = this._sections[i]; + var sectionMappings = section.consumer._generatedMappings; + for (var j = 0; j < sectionMappings.length; j++) { + var mapping = sectionMappings[j]; - getFrom: function(code) { - var match = code.match(regex) - return (match ? match[1] || match[2] || "" : null) - }, + var source = section.consumer._sources.at(mapping.source); + if (section.consumer.sourceRoot !== null) { + source = util.join(section.consumer.sourceRoot, source); + } + this._sources.add(source); + source = this._sources.indexOf(source); - existsIn: function(code) { - return regex.test(code) - }, + var name = section.consumer._names.at(mapping.name); + this._names.add(name); + name = this._names.indexOf(name); - removeFrom: function(code) { - return code.replace(regex, "") - }, + // The mappings coming from the consumer for the section have + // generated positions relative to the start of the section, so we + // need to offset them to be relative to the start of the concatenated + // generated file. + var adjustedMapping = { + source: source, + generatedLine: mapping.generatedLine + + (section.generatedOffset.generatedLine - 1), + generatedColumn: mapping.generatedColumn + + (section.generatedOffset.generatedLine === mapping.generatedLine + ? section.generatedOffset.generatedColumn - 1 + : 0), + originalLine: mapping.originalLine, + originalColumn: mapping.originalColumn, + name: name + }; - insertBefore: function(code, string) { - var match = code.match(regex) - if (match) { - return code.slice(0, match.index) + string + code.slice(match.index) - } else { - return code + string + this.__generatedMappings.push(adjustedMapping); + if (typeof adjustedMapping.originalLine === 'number') { + this.__originalMappings.push(adjustedMapping); + } } } - } - -})); - - -/***/ }), -/* 626 */ -/***/ (function(module, exports, __webpack_require__) { -// Copyright 2014 Simon Lydell -// X11 (“MIT”) Licensed. (See LICENSE.) + quickSort(this.__generatedMappings, util.compareByGeneratedPositionsDeflated); + quickSort(this.__originalMappings, util.compareByOriginalPositions); + }; -var url = __webpack_require__(196) +exports.IndexedSourceMapConsumer = IndexedSourceMapConsumer; -function resolveUrl(/* ...urls */) { - return Array.prototype.reduce.call(arguments, function(resolved, nextUrl) { - return url.resolve(resolved, nextUrl) - }) -} -module.exports = resolveUrl +/***/ }), +/* 624 */ +/***/ (function(module, exports) { +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ -/***/ }), -/* 627 */ -/***/ (function(module, exports, __webpack_require__) { +exports.GREATEST_LOWER_BOUND = 1; +exports.LEAST_UPPER_BOUND = 2; -// Copyright 2017 Simon Lydell -// X11 (“MIT”) Licensed. (See LICENSE.) +/** + * Recursive implementation of binary search. + * + * @param aLow Indices here and lower do not contain the needle. + * @param aHigh Indices here and higher do not contain the needle. + * @param aNeedle The element being searched for. + * @param aHaystack The non-empty array being searched. + * @param aCompare Function which takes two elements and returns -1, 0, or 1. + * @param aBias Either 'binarySearch.GREATEST_LOWER_BOUND' or + * 'binarySearch.LEAST_UPPER_BOUND'. Specifies whether to return the + * closest element that is smaller than or greater than the one we are + * searching for, respectively, if the exact element cannot be found. + */ +function recursiveSearch(aLow, aHigh, aNeedle, aHaystack, aCompare, aBias) { + // This function terminates when one of the following is true: + // + // 1. We find the exact element we are looking for. + // + // 2. We did not find the exact element, but we can return the index of + // the next-closest element. + // + // 3. We did not find the exact element, and there is no next-closest + // element than the one we are searching for, so we return -1. + var mid = Math.floor((aHigh - aLow) / 2) + aLow; + var cmp = aCompare(aNeedle, aHaystack[mid], true); + if (cmp === 0) { + // Found the element we are looking for. + return mid; + } + else if (cmp > 0) { + // Our needle is greater than aHaystack[mid]. + if (aHigh - mid > 1) { + // The element is in the upper half. + return recursiveSearch(mid, aHigh, aNeedle, aHaystack, aCompare, aBias); + } -var decodeUriComponent = __webpack_require__(628) + // The exact needle element was not found in this haystack. Determine if + // we are in termination case (3) or (2) and return the appropriate thing. + if (aBias == exports.LEAST_UPPER_BOUND) { + return aHigh < aHaystack.length ? aHigh : -1; + } else { + return mid; + } + } + else { + // Our needle is less than aHaystack[mid]. + if (mid - aLow > 1) { + // The element is in the lower half. + return recursiveSearch(aLow, mid, aNeedle, aHaystack, aCompare, aBias); + } -function customDecodeUriComponent(string) { - // `decodeUriComponent` turns `+` into ` `, but that's not wanted. - return decodeUriComponent(string.replace(/\+/g, "%2B")) + // we are in termination case (3) or (2) and return the appropriate thing. + if (aBias == exports.LEAST_UPPER_BOUND) { + return mid; + } else { + return aLow < 0 ? -1 : aLow; + } + } } -module.exports = customDecodeUriComponent - +/** + * This is an implementation of binary search which will always try and return + * the index of the closest element if there is no exact hit. This is because + * mappings between original and generated line/col pairs are single points, + * and there is an implicit region between each of them, so a miss just means + * that you aren't on the very start of a region. + * + * @param aNeedle The element you are looking for. + * @param aHaystack The array that is being searched. + * @param aCompare A function which takes the needle and an element in the + * array and returns -1, 0, or 1 depending on whether the needle is less + * than, equal to, or greater than the element, respectively. + * @param aBias Either 'binarySearch.GREATEST_LOWER_BOUND' or + * 'binarySearch.LEAST_UPPER_BOUND'. Specifies whether to return the + * closest element that is smaller than or greater than the one we are + * searching for, respectively, if the exact element cannot be found. + * Defaults to 'binarySearch.GREATEST_LOWER_BOUND'. + */ +exports.search = function search(aNeedle, aHaystack, aCompare, aBias) { + if (aHaystack.length === 0) { + return -1; + } -/***/ }), -/* 628 */ -/***/ (function(module, exports, __webpack_require__) { + var index = recursiveSearch(-1, aHaystack.length, aNeedle, aHaystack, + aCompare, aBias || exports.GREATEST_LOWER_BOUND); + if (index < 0) { + return -1; + } -"use strict"; + // We have found either the exact element, or the next-closest element than + // the one we are searching for. However, there may be more than one such + // element. Make sure we always return the smallest of these. + while (index - 1 >= 0) { + if (aCompare(aHaystack[index], aHaystack[index - 1], true) !== 0) { + break; + } + --index; + } -var token = '%[a-f0-9]{2}'; -var singleMatcher = new RegExp(token, 'gi'); -var multiMatcher = new RegExp('(' + token + ')+', 'gi'); + return index; +}; -function decodeComponents(components, split) { - try { - // Try to decode the entire string first - return decodeURIComponent(components.join('')); - } catch (err) { - // Do nothing - } - if (components.length === 1) { - return components; - } +/***/ }), +/* 625 */ +/***/ (function(module, exports) { - split = split || 1; +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ - // Split the array in 2 parts - var left = components.slice(0, split); - var right = components.slice(split); +// It turns out that some (most?) JavaScript engines don't self-host +// `Array.prototype.sort`. This makes sense because C++ will likely remain +// faster than JS when doing raw CPU-intensive sorting. However, when using a +// custom comparator function, calling back and forth between the VM's C++ and +// JIT'd JS is rather slow *and* loses JIT type information, resulting in +// worse generated code for the comparator function than would be optimal. In +// fact, when sorting with a comparator, these costs outweigh the benefits of +// sorting in C++. By using our own JS-implemented Quick Sort (below), we get +// a ~3500ms mean speed-up in `bench/bench.html`. - return Array.prototype.concat.call([], decodeComponents(left), decodeComponents(right)); +/** + * Swap the elements indexed by `x` and `y` in the array `ary`. + * + * @param {Array} ary + * The array. + * @param {Number} x + * The index of the first item. + * @param {Number} y + * The index of the second item. + */ +function swap(ary, x, y) { + var temp = ary[x]; + ary[x] = ary[y]; + ary[y] = temp; } -function decode(input) { - try { - return decodeURIComponent(input); - } catch (err) { - var tokens = input.match(singleMatcher); - - for (var i = 1; i < tokens.length; i++) { - input = decodeComponents(tokens, i).join(''); - - tokens = input.match(singleMatcher); - } - - return input; - } +/** + * Returns a random integer within the range `low .. high` inclusive. + * + * @param {Number} low + * The lower bound on the range. + * @param {Number} high + * The upper bound on the range. + */ +function randomIntInRange(low, high) { + return Math.round(low + (Math.random() * (high - low))); } -function customDecodeURIComponent(input) { - // Keep track of all the replacements and prefill the map with the `BOM` - var replaceMap = { - '%FE%FF': '\uFFFD\uFFFD', - '%FF%FE': '\uFFFD\uFFFD' - }; +/** + * The Quick Sort algorithm. + * + * @param {Array} ary + * An array to sort. + * @param {function} comparator + * Function to use to compare two items. + * @param {Number} p + * Start index of the array + * @param {Number} r + * End index of the array + */ +function doQuickSort(ary, comparator, p, r) { + // If our lower bound is less than our upper bound, we (1) partition the + // array into two pieces and (2) recurse on each half. If it is not, this is + // the empty array and our base case. - var match = multiMatcher.exec(input); - while (match) { - try { - // Decode as big chunks as possible - replaceMap[match[0]] = decodeURIComponent(match[0]); - } catch (err) { - var result = decode(match[0]); + if (p < r) { + // (1) Partitioning. + // + // The partitioning chooses a pivot between `p` and `r` and moves all + // elements that are less than or equal to the pivot to the before it, and + // all the elements that are greater than it after it. The effect is that + // once partition is done, the pivot is in the exact place it will be when + // the array is put in sorted order, and it will not need to be moved + // again. This runs in O(n) time. - if (result !== match[0]) { - replaceMap[match[0]] = result; - } - } + // Always choose a random pivot so that an input array which is reverse + // sorted does not cause O(n^2) running time. + var pivotIndex = randomIntInRange(p, r); + var i = p - 1; - match = multiMatcher.exec(input); - } + swap(ary, pivotIndex, r); + var pivot = ary[r]; - // Add `%C2` at the end of the map to make sure it does not replace the combinator before everything else - replaceMap['%C2'] = '\uFFFD'; + // Immediately after `j` is incremented in this loop, the following hold + // true: + // + // * Every element in `ary[p .. i]` is less than or equal to the pivot. + // + // * Every element in `ary[i+1 .. j-1]` is greater than the pivot. + for (var j = p; j < r; j++) { + if (comparator(ary[j], pivot) <= 0) { + i += 1; + swap(ary, i, j); + } + } - var entries = Object.keys(replaceMap); + swap(ary, i + 1, j); + var q = i + 1; - for (var i = 0; i < entries.length; i++) { - // Replace all decoded components - var key = entries[i]; - input = input.replace(new RegExp(key, 'g'), replaceMap[key]); - } + // (2) Recurse on each half. - return input; + doQuickSort(ary, comparator, p, q - 1); + doQuickSort(ary, comparator, q + 1, r); + } } -module.exports = function (encodedURI) { - if (typeof encodedURI !== 'string') { - throw new TypeError('Expected `encodedURI` to be of type `string`, got `' + typeof encodedURI + '`'); - } - - try { - encodedURI = encodedURI.replace(/\+/g, ' '); - - // Try the built in decoder first - return decodeURIComponent(encodedURI); - } catch (err) { - // Fallback to a more advanced decoder - return customDecodeURIComponent(encodedURI); - } +/** + * Sort the given array in-place with the given comparator function. + * + * @param {Array} ary + * An array to sort. + * @param {function} comparator + * Function to use to compare two items. + */ +exports.quickSort = function (ary, comparator) { + doQuickSort(ary, comparator, 0, ary.length - 1); }; /***/ }), -/* 629 */ +/* 626 */ /***/ (function(module, exports, __webpack_require__) { -// Copyright 2014 Simon Lydell -// X11 (“MIT”) Licensed. (See LICENSE.) - -var path = __webpack_require__(4) - -"use strict" - -function urix(aPath) { - if (path.sep === "\\") { - return aPath - .replace(/\\/g, "/") - .replace(/^[a-z]:\/?/i, "/") - } - return aPath -} - -module.exports = urix +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +var SourceMapGenerator = __webpack_require__(617).SourceMapGenerator; +var util = __webpack_require__(620); -/***/ }), -/* 630 */ -/***/ (function(module, exports, __webpack_require__) { +// Matches a Windows-style `\r\n` newline or a `\n` newline used by all other +// operating systems these days (capturing the result). +var REGEX_NEWLINE = /(\r?\n)/; -"use strict"; +// Newline character code for charCodeAt() comparisons +var NEWLINE_CODE = 10; +// Private symbol for identifying `SourceNode`s when multiple versions of +// the source-map library are loaded. This MUST NOT CHANGE across +// versions! +var isSourceNode = "$$$isSourceNode$$$"; -function atob(str) { - return Buffer.from(str, 'base64').toString('binary'); +/** + * SourceNodes provide a way to abstract over interpolating/concatenating + * snippets of generated JavaScript source code while maintaining the line and + * column information associated with the original source code. + * + * @param aLine The original line number. + * @param aColumn The original column number. + * @param aSource The original source's filename. + * @param aChunks Optional. An array of strings which are snippets of + * generated JS, or other SourceNodes. + * @param aName The original identifier. + */ +function SourceNode(aLine, aColumn, aSource, aChunks, aName) { + this.children = []; + this.sourceContents = {}; + this.line = aLine == null ? null : aLine; + this.column = aColumn == null ? null : aColumn; + this.source = aSource == null ? null : aSource; + this.name = aName == null ? null : aName; + this[isSourceNode] = true; + if (aChunks != null) this.add(aChunks); } -module.exports = atob.atob = atob; +/** + * Creates a SourceNode from generated code and a SourceMapConsumer. + * + * @param aGeneratedCode The generated code + * @param aSourceMapConsumer The SourceMap for the generated code + * @param aRelativePath Optional. The path that relative sources in the + * SourceMapConsumer should be relative to. + */ +SourceNode.fromStringWithSourceMap = + function SourceNode_fromStringWithSourceMap(aGeneratedCode, aSourceMapConsumer, aRelativePath) { + // The SourceNode we want to fill with the generated code + // and the SourceMap + var node = new SourceNode(); + + // All even indices of this array are one line of the generated code, + // while all odd indices are the newlines between two adjacent lines + // (since `REGEX_NEWLINE` captures its match). + // Processed fragments are accessed by calling `shiftNextLine`. + var remainingLines = aGeneratedCode.split(REGEX_NEWLINE); + var remainingLinesIndex = 0; + var shiftNextLine = function() { + var lineContents = getNextLine(); + // The last line of a file might not have a newline. + var newLine = getNextLine() || ""; + return lineContents + newLine; + function getNextLine() { + return remainingLinesIndex < remainingLines.length ? + remainingLines[remainingLinesIndex++] : undefined; + } + }; -/***/ }), -/* 631 */ -/***/ (function(module, exports, __webpack_require__) { + // We need to remember the position of "remainingLines" + var lastGeneratedLine = 1, lastGeneratedColumn = 0; -"use strict"; + // The generate SourceNodes we need a code range. + // To extract it current and last mapping is used. + // Here we store the last mapping. + var lastMapping = null; + aSourceMapConsumer.eachMapping(function (mapping) { + if (lastMapping !== null) { + // We add the code from "lastMapping" to "mapping": + // First check if there is a new line in between. + if (lastGeneratedLine < mapping.generatedLine) { + // Associate first line with "lastMapping" + addMappingWithCode(lastMapping, shiftNextLine()); + lastGeneratedLine++; + lastGeneratedColumn = 0; + // The remaining code is added without mapping + } else { + // There is no new line in between. + // Associate the code between "lastGeneratedColumn" and + // "mapping.generatedColumn" with "lastMapping" + var nextLine = remainingLines[remainingLinesIndex]; + var code = nextLine.substr(0, mapping.generatedColumn - + lastGeneratedColumn); + remainingLines[remainingLinesIndex] = nextLine.substr(mapping.generatedColumn - + lastGeneratedColumn); + lastGeneratedColumn = mapping.generatedColumn; + addMappingWithCode(lastMapping, code); + // No more remaining code, continue + lastMapping = mapping; + return; + } + } + // We add the generated code until the first mapping + // to the SourceNode without any mapping. + // Each line is added as separate string. + while (lastGeneratedLine < mapping.generatedLine) { + node.add(shiftNextLine()); + lastGeneratedLine++; + } + if (lastGeneratedColumn < mapping.generatedColumn) { + var nextLine = remainingLines[remainingLinesIndex]; + node.add(nextLine.substr(0, mapping.generatedColumn)); + remainingLines[remainingLinesIndex] = nextLine.substr(mapping.generatedColumn); + lastGeneratedColumn = mapping.generatedColumn; + } + lastMapping = mapping; + }, this); + // We have processed all mappings. + if (remainingLinesIndex < remainingLines.length) { + if (lastMapping) { + // Associate the remaining code in the current line with "lastMapping" + addMappingWithCode(lastMapping, shiftNextLine()); + } + // and add the remaining lines without any mapping + node.add(remainingLines.splice(remainingLinesIndex).join("")); + } -var fs = __webpack_require__(133); -var path = __webpack_require__(4); -var define = __webpack_require__(593); -var utils = __webpack_require__(612); + // Copy sourcesContent into SourceNode + aSourceMapConsumer.sources.forEach(function (sourceFile) { + var content = aSourceMapConsumer.sourceContentFor(sourceFile); + if (content != null) { + if (aRelativePath != null) { + sourceFile = util.join(aRelativePath, sourceFile); + } + node.setSourceContent(sourceFile, content); + } + }); -/** - * Expose `mixin()`. - * This code is based on `source-maps-support.js` in reworkcss/css - * https://github.com/reworkcss/css/blob/master/lib/stringify/source-map-support.js - * Copyright (c) 2012 TJ Holowaychuk - */ + return node; -module.exports = mixin; + function addMappingWithCode(mapping, code) { + if (mapping === null || mapping.source === undefined) { + node.add(code); + } else { + var source = aRelativePath + ? util.join(aRelativePath, mapping.source) + : mapping.source; + node.add(new SourceNode(mapping.originalLine, + mapping.originalColumn, + source, + code, + mapping.name)); + } + } + }; /** - * Mixin source map support into `compiler`. + * Add a chunk of generated JS to this source node. * - * @param {Object} `compiler` - * @api public + * @param aChunk A string snippet of generated JS code, another instance of + * SourceNode, or an array where each member is one of those things. */ - -function mixin(compiler) { - define(compiler, '_comment', compiler.comment); - compiler.map = new utils.SourceMap.SourceMapGenerator(); - compiler.position = { line: 1, column: 1 }; - compiler.content = {}; - compiler.files = {}; - - for (var key in exports) { - define(compiler, key, exports[key]); +SourceNode.prototype.add = function SourceNode_add(aChunk) { + if (Array.isArray(aChunk)) { + aChunk.forEach(function (chunk) { + this.add(chunk); + }, this); } -} + else if (aChunk[isSourceNode] || typeof aChunk === "string") { + if (aChunk) { + this.children.push(aChunk); + } + } + else { + throw new TypeError( + "Expected a SourceNode, string, or an array of SourceNodes and strings. Got " + aChunk + ); + } + return this; +}; /** - * Update position. + * Add a chunk of generated JS to the beginning of this source node. * - * @param {String} str + * @param aChunk A string snippet of generated JS code, another instance of + * SourceNode, or an array where each member is one of those things. */ - -exports.updatePosition = function(str) { - var lines = str.match(/\n/g); - if (lines) this.position.line += lines.length; - var i = str.lastIndexOf('\n'); - this.position.column = ~i ? str.length - i : this.position.column + str.length; +SourceNode.prototype.prepend = function SourceNode_prepend(aChunk) { + if (Array.isArray(aChunk)) { + for (var i = aChunk.length-1; i >= 0; i--) { + this.prepend(aChunk[i]); + } + } + else if (aChunk[isSourceNode] || typeof aChunk === "string") { + this.children.unshift(aChunk); + } + else { + throw new TypeError( + "Expected a SourceNode, string, or an array of SourceNodes and strings. Got " + aChunk + ); + } + return this; }; /** - * Emit `str` with `position`. + * Walk over the tree of JS snippets in this node and its children. The + * walking function is called once for each snippet of JS and is passed that + * snippet and the its original associated source's line/column location. * - * @param {String} str - * @param {Object} [pos] - * @return {String} + * @param aFn The traversal function. */ - -exports.emit = function(str, node) { - var position = node.position || {}; - var source = position.source; - if (source) { - if (position.filepath) { - source = utils.unixify(position.filepath); +SourceNode.prototype.walk = function SourceNode_walk(aFn) { + var chunk; + for (var i = 0, len = this.children.length; i < len; i++) { + chunk = this.children[i]; + if (chunk[isSourceNode]) { + chunk.walk(aFn); } - - this.map.addMapping({ - source: source, - generated: { - line: this.position.line, - column: Math.max(this.position.column - 1, 0) - }, - original: { - line: position.start.line, - column: position.start.column - 1 + else { + if (chunk !== '') { + aFn(chunk, { source: this.source, + line: this.line, + column: this.column, + name: this.name }); } - }); - - if (position.content) { - this.addContent(source, position); - } - if (position.filepath) { - this.addFile(source, position); } - - this.updatePosition(str); - this.output += str; } - return str; }; /** - * Adds a file to the source map output if it has not already been added - * @param {String} `file` - * @param {Object} `pos` + * Like `String.prototype.join` except for SourceNodes. Inserts `aStr` between + * each of `this.children`. + * + * @param aSep The separator. */ - -exports.addFile = function(file, position) { - if (typeof position.content !== 'string') return; - if (Object.prototype.hasOwnProperty.call(this.files, file)) return; - this.files[file] = position.content; +SourceNode.prototype.join = function SourceNode_join(aSep) { + var newChildren; + var i; + var len = this.children.length; + if (len > 0) { + newChildren = []; + for (i = 0; i < len-1; i++) { + newChildren.push(this.children[i]); + newChildren.push(aSep); + } + newChildren.push(this.children[i]); + this.children = newChildren; + } + return this; }; /** - * Adds a content source to the source map output if it has not already been added - * @param {String} `source` - * @param {Object} `position` + * Call String.prototype.replace on the very right-most source snippet. Useful + * for trimming whitespace from the end of a source node, etc. + * + * @param aPattern The pattern to replace. + * @param aReplacement The thing to replace the pattern with. */ - -exports.addContent = function(source, position) { - if (typeof position.content !== 'string') return; - if (Object.prototype.hasOwnProperty.call(this.content, source)) return; - this.map.setSourceContent(source, position.content); +SourceNode.prototype.replaceRight = function SourceNode_replaceRight(aPattern, aReplacement) { + var lastChild = this.children[this.children.length - 1]; + if (lastChild[isSourceNode]) { + lastChild.replaceRight(aPattern, aReplacement); + } + else if (typeof lastChild === 'string') { + this.children[this.children.length - 1] = lastChild.replace(aPattern, aReplacement); + } + else { + this.children.push(''.replace(aPattern, aReplacement)); + } + return this; }; /** - * Applies any original source maps to the output and embeds the source file - * contents in the source map. + * Set the source content for a source file. This will be added to the SourceMapGenerator + * in the sourcesContent field. + * + * @param aSourceFile The filename of the source file + * @param aSourceContent The content of the source file */ - -exports.applySourceMaps = function() { - Object.keys(this.files).forEach(function(file) { - var content = this.files[file]; - this.map.setSourceContent(file, content); - - if (this.options.inputSourcemaps === true) { - var originalMap = utils.sourceMapResolve.resolveSync(content, file, fs.readFileSync); - if (originalMap) { - var map = new utils.SourceMap.SourceMapConsumer(originalMap.map); - var relativeTo = originalMap.sourcesRelativeTo; - this.map.applySourceMap(map, file, utils.unixify(path.dirname(relativeTo))); - } - } - }, this); -}; +SourceNode.prototype.setSourceContent = + function SourceNode_setSourceContent(aSourceFile, aSourceContent) { + this.sourceContents[util.toSetString(aSourceFile)] = aSourceContent; + }; /** - * Process comments, drops sourceMap comments. - * @param {Object} node + * Walk over the tree of SourceNodes. The walking function is called for each + * source file content and is passed the filename and source content. + * + * @param aFn The traversal function. */ +SourceNode.prototype.walkSourceContents = + function SourceNode_walkSourceContents(aFn) { + for (var i = 0, len = this.children.length; i < len; i++) { + if (this.children[i][isSourceNode]) { + this.children[i].walkSourceContents(aFn); + } + } -exports.comment = function(node) { - if (/^# sourceMappingURL=/.test(node.comment)) { - return this.emit('', node.position); - } - return this._comment(node); -}; - - -/***/ }), -/* 632 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -var use = __webpack_require__(604); -var util = __webpack_require__(111); -var Cache = __webpack_require__(633); -var define = __webpack_require__(593); -var debug = __webpack_require__(606)('snapdragon:parser'); -var Position = __webpack_require__(634); -var utils = __webpack_require__(612); + var sources = Object.keys(this.sourceContents); + for (var i = 0, len = sources.length; i < len; i++) { + aFn(util.fromSetString(sources[i]), this.sourceContents[sources[i]]); + } + }; /** - * Create a new `Parser` with the given `input` and `options`. - * @param {String} `input` - * @param {Object} `options` - * @api public + * Return the string representation of this source node. Walks over the tree + * and concatenates all the various snippets together to one string. */ - -function Parser(options) { - debug('initializing', __filename); - this.options = utils.extend({source: 'string'}, options); - this.init(this.options); - use(this); -} +SourceNode.prototype.toString = function SourceNode_toString() { + var str = ""; + this.walk(function (chunk) { + str += chunk; + }); + return str; +}; /** - * Prototype methods + * Returns the string representation of this source node along with a source + * map. */ - -Parser.prototype = { - constructor: Parser, - - init: function(options) { - this.orig = ''; - this.input = ''; - this.parsed = ''; - - this.column = 1; - this.line = 1; - - this.regex = new Cache(); - this.errors = this.errors || []; - this.parsers = this.parsers || {}; - this.types = this.types || []; - this.sets = this.sets || {}; - this.fns = this.fns || []; - this.currentType = 'root'; - - var pos = this.position(); - this.bos = pos({type: 'bos', val: ''}); - - this.ast = { - type: 'root', - errors: this.errors, - nodes: [this.bos] - }; - - define(this.bos, 'parent', this.ast); - this.nodes = [this.ast]; - - this.count = 0; - this.setCount = 0; - this.stack = []; - }, - - /** - * Throw a formatted error with the cursor column and `msg`. - * @param {String} `msg` Message to use in the Error. - */ - - error: function(msg, node) { - var pos = node.position || {start: {column: 0, line: 0}}; - var line = pos.start.line; - var column = pos.start.column; - var source = this.options.source; - - var message = source + ' : ' + msg; - var err = new Error(message); - err.source = source; - err.reason = msg; - err.pos = pos; - - if (this.options.silent) { - this.errors.push(err); - } else { - throw err; +SourceNode.prototype.toStringWithSourceMap = function SourceNode_toStringWithSourceMap(aArgs) { + var generated = { + code: "", + line: 1, + column: 0 + }; + var map = new SourceMapGenerator(aArgs); + var sourceMappingActive = false; + var lastOriginalSource = null; + var lastOriginalLine = null; + var lastOriginalColumn = null; + var lastOriginalName = null; + this.walk(function (chunk, original) { + generated.code += chunk; + if (original.source !== null + && original.line !== null + && original.column !== null) { + if(lastOriginalSource !== original.source + || lastOriginalLine !== original.line + || lastOriginalColumn !== original.column + || lastOriginalName !== original.name) { + map.addMapping({ + source: original.source, + original: { + line: original.line, + column: original.column + }, + generated: { + line: generated.line, + column: generated.column + }, + name: original.name + }); + } + lastOriginalSource = original.source; + lastOriginalLine = original.line; + lastOriginalColumn = original.column; + lastOriginalName = original.name; + sourceMappingActive = true; + } else if (sourceMappingActive) { + map.addMapping({ + generated: { + line: generated.line, + column: generated.column + } + }); + lastOriginalSource = null; + sourceMappingActive = false; } - }, - - /** - * Define a non-enumberable property on the `Parser` instance. - * - * ```js - * parser.define('foo', 'bar'); - * ``` - * @name .define - * @param {String} `key` propery name - * @param {any} `val` property value - * @return {Object} Returns the Parser instance for chaining. - * @api public - */ - - define: function(key, val) { - define(this, key, val); - return this; - }, - - /** - * Mark position and patch `node.position`. - */ - - position: function() { - var start = { line: this.line, column: this.column }; - var self = this; - - return function(node) { - define(node, 'position', new Position(start, self)); - return node; - }; - }, - - /** - * Set parser `name` with the given `fn` - * @param {String} `name` - * @param {Function} `fn` - * @api public - */ - - set: function(type, fn) { - if (this.types.indexOf(type) === -1) { - this.types.push(type); + for (var idx = 0, length = chunk.length; idx < length; idx++) { + if (chunk.charCodeAt(idx) === NEWLINE_CODE) { + generated.line++; + generated.column = 0; + // Mappings end at eol + if (idx + 1 === length) { + lastOriginalSource = null; + sourceMappingActive = false; + } else if (sourceMappingActive) { + map.addMapping({ + source: original.source, + original: { + line: original.line, + column: original.column + }, + generated: { + line: generated.line, + column: generated.column + }, + name: original.name + }); + } + } else { + generated.column++; + } } - this.parsers[type] = fn.bind(this); - return this; - }, - - /** - * Get parser `name` - * @param {String} `name` - * @api public - */ - - get: function(name) { - return this.parsers[name]; - }, - - /** - * Push a `token` onto the `type` stack. - * - * @param {String} `type` - * @return {Object} `token` - * @api public - */ - - push: function(type, token) { - this.sets[type] = this.sets[type] || []; - this.count++; - this.stack.push(token); - return this.sets[type].push(token); - }, - - /** - * Pop a token off of the `type` stack - * @param {String} `type` - * @returns {Object} Returns a token - * @api public - */ - - pop: function(type) { - this.sets[type] = this.sets[type] || []; - this.count--; - this.stack.pop(); - return this.sets[type].pop(); - }, + }); + this.walkSourceContents(function (sourceFile, sourceContent) { + map.setSourceContent(sourceFile, sourceContent); + }); - /** - * Return true if inside a `stack` node. Types are `braces`, `parens` or `brackets`. - * - * @param {String} `type` - * @return {Boolean} - * @api public - */ + return { code: generated.code, map: map }; +}; - isInside: function(type) { - this.sets[type] = this.sets[type] || []; - return this.sets[type].length > 0; - }, +exports.SourceNode = SourceNode; - /** - * Return true if `node` is the given `type`. - * - * ```js - * parser.isType(node, 'brace'); - * ``` - * @param {Object} `node` - * @param {String} `type` - * @return {Boolean} - * @api public - */ - isType: function(node, type) { - return node && node.type === type; - }, +/***/ }), +/* 627 */ +/***/ (function(module, exports, __webpack_require__) { - /** - * Get the previous AST node - * @return {Object} - */ +// Copyright 2014, 2015, 2016, 2017 Simon Lydell +// X11 (“MIT”) Licensed. (See LICENSE.) - prev: function(n) { - return this.stack.length > 0 - ? utils.last(this.stack, n) - : utils.last(this.nodes, n); - }, +var sourceMappingURL = __webpack_require__(628) +var resolveUrl = __webpack_require__(629) +var decodeUriComponent = __webpack_require__(630) +var urix = __webpack_require__(632) +var atob = __webpack_require__(633) - /** - * Update line and column based on `str`. - */ - consume: function(len) { - this.input = this.input.substr(len); - }, - /** - * Update column based on `str`. - */ +function callbackAsync(callback, error, result) { + setImmediate(function() { callback(error, result) }) +} - updatePosition: function(str, len) { - var lines = str.match(/\n/g); - if (lines) this.line += lines.length; - var i = str.lastIndexOf('\n'); - this.column = ~i ? len - i : this.column + len; - this.parsed += str; - this.consume(len); - }, +function parseMapToJSON(string, data) { + try { + return JSON.parse(string.replace(/^\)\]\}'/, "")) + } catch (error) { + error.sourceMapData = data + throw error + } +} - /** - * Match `regex`, return captures, and update the cursor position by `match[0]` length. - * @param {RegExp} `regex` - * @return {Object} - */ +function readSync(read, url, data) { + var readUrl = decodeUriComponent(url) + try { + return String(read(readUrl)) + } catch (error) { + error.sourceMapData = data + throw error + } +} - match: function(regex) { - var m = regex.exec(this.input); - if (m) { - this.updatePosition(m[0], m[0].length); - return m; - } - }, - /** - * Capture `type` with the given regex. - * @param {String} `type` - * @param {RegExp} `regex` - * @return {Function} - */ - capture: function(type, regex) { - if (typeof regex === 'function') { - return this.set.apply(this, arguments); +function resolveSourceMap(code, codeUrl, read, callback) { + var mapData + try { + mapData = resolveSourceMapHelper(code, codeUrl) + } catch (error) { + return callbackAsync(callback, error) + } + if (!mapData || mapData.map) { + return callbackAsync(callback, null, mapData) + } + var readUrl = decodeUriComponent(mapData.url) + read(readUrl, function(error, result) { + if (error) { + error.sourceMapData = mapData + return callback(error) } + mapData.map = String(result) + try { + mapData.map = parseMapToJSON(mapData.map, mapData) + } catch (error) { + return callback(error) + } + callback(null, mapData) + }) +} - this.regex.set(type, regex); - this.set(type, function() { - var parsed = this.parsed; - var pos = this.position(); - var m = this.match(regex); - if (!m || !m[0]) return; - - var prev = this.prev(); - var node = pos({ - type: type, - val: m[0], - parsed: parsed, - rest: this.input - }); - - if (m[1]) { - node.inner = m[1]; - } - - define(node, 'inside', this.stack.length > 0); - define(node, 'parent', prev); - prev.nodes.push(node); - }.bind(this)); - return this; - }, +function resolveSourceMapSync(code, codeUrl, read) { + var mapData = resolveSourceMapHelper(code, codeUrl) + if (!mapData || mapData.map) { + return mapData + } + mapData.map = readSync(read, mapData.url, mapData) + mapData.map = parseMapToJSON(mapData.map, mapData) + return mapData +} - /** - * Create a parser with open and close for parens, - * brackets or braces - */ +var dataUriRegex = /^data:([^,;]*)(;[^,;]*)*(?:,(.*))?$/ +var jsonMimeTypeRegex = /^(?:application|text)\/json$/ - capturePair: function(type, openRegex, closeRegex, fn) { - this.sets[type] = this.sets[type] || []; +function resolveSourceMapHelper(code, codeUrl) { + codeUrl = urix(codeUrl) - /** - * Open - */ + var url = sourceMappingURL.getFrom(code) + if (!url) { + return null + } - this.set(type + '.open', function() { - var parsed = this.parsed; - var pos = this.position(); - var m = this.match(openRegex); - if (!m || !m[0]) return; + var dataUri = url.match(dataUriRegex) + if (dataUri) { + var mimeType = dataUri[1] + var lastParameter = dataUri[2] || "" + var encoded = dataUri[3] || "" + var data = { + sourceMappingURL: url, + url: null, + sourcesRelativeTo: codeUrl, + map: encoded + } + if (!jsonMimeTypeRegex.test(mimeType)) { + var error = new Error("Unuseful data uri mime type: " + (mimeType || "text/plain")) + error.sourceMapData = data + throw error + } + data.map = parseMapToJSON( + lastParameter === ";base64" ? atob(encoded) : decodeURIComponent(encoded), + data + ) + return data + } - var val = m[0]; - this.setCount++; - this.specialChars = true; - var open = pos({ - type: type + '.open', - val: val, - rest: this.input - }); + var mapUrl = resolveUrl(codeUrl, url) + return { + sourceMappingURL: url, + url: mapUrl, + sourcesRelativeTo: mapUrl, + map: null + } +} - if (typeof m[1] !== 'undefined') { - open.inner = m[1]; - } - var prev = this.prev(); - var node = pos({ - type: type, - nodes: [open] - }); - define(node, 'rest', this.input); - define(node, 'parsed', parsed); - define(node, 'prefix', m[1]); - define(node, 'parent', prev); - define(open, 'parent', node); +function resolveSources(map, mapUrl, read, options, callback) { + if (typeof options === "function") { + callback = options + options = {} + } + var pending = map.sources ? map.sources.length : 0 + var result = { + sourcesResolved: [], + sourcesContent: [] + } - if (typeof fn === 'function') { - fn.call(this, open, node); - } + if (pending === 0) { + callbackAsync(callback, null, result) + return + } - this.push(type, node); - prev.nodes.push(node); - }); + var done = function() { + pending-- + if (pending === 0) { + callback(null, result) + } + } - /** - * Close - */ + resolveSourcesHelper(map, mapUrl, options, function(fullUrl, sourceContent, index) { + result.sourcesResolved[index] = fullUrl + if (typeof sourceContent === "string") { + result.sourcesContent[index] = sourceContent + callbackAsync(done, null) + } else { + var readUrl = decodeUriComponent(fullUrl) + read(readUrl, function(error, source) { + result.sourcesContent[index] = error ? error : String(source) + done() + }) + } + }) +} - this.set(type + '.close', function() { - var pos = this.position(); - var m = this.match(closeRegex); - if (!m || !m[0]) return; +function resolveSourcesSync(map, mapUrl, read, options) { + var result = { + sourcesResolved: [], + sourcesContent: [] + } - var parent = this.pop(type); - var node = pos({ - type: type + '.close', - rest: this.input, - suffix: m[1], - val: m[0] - }); + if (!map.sources || map.sources.length === 0) { + return result + } - if (!this.isType(parent, type)) { - if (this.options.strict) { - throw new Error('missing opening "' + type + '"'); + resolveSourcesHelper(map, mapUrl, options, function(fullUrl, sourceContent, index) { + result.sourcesResolved[index] = fullUrl + if (read !== null) { + if (typeof sourceContent === "string") { + result.sourcesContent[index] = sourceContent + } else { + var readUrl = decodeUriComponent(fullUrl) + try { + result.sourcesContent[index] = String(read(readUrl)) + } catch (error) { + result.sourcesContent[index] = error } - - this.setCount--; - node.escaped = true; - return node; } + } + }) - if (node.suffix === '\\') { - parent.escaped = true; - node.escaped = true; - } + return result +} - parent.nodes.push(node); - define(node, 'parent', parent); - }); +var endingSlash = /\/?$/ - return this; - }, +function resolveSourcesHelper(map, mapUrl, options, fn) { + options = options || {} + mapUrl = urix(mapUrl) + var fullUrl + var sourceContent + var sourceRoot + for (var index = 0, len = map.sources.length; index < len; index++) { + sourceRoot = null + if (typeof options.sourceRoot === "string") { + sourceRoot = options.sourceRoot + } else if (typeof map.sourceRoot === "string" && options.sourceRoot !== false) { + sourceRoot = map.sourceRoot + } + // If the sourceRoot is the empty string, it is equivalent to not setting + // the property at all. + if (sourceRoot === null || sourceRoot === '') { + fullUrl = resolveUrl(mapUrl, map.sources[index]) + } else { + // Make sure that the sourceRoot ends with a slash, so that `/scripts/subdir` becomes + // `/scripts/subdir/`, not `/scripts/`. Pointing to a file as source root + // does not make sense. + fullUrl = resolveUrl(mapUrl, sourceRoot.replace(endingSlash, "/"), map.sources[index]) + } + sourceContent = (map.sourcesContent || [])[index] + fn(fullUrl, sourceContent, index) + } +} - /** - * Capture end-of-string - */ - eos: function() { - var pos = this.position(); - if (this.input) return; - var prev = this.prev(); - while (prev.type !== 'root' && !prev.visited) { - if (this.options.strict === true) { - throw new SyntaxError('invalid syntax:' + util.inspect(prev, null, 2)); +function resolve(code, codeUrl, read, options, callback) { + if (typeof options === "function") { + callback = options + options = {} + } + if (code === null) { + var mapUrl = codeUrl + var data = { + sourceMappingURL: null, + url: mapUrl, + sourcesRelativeTo: mapUrl, + map: null + } + var readUrl = decodeUriComponent(mapUrl) + read(readUrl, function(error, result) { + if (error) { + error.sourceMapData = data + return callback(error) } - - if (!hasDelims(prev)) { - prev.parent.escaped = true; - prev.escaped = true; + data.map = String(result) + try { + data.map = parseMapToJSON(data.map, data) + } catch (error) { + return callback(error) + } + _resolveSources(data) + }) + } else { + resolveSourceMap(code, codeUrl, read, function(error, mapData) { + if (error) { + return callback(error) + } + if (!mapData) { + return callback(null, null) } + _resolveSources(mapData) + }) + } - visit(prev, function(node) { - if (!hasDelims(node.parent)) { - node.parent.escaped = true; - node.escaped = true; - } - }); + function _resolveSources(mapData) { + resolveSources(mapData.map, mapData.sourcesRelativeTo, read, options, function(error, result) { + if (error) { + return callback(error) + } + mapData.sourcesResolved = result.sourcesResolved + mapData.sourcesContent = result.sourcesContent + callback(null, mapData) + }) + } +} - prev = prev.parent; +function resolveSync(code, codeUrl, read, options) { + var mapData + if (code === null) { + var mapUrl = codeUrl + mapData = { + sourceMappingURL: null, + url: mapUrl, + sourcesRelativeTo: mapUrl, + map: null } + mapData.map = readSync(read, mapUrl, mapData) + mapData.map = parseMapToJSON(mapData.map, mapData) + } else { + mapData = resolveSourceMapSync(code, codeUrl, read) + if (!mapData) { + return null + } + } + var result = resolveSourcesSync(mapData.map, mapData.sourcesRelativeTo, read, options) + mapData.sourcesResolved = result.sourcesResolved + mapData.sourcesContent = result.sourcesContent + return mapData +} - var tok = pos({ - type: 'eos', - val: this.append || '' - }); - define(tok, 'parent', this.ast); - return tok; - }, - /** - * Run parsers to advance the cursor position - */ +module.exports = { + resolveSourceMap: resolveSourceMap, + resolveSourceMapSync: resolveSourceMapSync, + resolveSources: resolveSources, + resolveSourcesSync: resolveSourcesSync, + resolve: resolve, + resolveSync: resolveSync, + parseMapToJSON: parseMapToJSON +} - next: function() { - var parsed = this.parsed; - var len = this.types.length; - var idx = -1; - var tok; - while (++idx < len) { - if ((tok = this.parsers[this.types[idx]].call(this))) { - define(tok, 'rest', this.input); - define(tok, 'parsed', parsed); - this.last = tok; - return tok; - } - } - }, +/***/ }), +/* 628 */ +/***/ (function(module, exports, __webpack_require__) { - /** - * Parse the given string. - * @return {Array} - */ +var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_RESULT__;// Copyright 2014 Simon Lydell +// X11 (“MIT”) Licensed. (See LICENSE.) + +void (function(root, factory) { + if (true) { + !(__WEBPACK_AMD_DEFINE_FACTORY__ = (factory), + __WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ? + (__WEBPACK_AMD_DEFINE_FACTORY__.call(exports, __webpack_require__, exports, module)) : + __WEBPACK_AMD_DEFINE_FACTORY__), + __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)) + } else {} +}(this, function() { + + var innerRegex = /[#@] sourceMappingURL=([^\s'"]*)/ + + var regex = RegExp( + "(?:" + + "/\\*" + + "(?:\\s*\r?\n(?://)?)?" + + "(?:" + innerRegex.source + ")" + + "\\s*" + + "\\*/" + + "|" + + "//(?:" + innerRegex.source + ")" + + ")" + + "\\s*" + ) - parse: function(input) { - if (typeof input !== 'string') { - throw new TypeError('expected a string'); - } + return { - this.init(this.options); - this.orig = input; - this.input = input; - var self = this; + regex: regex, + _innerRegex: innerRegex, - function parse() { - // check input before calling `.next()` - input = self.input; + getFrom: function(code) { + var match = code.match(regex) + return (match ? match[1] || match[2] || "" : null) + }, - // get the next AST ndoe - var node = self.next(); - if (node) { - var prev = self.prev(); - if (prev) { - define(node, 'parent', prev); - if (prev.nodes) { - prev.nodes.push(node); - } - } + existsIn: function(code) { + return regex.test(code) + }, - if (self.sets.hasOwnProperty(prev.type)) { - self.currentType = prev.type; - } - } + removeFrom: function(code) { + return code.replace(regex, "") + }, - // if we got here but input is not changed, throw an error - if (self.input && input === self.input) { - throw new Error('no parsers registered for: "' + self.input.slice(0, 5) + '"'); + insertBefore: function(code, string) { + var match = code.match(regex) + if (match) { + return code.slice(0, match.index) + string + code.slice(match.index) + } else { + return code + string } } + } - while (this.input) parse(); - if (this.stack.length && this.options.strict) { - var node = this.stack.pop(); - throw this.error('missing opening ' + node.type + ': "' + this.orig + '"'); - } +})); - var eos = this.eos(); - var tok = this.prev(); - if (tok.type !== 'eos') { - this.ast.nodes.push(eos); - } - return this.ast; - } -}; +/***/ }), +/* 629 */ +/***/ (function(module, exports, __webpack_require__) { -/** - * Visit `node` with the given `fn` - */ +// Copyright 2014 Simon Lydell +// X11 (“MIT”) Licensed. (See LICENSE.) -function visit(node, fn) { - if (!node.visited) { - define(node, 'visited', true); - return node.nodes ? mapVisit(node.nodes, fn) : fn(node); - } - return node; +var url = __webpack_require__(197) + +function resolveUrl(/* ...urls */) { + return Array.prototype.reduce.call(arguments, function(resolved, nextUrl) { + return url.resolve(resolved, nextUrl) + }) } -/** - * Map visit over array of `nodes`. - */ +module.exports = resolveUrl -function mapVisit(nodes, fn) { - var len = nodes.length; - var idx = -1; - while (++idx < len) { - visit(nodes[idx], fn); - } -} -function hasOpen(node) { - return node.nodes && node.nodes[0].type === (node.type + '.open'); -} +/***/ }), +/* 630 */ +/***/ (function(module, exports, __webpack_require__) { -function hasClose(node) { - return node.nodes && utils.last(node.nodes).type === (node.type + '.close'); -} +// Copyright 2017 Simon Lydell +// X11 (“MIT”) Licensed. (See LICENSE.) -function hasDelims(node) { - return hasOpen(node) && hasClose(node); -} +var decodeUriComponent = __webpack_require__(631) -/** - * Expose `Parser` - */ +function customDecodeUriComponent(string) { + // `decodeUriComponent` turns `+` into ` `, but that's not wanted. + return decodeUriComponent(string.replace(/\+/g, "%2B")) +} -module.exports = Parser; +module.exports = customDecodeUriComponent /***/ }), -/* 633 */ +/* 631 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -/*! - * map-cache - * - * Copyright (c) 2015, Jon Schlinkert. - * Licensed under the MIT License. - */ +var token = '%[a-f0-9]{2}'; +var singleMatcher = new RegExp(token, 'gi'); +var multiMatcher = new RegExp('(' + token + ')+', 'gi'); + +function decodeComponents(components, split) { + try { + // Try to decode the entire string first + return decodeURIComponent(components.join('')); + } catch (err) { + // Do nothing + } + + if (components.length === 1) { + return components; + } + split = split || 1; -var hasOwn = Object.prototype.hasOwnProperty; + // Split the array in 2 parts + var left = components.slice(0, split); + var right = components.slice(split); -/** - * Expose `MapCache` - */ + return Array.prototype.concat.call([], decodeComponents(left), decodeComponents(right)); +} -module.exports = MapCache; +function decode(input) { + try { + return decodeURIComponent(input); + } catch (err) { + var tokens = input.match(singleMatcher); -/** - * Creates a cache object to store key/value pairs. - * - * ```js - * var cache = new MapCache(); - * ``` - * - * @api public - */ + for (var i = 1; i < tokens.length; i++) { + input = decodeComponents(tokens, i).join(''); -function MapCache(data) { - this.__data__ = data || {}; + tokens = input.match(singleMatcher); + } + + return input; + } } -/** - * Adds `value` to `key` on the cache. - * - * ```js - * cache.set('foo', 'bar'); - * ``` - * - * @param {String} `key` The key of the value to cache. - * @param {*} `value` The value to cache. - * @returns {Object} Returns the `Cache` object for chaining. - * @api public - */ +function customDecodeURIComponent(input) { + // Keep track of all the replacements and prefill the map with the `BOM` + var replaceMap = { + '%FE%FF': '\uFFFD\uFFFD', + '%FF%FE': '\uFFFD\uFFFD' + }; -MapCache.prototype.set = function mapSet(key, value) { - if (key !== '__proto__') { - this.__data__[key] = value; - } - return this; -}; + var match = multiMatcher.exec(input); + while (match) { + try { + // Decode as big chunks as possible + replaceMap[match[0]] = decodeURIComponent(match[0]); + } catch (err) { + var result = decode(match[0]); -/** - * Gets the cached value for `key`. - * - * ```js - * cache.get('foo'); - * //=> 'bar' - * ``` - * - * @param {String} `key` The key of the value to get. - * @returns {*} Returns the cached value. - * @api public - */ + if (result !== match[0]) { + replaceMap[match[0]] = result; + } + } -MapCache.prototype.get = function mapGet(key) { - return key === '__proto__' ? undefined : this.__data__[key]; -}; + match = multiMatcher.exec(input); + } -/** - * Checks if a cached value for `key` exists. - * - * ```js - * cache.has('foo'); - * //=> true - * ``` - * - * @param {String} `key` The key of the entry to check. - * @returns {Boolean} Returns `true` if an entry for `key` exists, else `false`. - * @api public - */ + // Add `%C2` at the end of the map to make sure it does not replace the combinator before everything else + replaceMap['%C2'] = '\uFFFD'; -MapCache.prototype.has = function mapHas(key) { - return key !== '__proto__' && hasOwn.call(this.__data__, key); -}; + var entries = Object.keys(replaceMap); -/** - * Removes `key` and its value from the cache. - * - * ```js - * cache.del('foo'); - * ``` - * @title .del - * @param {String} `key` The key of the value to remove. - * @returns {Boolean} Returns `true` if the entry was removed successfully, else `false`. - * @api public - */ + for (var i = 0; i < entries.length; i++) { + // Replace all decoded components + var key = entries[i]; + input = input.replace(new RegExp(key, 'g'), replaceMap[key]); + } -MapCache.prototype.del = function mapDelete(key) { - return this.has(key) && delete this.__data__[key]; + return input; +} + +module.exports = function (encodedURI) { + if (typeof encodedURI !== 'string') { + throw new TypeError('Expected `encodedURI` to be of type `string`, got `' + typeof encodedURI + '`'); + } + + try { + encodedURI = encodedURI.replace(/\+/g, ' '); + + // Try the built in decoder first + return decodeURIComponent(encodedURI); + } catch (err) { + // Fallback to a more advanced decoder + return customDecodeURIComponent(encodedURI); + } }; /***/ }), -/* 634 */ +/* 632 */ /***/ (function(module, exports, __webpack_require__) { -"use strict"; +// Copyright 2014 Simon Lydell +// X11 (“MIT”) Licensed. (See LICENSE.) + +var path = __webpack_require__(4) + +"use strict" + +function urix(aPath) { + if (path.sep === "\\") { + return aPath + .replace(/\\/g, "/") + .replace(/^[a-z]:\/?/i, "/") + } + return aPath +} + +module.exports = urix -var define = __webpack_require__(593); +/***/ }), +/* 633 */ +/***/ (function(module, exports, __webpack_require__) { -/** - * Store position for a node - */ +"use strict"; -module.exports = function Position(start, parser) { - this.start = start; - this.end = { line: parser.line, column: parser.column }; - define(this, 'content', parser.orig); - define(this, 'source', parser.options.source); -}; + +function atob(str) { + return Buffer.from(str, 'base64').toString('binary'); +} + +module.exports = atob.atob = atob; /***/ }), -/* 635 */ +/* 634 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var safe = __webpack_require__(636); -var define = __webpack_require__(642); -var extend = __webpack_require__(643); -var not = __webpack_require__(645); -var MAX_LENGTH = 1024 * 64; +var fs = __webpack_require__(134); +var path = __webpack_require__(4); +var define = __webpack_require__(596); +var utils = __webpack_require__(615); /** - * Session cache + * Expose `mixin()`. + * This code is based on `source-maps-support.js` in reworkcss/css + * https://github.com/reworkcss/css/blob/master/lib/stringify/source-map-support.js + * Copyright (c) 2012 TJ Holowaychuk */ -var cache = {}; +module.exports = mixin; /** - * Create a regular expression from the given `pattern` string. + * Mixin source map support into `compiler`. * - * @param {String|RegExp} `pattern` Pattern can be a string or regular expression. - * @param {Object} `options` - * @return {RegExp} + * @param {Object} `compiler` * @api public */ -module.exports = function(patterns, options) { - if (!Array.isArray(patterns)) { - return makeRe(patterns, options); +function mixin(compiler) { + define(compiler, '_comment', compiler.comment); + compiler.map = new utils.SourceMap.SourceMapGenerator(); + compiler.position = { line: 1, column: 1 }; + compiler.content = {}; + compiler.files = {}; + + for (var key in exports) { + define(compiler, key, exports[key]); } - return makeRe(patterns.join('|'), options); -}; +} /** - * Create a regular expression from the given `pattern` string. + * Update position. * - * @param {String|RegExp} `pattern` Pattern can be a string or regular expression. - * @param {Object} `options` - * @return {RegExp} - * @api public + * @param {String} str */ -function makeRe(pattern, options) { - if (pattern instanceof RegExp) { - return pattern; - } - - if (typeof pattern !== 'string') { - throw new TypeError('expected a string'); - } - - if (pattern.length > MAX_LENGTH) { - throw new Error('expected pattern to be less than ' + MAX_LENGTH + ' characters'); - } - - var key = pattern; - // do this before shallow cloning options, it's a lot faster - if (!options || (options && options.cache !== false)) { - key = createKey(pattern, options); - - if (cache.hasOwnProperty(key)) { - return cache[key]; - } - } - - var opts = extend({}, options); - if (opts.contains === true) { - if (opts.negate === true) { - opts.strictNegate = false; - } else { - opts.strict = false; - } - } - - if (opts.strict === false) { - opts.strictOpen = false; - opts.strictClose = false; - } - - var open = opts.strictOpen !== false ? '^' : ''; - var close = opts.strictClose !== false ? '$' : ''; - var flags = opts.flags || ''; - var regex; +exports.updatePosition = function(str) { + var lines = str.match(/\n/g); + if (lines) this.position.line += lines.length; + var i = str.lastIndexOf('\n'); + this.position.column = ~i ? str.length - i : this.position.column + str.length; +}; - if (opts.nocase === true && !/i/.test(flags)) { - flags += 'i'; - } +/** + * Emit `str` with `position`. + * + * @param {String} str + * @param {Object} [pos] + * @return {String} + */ - try { - if (opts.negate || typeof opts.strictNegate === 'boolean') { - pattern = not.create(pattern, opts); +exports.emit = function(str, node) { + var position = node.position || {}; + var source = position.source; + if (source) { + if (position.filepath) { + source = utils.unixify(position.filepath); } - var str = open + '(?:' + pattern + ')' + close; - regex = new RegExp(str, flags); + this.map.addMapping({ + source: source, + generated: { + line: this.position.line, + column: Math.max(this.position.column - 1, 0) + }, + original: { + line: position.start.line, + column: position.start.column - 1 + } + }); - if (opts.safe === true && safe(regex) === false) { - throw new Error('potentially unsafe regular expression: ' + regex.source); + if (position.content) { + this.addContent(source, position); } - - } catch (err) { - if (opts.strictErrors === true || opts.safe === true) { - err.key = key; - err.pattern = pattern; - err.originalOptions = options; - err.createdOptions = opts; - throw err; + if (position.filepath) { + this.addFile(source, position); } - try { - regex = new RegExp('^' + pattern.replace(/(\W)/g, '\\$1') + '$'); - } catch (err) { - regex = /.^/; //<= match nothing - } + this.updatePosition(str); + this.output += str; } + return str; +}; - if (opts.cache !== false) { - memoize(regex, key, pattern, opts); - } - return regex; -} +/** + * Adds a file to the source map output if it has not already been added + * @param {String} `file` + * @param {Object} `pos` + */ + +exports.addFile = function(file, position) { + if (typeof position.content !== 'string') return; + if (Object.prototype.hasOwnProperty.call(this.files, file)) return; + this.files[file] = position.content; +}; /** - * Memoize generated regex. This can result in dramatic speed improvements - * and simplify debugging by adding options and pattern to the regex. It can be - * disabled by passing setting `options.cache` to false. + * Adds a content source to the source map output if it has not already been added + * @param {String} `source` + * @param {Object} `position` */ -function memoize(regex, key, pattern, options) { - define(regex, 'cached', true); - define(regex, 'pattern', pattern); - define(regex, 'options', options); - define(regex, 'key', key); - cache[key] = regex; -} +exports.addContent = function(source, position) { + if (typeof position.content !== 'string') return; + if (Object.prototype.hasOwnProperty.call(this.content, source)) return; + this.map.setSourceContent(source, position.content); +}; /** - * Create the key to use for memoization. The key is generated - * by iterating over the options and concatenating key-value pairs - * to the pattern string. + * Applies any original source maps to the output and embeds the source file + * contents in the source map. */ -function createKey(pattern, options) { - if (!options) return pattern; - var key = pattern; - for (var prop in options) { - if (options.hasOwnProperty(prop)) { - key += ';' + prop + '=' + String(options[prop]); +exports.applySourceMaps = function() { + Object.keys(this.files).forEach(function(file) { + var content = this.files[file]; + this.map.setSourceContent(file, content); + + if (this.options.inputSourcemaps === true) { + var originalMap = utils.sourceMapResolve.resolveSync(content, file, fs.readFileSync); + if (originalMap) { + var map = new utils.SourceMap.SourceMapConsumer(originalMap.map); + var relativeTo = originalMap.sourcesRelativeTo; + this.map.applySourceMap(map, file, utils.unixify(path.dirname(relativeTo))); + } } - } - return key; -} + }, this); +}; /** - * Expose `makeRe` + * Process comments, drops sourceMap comments. + * @param {Object} node */ -module.exports.makeRe = makeRe; +exports.comment = function(node) { + if (/^# sourceMappingURL=/.test(node.comment)) { + return this.emit('', node.position); + } + return this._comment(node); +}; /***/ }), -/* 636 */ +/* 635 */ /***/ (function(module, exports, __webpack_require__) { -var parse = __webpack_require__(637); -var types = parse.types; - -module.exports = function (re, opts) { - if (!opts) opts = {}; - var replimit = opts.limit === undefined ? 25 : opts.limit; - - if (isRegExp(re)) re = re.source; - else if (typeof re !== 'string') re = String(re); - - try { re = parse(re) } - catch (err) { return false } - - var reps = 0; - return (function walk (node, starHeight) { - if (node.type === types.REPETITION) { - starHeight ++; - reps ++; - if (starHeight > 1) return false; - if (reps > replimit) return false; - } - - if (node.options) { - for (var i = 0, len = node.options.length; i < len; i++) { - var ok = walk({ stack: node.options[i] }, starHeight); - if (!ok) return false; - } - } - var stack = node.stack || (node.value && node.value.stack); - if (!stack) return true; - - for (var i = 0; i < stack.length; i++) { - var ok = walk(stack[i], starHeight); - if (!ok) return false; - } - - return true; - })(re, 0); -}; - -function isRegExp (x) { - return {}.toString.call(x) === '[object RegExp]'; -} - +"use strict"; -/***/ }), -/* 637 */ -/***/ (function(module, exports, __webpack_require__) { -var util = __webpack_require__(638); -var types = __webpack_require__(639); -var sets = __webpack_require__(640); -var positions = __webpack_require__(641); +var use = __webpack_require__(607); +var util = __webpack_require__(112); +var Cache = __webpack_require__(636); +var define = __webpack_require__(596); +var debug = __webpack_require__(609)('snapdragon:parser'); +var Position = __webpack_require__(637); +var utils = __webpack_require__(615); +/** + * Create a new `Parser` with the given `input` and `options`. + * @param {String} `input` + * @param {Object} `options` + * @api public + */ -module.exports = function(regexpStr) { - var i = 0, l, c, - start = { type: types.ROOT, stack: []}, +function Parser(options) { + debug('initializing', __filename); + this.options = utils.extend({source: 'string'}, options); + this.init(this.options); + use(this); +} - // Keep track of last clause/group and stack. - lastGroup = start, - last = start.stack, - groupStack = []; +/** + * Prototype methods + */ +Parser.prototype = { + constructor: Parser, - var repeatErr = function(i) { - util.error(regexpStr, 'Nothing to repeat at column ' + (i - 1)); - }; + init: function(options) { + this.orig = ''; + this.input = ''; + this.parsed = ''; - // Decode a few escaped characters. - var str = util.strToChars(regexpStr); - l = str.length; + this.column = 1; + this.line = 1; - // Iterate through each character in string. - while (i < l) { - c = str[i++]; + this.regex = new Cache(); + this.errors = this.errors || []; + this.parsers = this.parsers || {}; + this.types = this.types || []; + this.sets = this.sets || {}; + this.fns = this.fns || []; + this.currentType = 'root'; - switch (c) { - // Handle escaped characters, inclues a few sets. - case '\\': - c = str[i++]; + var pos = this.position(); + this.bos = pos({type: 'bos', val: ''}); - switch (c) { - case 'b': - last.push(positions.wordBoundary()); - break; + this.ast = { + type: 'root', + errors: this.errors, + nodes: [this.bos] + }; - case 'B': - last.push(positions.nonWordBoundary()); - break; + define(this.bos, 'parent', this.ast); + this.nodes = [this.ast]; - case 'w': - last.push(sets.words()); - break; + this.count = 0; + this.setCount = 0; + this.stack = []; + }, - case 'W': - last.push(sets.notWords()); - break; + /** + * Throw a formatted error with the cursor column and `msg`. + * @param {String} `msg` Message to use in the Error. + */ - case 'd': - last.push(sets.ints()); - break; + error: function(msg, node) { + var pos = node.position || {start: {column: 0, line: 0}}; + var line = pos.start.line; + var column = pos.start.column; + var source = this.options.source; - case 'D': - last.push(sets.notInts()); - break; + var message = source + ' : ' + msg; + var err = new Error(message); + err.source = source; + err.reason = msg; + err.pos = pos; - case 's': - last.push(sets.whitespace()); - break; + if (this.options.silent) { + this.errors.push(err); + } else { + throw err; + } + }, - case 'S': - last.push(sets.notWhitespace()); - break; + /** + * Define a non-enumberable property on the `Parser` instance. + * + * ```js + * parser.define('foo', 'bar'); + * ``` + * @name .define + * @param {String} `key` propery name + * @param {any} `val` property value + * @return {Object} Returns the Parser instance for chaining. + * @api public + */ - default: - // Check if c is integer. - // In which case it's a reference. - if (/\d/.test(c)) { - last.push({ type: types.REFERENCE, value: parseInt(c, 10) }); + define: function(key, val) { + define(this, key, val); + return this; + }, - // Escaped character. - } else { - last.push({ type: types.CHAR, value: c.charCodeAt(0) }); - } - } + /** + * Mark position and patch `node.position`. + */ - break; + position: function() { + var start = { line: this.line, column: this.column }; + var self = this; + return function(node) { + define(node, 'position', new Position(start, self)); + return node; + }; + }, - // Positionals. - case '^': - last.push(positions.begin()); - break; + /** + * Set parser `name` with the given `fn` + * @param {String} `name` + * @param {Function} `fn` + * @api public + */ - case '$': - last.push(positions.end()); - break; + set: function(type, fn) { + if (this.types.indexOf(type) === -1) { + this.types.push(type); + } + this.parsers[type] = fn.bind(this); + return this; + }, + /** + * Get parser `name` + * @param {String} `name` + * @api public + */ - // Handle custom sets. - case '[': - // Check if this class is 'anti' i.e. [^abc]. - var not; - if (str[i] === '^') { - not = true; - i++; - } else { - not = false; - } + get: function(name) { + return this.parsers[name]; + }, - // Get all the characters in class. - var classTokens = util.tokenizeClass(str.slice(i), regexpStr); + /** + * Push a `token` onto the `type` stack. + * + * @param {String} `type` + * @return {Object} `token` + * @api public + */ - // Increase index by length of class. - i += classTokens[1]; - last.push({ - type: types.SET, - set: classTokens[0], - not: not, - }); + push: function(type, token) { + this.sets[type] = this.sets[type] || []; + this.count++; + this.stack.push(token); + return this.sets[type].push(token); + }, - break; + /** + * Pop a token off of the `type` stack + * @param {String} `type` + * @returns {Object} Returns a token + * @api public + */ + pop: function(type) { + this.sets[type] = this.sets[type] || []; + this.count--; + this.stack.pop(); + return this.sets[type].pop(); + }, - // Class of any character except \n. - case '.': - last.push(sets.anyChar()); - break; + /** + * Return true if inside a `stack` node. Types are `braces`, `parens` or `brackets`. + * + * @param {String} `type` + * @return {Boolean} + * @api public + */ + isInside: function(type) { + this.sets[type] = this.sets[type] || []; + return this.sets[type].length > 0; + }, - // Push group onto stack. - case '(': - // Create group. - var group = { - type: types.GROUP, - stack: [], - remember: true, - }; + /** + * Return true if `node` is the given `type`. + * + * ```js + * parser.isType(node, 'brace'); + * ``` + * @param {Object} `node` + * @param {String} `type` + * @return {Boolean} + * @api public + */ - c = str[i]; + isType: function(node, type) { + return node && node.type === type; + }, - // If if this is a special kind of group. - if (c === '?') { - c = str[i + 1]; - i += 2; + /** + * Get the previous AST node + * @return {Object} + */ - // Match if followed by. - if (c === '=') { - group.followedBy = true; + prev: function(n) { + return this.stack.length > 0 + ? utils.last(this.stack, n) + : utils.last(this.nodes, n); + }, - // Match if not followed by. - } else if (c === '!') { - group.notFollowedBy = true; + /** + * Update line and column based on `str`. + */ - } else if (c !== ':') { - util.error(regexpStr, - 'Invalid group, character \'' + c + - '\' after \'?\' at column ' + (i - 1)); - } + consume: function(len) { + this.input = this.input.substr(len); + }, - group.remember = false; - } + /** + * Update column based on `str`. + */ - // Insert subgroup into current group stack. - last.push(group); + updatePosition: function(str, len) { + var lines = str.match(/\n/g); + if (lines) this.line += lines.length; + var i = str.lastIndexOf('\n'); + this.column = ~i ? len - i : this.column + len; + this.parsed += str; + this.consume(len); + }, - // Remember the current group for when the group closes. - groupStack.push(lastGroup); + /** + * Match `regex`, return captures, and update the cursor position by `match[0]` length. + * @param {RegExp} `regex` + * @return {Object} + */ - // Make this new group the current group. - lastGroup = group; - last = group.stack; - break; + match: function(regex) { + var m = regex.exec(this.input); + if (m) { + this.updatePosition(m[0], m[0].length); + return m; + } + }, + /** + * Capture `type` with the given regex. + * @param {String} `type` + * @param {RegExp} `regex` + * @return {Function} + */ - // Pop group out of stack. - case ')': - if (groupStack.length === 0) { - util.error(regexpStr, 'Unmatched ) at column ' + (i - 1)); - } - lastGroup = groupStack.pop(); + capture: function(type, regex) { + if (typeof regex === 'function') { + return this.set.apply(this, arguments); + } - // Check if this group has a PIPE. - // To get back the correct last stack. - last = lastGroup.options ? - lastGroup.options[lastGroup.options.length - 1] : lastGroup.stack; - break; + this.regex.set(type, regex); + this.set(type, function() { + var parsed = this.parsed; + var pos = this.position(); + var m = this.match(regex); + if (!m || !m[0]) return; + var prev = this.prev(); + var node = pos({ + type: type, + val: m[0], + parsed: parsed, + rest: this.input + }); - // Use pipe character to give more choices. - case '|': - // Create array where options are if this is the first PIPE - // in this clause. - if (!lastGroup.options) { - lastGroup.options = [lastGroup.stack]; - delete lastGroup.stack; - } + if (m[1]) { + node.inner = m[1]; + } - // Create a new stack and add to options for rest of clause. - var stack = []; - lastGroup.options.push(stack); - last = stack; - break; + define(node, 'inside', this.stack.length > 0); + define(node, 'parent', prev); + prev.nodes.push(node); + }.bind(this)); + return this; + }, + /** + * Create a parser with open and close for parens, + * brackets or braces + */ - // Repetition. - // For every repetition, remove last element from last stack - // then insert back a RANGE object. - // This design is chosen because there could be more than - // one repetition symbols in a regex i.e. `a?+{2,3}`. - case '{': - var rs = /^(\d+)(,(\d+)?)?\}/.exec(str.slice(i)), min, max; - if (rs !== null) { - if (last.length === 0) { - repeatErr(i); - } - min = parseInt(rs[1], 10); - max = rs[2] ? rs[3] ? parseInt(rs[3], 10) : Infinity : min; - i += rs[0].length; + capturePair: function(type, openRegex, closeRegex, fn) { + this.sets[type] = this.sets[type] || []; - last.push({ - type: types.REPETITION, - min: min, - max: max, - value: last.pop(), - }); - } else { - last.push({ - type: types.CHAR, - value: 123, - }); - } - break; + /** + * Open + */ - case '?': - if (last.length === 0) { - repeatErr(i); - } - last.push({ - type: types.REPETITION, - min: 0, - max: 1, - value: last.pop(), - }); - break; + this.set(type + '.open', function() { + var parsed = this.parsed; + var pos = this.position(); + var m = this.match(openRegex); + if (!m || !m[0]) return; - case '+': - if (last.length === 0) { - repeatErr(i); - } - last.push({ - type: types.REPETITION, - min: 1, - max: Infinity, - value: last.pop(), - }); - break; + var val = m[0]; + this.setCount++; + this.specialChars = true; + var open = pos({ + type: type + '.open', + val: val, + rest: this.input + }); - case '*': - if (last.length === 0) { - repeatErr(i); - } - last.push({ - type: types.REPETITION, - min: 0, - max: Infinity, - value: last.pop(), - }); - break; + if (typeof m[1] !== 'undefined') { + open.inner = m[1]; + } + var prev = this.prev(); + var node = pos({ + type: type, + nodes: [open] + }); - // Default is a character that is not `\[](){}?+*^$`. - default: - last.push({ - type: types.CHAR, - value: c.charCodeAt(0), - }); - } + define(node, 'rest', this.input); + define(node, 'parsed', parsed); + define(node, 'prefix', m[1]); + define(node, 'parent', prev); + define(open, 'parent', node); - } + if (typeof fn === 'function') { + fn.call(this, open, node); + } - // Check if any groups have not been closed. - if (groupStack.length !== 0) { - util.error(regexpStr, 'Unterminated group'); - } + this.push(type, node); + prev.nodes.push(node); + }); - return start; -}; + /** + * Close + */ -module.exports.types = types; + this.set(type + '.close', function() { + var pos = this.position(); + var m = this.match(closeRegex); + if (!m || !m[0]) return; + var parent = this.pop(type); + var node = pos({ + type: type + '.close', + rest: this.input, + suffix: m[1], + val: m[0] + }); -/***/ }), -/* 638 */ -/***/ (function(module, exports, __webpack_require__) { + if (!this.isType(parent, type)) { + if (this.options.strict) { + throw new Error('missing opening "' + type + '"'); + } -var types = __webpack_require__(639); -var sets = __webpack_require__(640); + this.setCount--; + node.escaped = true; + return node; + } + if (node.suffix === '\\') { + parent.escaped = true; + node.escaped = true; + } -// All of these are private and only used by randexp. -// It's assumed that they will always be called with the correct input. + parent.nodes.push(node); + define(node, 'parent', parent); + }); -var CTRL = '@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^ ?'; -var SLSH = { '0': 0, 't': 9, 'n': 10, 'v': 11, 'f': 12, 'r': 13 }; + return this; + }, -/** - * Finds character representations in str and convert all to - * their respective characters - * - * @param {String} str - * @return {String} - */ -exports.strToChars = function(str) { - /* jshint maxlen: false */ - var chars_regex = /(\[\\b\])|(\\)?\\(?:u([A-F0-9]{4})|x([A-F0-9]{2})|(0?[0-7]{2})|c([@A-Z\[\\\]\^?])|([0tnvfr]))/g; - str = str.replace(chars_regex, function(s, b, lbs, a16, b16, c8, dctrl, eslsh) { - if (lbs) { - return s; - } + /** + * Capture end-of-string + */ - var code = b ? 8 : - a16 ? parseInt(a16, 16) : - b16 ? parseInt(b16, 16) : - c8 ? parseInt(c8, 8) : - dctrl ? CTRL.indexOf(dctrl) : - SLSH[eslsh]; + eos: function() { + var pos = this.position(); + if (this.input) return; + var prev = this.prev(); - var c = String.fromCharCode(code); + while (prev.type !== 'root' && !prev.visited) { + if (this.options.strict === true) { + throw new SyntaxError('invalid syntax:' + util.inspect(prev, null, 2)); + } - // Escape special regex characters. - if (/[\[\]{}\^$.|?*+()]/.test(c)) { - c = '\\' + c; + if (!hasDelims(prev)) { + prev.parent.escaped = true; + prev.escaped = true; + } + + visit(prev, function(node) { + if (!hasDelims(node.parent)) { + node.parent.escaped = true; + node.escaped = true; + } + }); + + prev = prev.parent; } - return c; - }); + var tok = pos({ + type: 'eos', + val: this.append || '' + }); - return str; -}; + define(tok, 'parent', this.ast); + return tok; + }, + /** + * Run parsers to advance the cursor position + */ -/** - * turns class into tokens - * reads str until it encounters a ] not preceeded by a \ - * - * @param {String} str - * @param {String} regexpStr - * @return {Array., Number>} - */ -exports.tokenizeClass = function(str, regexpStr) { - /* jshint maxlen: false */ - var tokens = []; - var regexp = /\\(?:(w)|(d)|(s)|(W)|(D)|(S))|((?:(?:\\)(.)|([^\]\\]))-(?:\\)?([^\]]))|(\])|(?:\\)?(.)/g; - var rs, c; + next: function() { + var parsed = this.parsed; + var len = this.types.length; + var idx = -1; + var tok; + while (++idx < len) { + if ((tok = this.parsers[this.types[idx]].call(this))) { + define(tok, 'rest', this.input); + define(tok, 'parsed', parsed); + this.last = tok; + return tok; + } + } + }, - while ((rs = regexp.exec(str)) != null) { - if (rs[1]) { - tokens.push(sets.words()); + /** + * Parse the given string. + * @return {Array} + */ - } else if (rs[2]) { - tokens.push(sets.ints()); + parse: function(input) { + if (typeof input !== 'string') { + throw new TypeError('expected a string'); + } - } else if (rs[3]) { - tokens.push(sets.whitespace()); + this.init(this.options); + this.orig = input; + this.input = input; + var self = this; - } else if (rs[4]) { - tokens.push(sets.notWords()); + function parse() { + // check input before calling `.next()` + input = self.input; - } else if (rs[5]) { - tokens.push(sets.notInts()); + // get the next AST ndoe + var node = self.next(); + if (node) { + var prev = self.prev(); + if (prev) { + define(node, 'parent', prev); + if (prev.nodes) { + prev.nodes.push(node); + } + } - } else if (rs[6]) { - tokens.push(sets.notWhitespace()); + if (self.sets.hasOwnProperty(prev.type)) { + self.currentType = prev.type; + } + } - } else if (rs[7]) { - tokens.push({ - type: types.RANGE, - from: (rs[8] || rs[9]).charCodeAt(0), - to: rs[10].charCodeAt(0), - }); + // if we got here but input is not changed, throw an error + if (self.input && input === self.input) { + throw new Error('no parsers registered for: "' + self.input.slice(0, 5) + '"'); + } + } - } else if (c = rs[12]) { - tokens.push({ - type: types.CHAR, - value: c.charCodeAt(0), - }); + while (this.input) parse(); + if (this.stack.length && this.options.strict) { + var node = this.stack.pop(); + throw this.error('missing opening ' + node.type + ': "' + this.orig + '"'); + } - } else { - return [tokens, regexp.lastIndex]; + var eos = this.eos(); + var tok = this.prev(); + if (tok.type !== 'eos') { + this.ast.nodes.push(eos); } - } - exports.error(regexpStr, 'Unterminated character class'); + return this.ast; + } }; +/** + * Visit `node` with the given `fn` + */ + +function visit(node, fn) { + if (!node.visited) { + define(node, 'visited', true); + return node.nodes ? mapVisit(node.nodes, fn) : fn(node); + } + return node; +} /** - * Shortcut to throw errors. - * - * @param {String} regexp - * @param {String} msg + * Map visit over array of `nodes`. */ -exports.error = function(regexp, msg) { - throw new SyntaxError('Invalid regular expression: /' + regexp + '/: ' + msg); -}; +function mapVisit(nodes, fn) { + var len = nodes.length; + var idx = -1; + while (++idx < len) { + visit(nodes[idx], fn); + } +} -/***/ }), -/* 639 */ -/***/ (function(module, exports) { +function hasOpen(node) { + return node.nodes && node.nodes[0].type === (node.type + '.open'); +} -module.exports = { - ROOT : 0, - GROUP : 1, - POSITION : 2, - SET : 3, - RANGE : 4, - REPETITION : 5, - REFERENCE : 6, - CHAR : 7, -}; +function hasClose(node) { + return node.nodes && utils.last(node.nodes).type === (node.type + '.close'); +} + +function hasDelims(node) { + return hasOpen(node) && hasClose(node); +} + +/** + * Expose `Parser` + */ + +module.exports = Parser; /***/ }), -/* 640 */ +/* 636 */ /***/ (function(module, exports, __webpack_require__) { -var types = __webpack_require__(639); +"use strict"; +/*! + * map-cache + * + * Copyright (c) 2015, Jon Schlinkert. + * Licensed under the MIT License. + */ -var INTS = function() { - return [{ type: types.RANGE , from: 48, to: 57 }]; -}; -var WORDS = function() { - return [ - { type: types.CHAR, value: 95 }, - { type: types.RANGE, from: 97, to: 122 }, - { type: types.RANGE, from: 65, to: 90 } - ].concat(INTS()); -}; -var WHITESPACE = function() { - return [ - { type: types.CHAR, value: 9 }, - { type: types.CHAR, value: 10 }, - { type: types.CHAR, value: 11 }, - { type: types.CHAR, value: 12 }, - { type: types.CHAR, value: 13 }, - { type: types.CHAR, value: 32 }, - { type: types.CHAR, value: 160 }, - { type: types.CHAR, value: 5760 }, - { type: types.CHAR, value: 6158 }, - { type: types.CHAR, value: 8192 }, - { type: types.CHAR, value: 8193 }, - { type: types.CHAR, value: 8194 }, - { type: types.CHAR, value: 8195 }, - { type: types.CHAR, value: 8196 }, - { type: types.CHAR, value: 8197 }, - { type: types.CHAR, value: 8198 }, - { type: types.CHAR, value: 8199 }, - { type: types.CHAR, value: 8200 }, - { type: types.CHAR, value: 8201 }, - { type: types.CHAR, value: 8202 }, - { type: types.CHAR, value: 8232 }, - { type: types.CHAR, value: 8233 }, - { type: types.CHAR, value: 8239 }, - { type: types.CHAR, value: 8287 }, - { type: types.CHAR, value: 12288 }, - { type: types.CHAR, value: 65279 } - ]; -}; +var hasOwn = Object.prototype.hasOwnProperty; -var NOTANYCHAR = function() { - return [ - { type: types.CHAR, value: 10 }, - { type: types.CHAR, value: 13 }, - { type: types.CHAR, value: 8232 }, - { type: types.CHAR, value: 8233 }, - ]; -}; +/** + * Expose `MapCache` + */ -// Predefined class objects. -exports.words = function() { - return { type: types.SET, set: WORDS(), not: false }; -}; +module.exports = MapCache; -exports.notWords = function() { - return { type: types.SET, set: WORDS(), not: true }; -}; +/** + * Creates a cache object to store key/value pairs. + * + * ```js + * var cache = new MapCache(); + * ``` + * + * @api public + */ -exports.ints = function() { - return { type: types.SET, set: INTS(), not: false }; -}; +function MapCache(data) { + this.__data__ = data || {}; +} -exports.notInts = function() { - return { type: types.SET, set: INTS(), not: true }; -}; +/** + * Adds `value` to `key` on the cache. + * + * ```js + * cache.set('foo', 'bar'); + * ``` + * + * @param {String} `key` The key of the value to cache. + * @param {*} `value` The value to cache. + * @returns {Object} Returns the `Cache` object for chaining. + * @api public + */ -exports.whitespace = function() { - return { type: types.SET, set: WHITESPACE(), not: false }; +MapCache.prototype.set = function mapSet(key, value) { + if (key !== '__proto__') { + this.__data__[key] = value; + } + return this; }; -exports.notWhitespace = function() { - return { type: types.SET, set: WHITESPACE(), not: true }; -}; +/** + * Gets the cached value for `key`. + * + * ```js + * cache.get('foo'); + * //=> 'bar' + * ``` + * + * @param {String} `key` The key of the value to get. + * @returns {*} Returns the cached value. + * @api public + */ -exports.anyChar = function() { - return { type: types.SET, set: NOTANYCHAR(), not: true }; +MapCache.prototype.get = function mapGet(key) { + return key === '__proto__' ? undefined : this.__data__[key]; }; +/** + * Checks if a cached value for `key` exists. + * + * ```js + * cache.has('foo'); + * //=> true + * ``` + * + * @param {String} `key` The key of the entry to check. + * @returns {Boolean} Returns `true` if an entry for `key` exists, else `false`. + * @api public + */ -/***/ }), -/* 641 */ -/***/ (function(module, exports, __webpack_require__) { - -var types = __webpack_require__(639); - -exports.wordBoundary = function() { - return { type: types.POSITION, value: 'b' }; -}; - -exports.nonWordBoundary = function() { - return { type: types.POSITION, value: 'B' }; +MapCache.prototype.has = function mapHas(key) { + return key !== '__proto__' && hasOwn.call(this.__data__, key); }; -exports.begin = function() { - return { type: types.POSITION, value: '^' }; -}; +/** + * Removes `key` and its value from the cache. + * + * ```js + * cache.del('foo'); + * ``` + * @title .del + * @param {String} `key` The key of the value to remove. + * @returns {Boolean} Returns `true` if the entry was removed successfully, else `false`. + * @api public + */ -exports.end = function() { - return { type: types.POSITION, value: '$' }; +MapCache.prototype.del = function mapDelete(key) { + return this.has(key) && delete this.__data__[key]; }; /***/ }), -/* 642 */ +/* 637 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -/*! - * define-property - * - * Copyright (c) 2015-2018, Jon Schlinkert. - * Released under the MIT License. - */ - - - -var isobject = __webpack_require__(544); -var isDescriptor = __webpack_require__(558); -var define = (typeof Reflect !== 'undefined' && Reflect.defineProperty) - ? Reflect.defineProperty - : Object.defineProperty; - -module.exports = function defineProperty(obj, key, val) { - if (!isobject(obj) && typeof obj !== 'function' && !Array.isArray(obj)) { - throw new TypeError('expected an object, function, or array'); - } - if (typeof key !== 'string') { - throw new TypeError('expected "key" to be a string'); - } - if (isDescriptor(val)) { - define(obj, key, val); - return obj; - } +var define = __webpack_require__(596); - define(obj, key, { - configurable: true, - enumerable: false, - writable: true, - value: val - }); +/** + * Store position for a node + */ - return obj; +module.exports = function Position(start, parser) { + this.start = start; + this.end = { line: parser.line, column: parser.column }; + define(this, 'content', parser.orig); + define(this, 'source', parser.options.source); }; /***/ }), -/* 643 */ +/* 638 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var isExtendable = __webpack_require__(644); -var assignSymbols = __webpack_require__(545); +var isExtendable = __webpack_require__(639); +var assignSymbols = __webpack_require__(544); module.exports = Object.assign || function(obj/*, objects*/) { if (obj === null || typeof obj === 'undefined') { @@ -75552,7 +75135,7 @@ function isEnum(obj, key) { /***/ }), -/* 644 */ +/* 639 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -75573,93 +75156,14 @@ module.exports = function isExtendable(val) { /***/ }), -/* 645 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -var extend = __webpack_require__(643); -var safe = __webpack_require__(636); - -/** - * The main export is a function that takes a `pattern` string and an `options` object. - * - * ```js - & var not = require('regex-not'); - & console.log(not('foo')); - & //=> /^(?:(?!^(?:foo)$).)*$/ - * ``` - * - * @param {String} `pattern` - * @param {Object} `options` - * @return {RegExp} Converts the given `pattern` to a regex using the specified `options`. - * @api public - */ - -function toRegex(pattern, options) { - return new RegExp(toRegex.create(pattern, options)); -} - -/** - * Create a regex-compatible string from the given `pattern` and `options`. - * - * ```js - & var not = require('regex-not'); - & console.log(not.create('foo')); - & //=> '^(?:(?!^(?:foo)$).)*$' - * ``` - * @param {String} `pattern` - * @param {Object} `options` - * @return {String} - * @api public - */ - -toRegex.create = function(pattern, options) { - if (typeof pattern !== 'string') { - throw new TypeError('expected a string'); - } - - var opts = extend({}, options); - if (opts.contains === true) { - opts.strictNegate = false; - } - - var open = opts.strictOpen !== false ? '^' : ''; - var close = opts.strictClose !== false ? '$' : ''; - var endChar = opts.endChar ? opts.endChar : '+'; - var str = pattern; - - if (opts.strictNegate === false) { - str = '(?:(?!(?:' + pattern + ')).)' + endChar; - } else { - str = '(?:(?!^(?:' + pattern + ')$).)' + endChar; - } - - var res = open + str + close; - if (opts.safe === true && safe(res) === false) { - throw new Error('potentially unsafe regular expression: ' + res); - } - - return res; -}; - -/** - * Expose `toRegex` - */ - -module.exports = toRegex; - - -/***/ }), -/* 646 */ +/* 640 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var nanomatch = __webpack_require__(647); -var extglob = __webpack_require__(663); +var nanomatch = __webpack_require__(641); +var extglob = __webpack_require__(656); module.exports = function(snapdragon) { var compilers = snapdragon.compiler.compilers; @@ -75736,7 +75240,7 @@ function escapeExtglobs(compiler) { /***/ }), -/* 647 */ +/* 641 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -75746,18 +75250,18 @@ function escapeExtglobs(compiler) { * Module dependencies */ -var util = __webpack_require__(111); -var toRegex = __webpack_require__(648); -var extend = __webpack_require__(649); +var util = __webpack_require__(112); +var toRegex = __webpack_require__(526); +var extend = __webpack_require__(642); /** * Local dependencies */ -var compilers = __webpack_require__(651); -var parsers = __webpack_require__(652); -var cache = __webpack_require__(655); -var utils = __webpack_require__(657); +var compilers = __webpack_require__(644); +var parsers = __webpack_require__(645); +var cache = __webpack_require__(648); +var utils = __webpack_require__(650); var MAX_LENGTH = 1024 * 64; /** @@ -76581,169 +76085,14 @@ module.exports = nanomatch; /***/ }), -/* 648 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -var define = __webpack_require__(593); -var extend = __webpack_require__(535); -var not = __webpack_require__(534); -var MAX_LENGTH = 1024 * 64; - -/** - * Session cache - */ - -var cache = {}; - -/** - * Create a regular expression from the given `pattern` string. - * - * @param {String|RegExp} `pattern` Pattern can be a string or regular expression. - * @param {Object} `options` - * @return {RegExp} - * @api public - */ - -module.exports = function(patterns, options) { - if (!Array.isArray(patterns)) { - return makeRe(patterns, options); - } - return makeRe(patterns.join('|'), options); -}; - -/** - * Create a regular expression from the given `pattern` string. - * - * @param {String|RegExp} `pattern` Pattern can be a string or regular expression. - * @param {Object} `options` - * @return {RegExp} - * @api public - */ - -function makeRe(pattern, options) { - if (pattern instanceof RegExp) { - return pattern; - } - - if (typeof pattern !== 'string') { - throw new TypeError('expected a string'); - } - - if (pattern.length > MAX_LENGTH) { - throw new Error('expected pattern to be less than ' + MAX_LENGTH + ' characters'); - } - - var key = pattern; - // do this before shallow cloning options, it's a lot faster - if (!options || (options && options.cache !== false)) { - key = createKey(pattern, options); - - if (cache.hasOwnProperty(key)) { - return cache[key]; - } - } - - var opts = extend({}, options); - if (opts.contains === true) { - if (opts.negate === true) { - opts.strictNegate = false; - } else { - opts.strict = false; - } - } - - if (opts.strict === false) { - opts.strictOpen = false; - opts.strictClose = false; - } - - var open = opts.strictOpen !== false ? '^' : ''; - var close = opts.strictClose !== false ? '$' : ''; - var flags = opts.flags || ''; - var regex; - - if (opts.nocase === true && !/i/.test(flags)) { - flags += 'i'; - } - - try { - if (opts.negate || typeof opts.strictNegate === 'boolean') { - pattern = not.create(pattern, opts); - } - var str = open + '(?:' + pattern + ')' + close; - regex = new RegExp(str, flags); - } catch (err) { - if (opts.strictErrors === true) { - err.key = key; - err.pattern = pattern; - err.originalOptions = options; - err.createdOptions = opts; - throw err; - } - - try { - regex = new RegExp('^' + pattern.replace(/(\W)/g, '\\$1') + '$'); - } catch (err) { - regex = /.^/; //<= match nothing - } - } - - if (opts.cache !== false) { - cacheRegex(regex, key, pattern, opts); - } - return regex; -} - -/** - * Cache generated regex. This can result in dramatic speed improvements - * and simplify debugging by adding options and pattern to the regex. It can be - * disabled by passing setting `options.cache` to false. - */ - -function cacheRegex(regex, key, pattern, options) { - define(regex, 'cached', true); - define(regex, 'pattern', pattern); - define(regex, 'options', options); - define(regex, 'key', key); - cache[key] = regex; -} - -/** - * Create the key to use for memoization. The key is generated - * by iterating over the options and concatenating key-value pairs - * to the pattern string. - */ - -function createKey(pattern, options) { - if (!options) return pattern; - var key = pattern; - for (var prop in options) { - if (options.hasOwnProperty(prop)) { - key += ';' + prop + '=' + String(options[prop]); - } - } - return key; -} - -/** - * Expose `makeRe` - */ - -module.exports.makeRe = makeRe; - - -/***/ }), -/* 649 */ +/* 642 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var isExtendable = __webpack_require__(650); -var assignSymbols = __webpack_require__(545); +var isExtendable = __webpack_require__(643); +var assignSymbols = __webpack_require__(544); module.exports = Object.assign || function(obj/*, objects*/) { if (obj === null || typeof obj === 'undefined') { @@ -76803,7 +76152,7 @@ function isEnum(obj, key) { /***/ }), -/* 650 */ +/* 643 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -76824,7 +76173,7 @@ module.exports = function isExtendable(val) { /***/ }), -/* 651 */ +/* 644 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -77170,15 +76519,15 @@ module.exports = function(nanomatch, options) { /***/ }), -/* 652 */ +/* 645 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var regexNot = __webpack_require__(534); -var toRegex = __webpack_require__(648); -var isOdd = __webpack_require__(653); +var regexNot = __webpack_require__(545); +var toRegex = __webpack_require__(526); +var isOdd = __webpack_require__(646); /** * Characters to use in negation regex (we want to "not" match @@ -77564,7 +76913,7 @@ module.exports.not = NOT_REGEX; /***/ }), -/* 653 */ +/* 646 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -77577,7 +76926,7 @@ module.exports.not = NOT_REGEX; -var isNumber = __webpack_require__(654); +var isNumber = __webpack_require__(647); module.exports = function isOdd(i) { if (!isNumber(i)) { @@ -77591,7 +76940,7 @@ module.exports = function isOdd(i) { /***/ }), -/* 654 */ +/* 647 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -77619,14 +76968,14 @@ module.exports = function isNumber(num) { /***/ }), -/* 655 */ +/* 648 */ /***/ (function(module, exports, __webpack_require__) { -module.exports = new (__webpack_require__(656))(); +module.exports = new (__webpack_require__(649))(); /***/ }), -/* 656 */ +/* 649 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -77639,7 +76988,7 @@ module.exports = new (__webpack_require__(656))(); -var MapCache = __webpack_require__(633); +var MapCache = __webpack_require__(636); /** * Create a new `FragmentCache` with an optional object to use for `caches`. @@ -77761,7 +77110,7 @@ exports = module.exports = FragmentCache; /***/ }), -/* 657 */ +/* 650 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -77774,14 +77123,14 @@ var path = __webpack_require__(4); * Module dependencies */ -var isWindows = __webpack_require__(658)(); -var Snapdragon = __webpack_require__(566); -utils.define = __webpack_require__(659); -utils.diff = __webpack_require__(660); -utils.extend = __webpack_require__(649); -utils.pick = __webpack_require__(661); -utils.typeOf = __webpack_require__(662); -utils.unique = __webpack_require__(537); +var isWindows = __webpack_require__(651)(); +var Snapdragon = __webpack_require__(569); +utils.define = __webpack_require__(652); +utils.diff = __webpack_require__(653); +utils.extend = __webpack_require__(642); +utils.pick = __webpack_require__(654); +utils.typeOf = __webpack_require__(655); +utils.unique = __webpack_require__(548); /** * Returns true if the given value is effectively an empty string @@ -78147,7 +77496,7 @@ utils.unixify = function(options) { /***/ }), -/* 658 */ +/* 651 */ /***/ (function(module, exports, __webpack_require__) { var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*! @@ -78175,7 +77524,7 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_ /***/ }), -/* 659 */ +/* 652 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -78188,8 +77537,8 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_ -var isobject = __webpack_require__(544); -var isDescriptor = __webpack_require__(558); +var isobject = __webpack_require__(534); +var isDescriptor = __webpack_require__(535); var define = (typeof Reflect !== 'undefined' && Reflect.defineProperty) ? Reflect.defineProperty : Object.defineProperty; @@ -78220,7 +77569,7 @@ module.exports = function defineProperty(obj, key, val) { /***/ }), -/* 660 */ +/* 653 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -78274,7 +77623,7 @@ function diffArray(one, two) { /***/ }), -/* 661 */ +/* 654 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -78287,7 +77636,7 @@ function diffArray(one, two) { -var isObject = __webpack_require__(544); +var isObject = __webpack_require__(534); module.exports = function pick(obj, keys) { if (!isObject(obj) && typeof obj !== 'function') { @@ -78316,7 +77665,7 @@ module.exports = function pick(obj, keys) { /***/ }), -/* 662 */ +/* 655 */ /***/ (function(module, exports) { var toString = Object.prototype.toString; @@ -78451,7 +77800,7 @@ function isBuffer(val) { /***/ }), -/* 663 */ +/* 656 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -78461,18 +77810,18 @@ function isBuffer(val) { * Module dependencies */ -var extend = __webpack_require__(535); -var unique = __webpack_require__(537); -var toRegex = __webpack_require__(648); +var extend = __webpack_require__(549); +var unique = __webpack_require__(548); +var toRegex = __webpack_require__(526); /** * Local dependencies */ -var compilers = __webpack_require__(664); -var parsers = __webpack_require__(675); -var Extglob = __webpack_require__(678); -var utils = __webpack_require__(677); +var compilers = __webpack_require__(657); +var parsers = __webpack_require__(668); +var Extglob = __webpack_require__(671); +var utils = __webpack_require__(670); var MAX_LENGTH = 1024 * 64; /** @@ -78789,13 +78138,13 @@ module.exports = extglob; /***/ }), -/* 664 */ +/* 657 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var brackets = __webpack_require__(665); +var brackets = __webpack_require__(658); /** * Extglob compilers @@ -78965,7 +78314,7 @@ module.exports = function(extglob) { /***/ }), -/* 665 */ +/* 658 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -78975,17 +78324,17 @@ module.exports = function(extglob) { * Local dependencies */ -var compilers = __webpack_require__(666); -var parsers = __webpack_require__(668); +var compilers = __webpack_require__(659); +var parsers = __webpack_require__(661); /** * Module dependencies */ -var debug = __webpack_require__(670)('expand-brackets'); -var extend = __webpack_require__(535); -var Snapdragon = __webpack_require__(566); -var toRegex = __webpack_require__(648); +var debug = __webpack_require__(663)('expand-brackets'); +var extend = __webpack_require__(549); +var Snapdragon = __webpack_require__(569); +var toRegex = __webpack_require__(526); /** * Parses the given POSIX character class `pattern` and returns a @@ -79183,13 +78532,13 @@ module.exports = brackets; /***/ }), -/* 666 */ +/* 659 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var posix = __webpack_require__(667); +var posix = __webpack_require__(660); module.exports = function(brackets) { brackets.compiler @@ -79277,7 +78626,7 @@ module.exports = function(brackets) { /***/ }), -/* 667 */ +/* 660 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -79306,14 +78655,14 @@ module.exports = { /***/ }), -/* 668 */ +/* 661 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var utils = __webpack_require__(669); -var define = __webpack_require__(593); +var utils = __webpack_require__(662); +var define = __webpack_require__(596); /** * Text regex @@ -79532,14 +78881,14 @@ module.exports.TEXT_REGEX = TEXT_REGEX; /***/ }), -/* 669 */ +/* 662 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var toRegex = __webpack_require__(648); -var regexNot = __webpack_require__(534); +var toRegex = __webpack_require__(526); +var regexNot = __webpack_require__(545); var cached; /** @@ -79573,7 +78922,7 @@ exports.createRegex = function(pattern, include) { /***/ }), -/* 670 */ +/* 663 */ /***/ (function(module, exports, __webpack_require__) { /** @@ -79582,14 +78931,14 @@ exports.createRegex = function(pattern, include) { */ if (typeof process !== 'undefined' && process.type === 'renderer') { - module.exports = __webpack_require__(671); + module.exports = __webpack_require__(664); } else { - module.exports = __webpack_require__(674); + module.exports = __webpack_require__(667); } /***/ }), -/* 671 */ +/* 664 */ /***/ (function(module, exports, __webpack_require__) { /** @@ -79598,7 +78947,7 @@ if (typeof process !== 'undefined' && process.type === 'renderer') { * Expose `debug()` as the module. */ -exports = module.exports = __webpack_require__(672); +exports = module.exports = __webpack_require__(665); exports.log = log; exports.formatArgs = formatArgs; exports.save = save; @@ -79780,7 +79129,7 @@ function localstorage() { /***/ }), -/* 672 */ +/* 665 */ /***/ (function(module, exports, __webpack_require__) { @@ -79796,7 +79145,7 @@ exports.coerce = coerce; exports.disable = disable; exports.enable = enable; exports.enabled = enabled; -exports.humanize = __webpack_require__(673); +exports.humanize = __webpack_require__(666); /** * The currently active debug mode names, and names to skip. @@ -79988,7 +79337,7 @@ function coerce(val) { /***/ }), -/* 673 */ +/* 666 */ /***/ (function(module, exports) { /** @@ -80146,15 +79495,15 @@ function plural(ms, n, name) { /***/ }), -/* 674 */ +/* 667 */ /***/ (function(module, exports, __webpack_require__) { /** * Module dependencies. */ -var tty = __webpack_require__(121); -var util = __webpack_require__(111); +var tty = __webpack_require__(122); +var util = __webpack_require__(112); /** * This is the Node.js implementation of `debug()`. @@ -80162,7 +79511,7 @@ var util = __webpack_require__(111); * Expose `debug()` as the module. */ -exports = module.exports = __webpack_require__(672); +exports = module.exports = __webpack_require__(665); exports.init = init; exports.log = log; exports.formatArgs = formatArgs; @@ -80334,14 +79683,14 @@ function createWritableStdioStream (fd) { break; case 'FILE': - var fs = __webpack_require__(133); + var fs = __webpack_require__(134); stream = new fs.SyncWriteStream(fd, { autoClose: false }); stream._type = 'fs'; break; case 'PIPE': case 'TCP': - var net = __webpack_require__(611); + var net = __webpack_require__(614); stream = new net.Socket({ fd: fd, readable: false, @@ -80400,15 +79749,15 @@ exports.enable(load()); /***/ }), -/* 675 */ +/* 668 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var brackets = __webpack_require__(665); -var define = __webpack_require__(676); -var utils = __webpack_require__(677); +var brackets = __webpack_require__(658); +var define = __webpack_require__(669); +var utils = __webpack_require__(670); /** * Characters to use in text regex (we want to "not" match @@ -80563,7 +79912,7 @@ module.exports = parsers; /***/ }), -/* 676 */ +/* 669 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -80576,7 +79925,7 @@ module.exports = parsers; -var isDescriptor = __webpack_require__(558); +var isDescriptor = __webpack_require__(535); module.exports = function defineProperty(obj, prop, val) { if (typeof obj !== 'object' && typeof obj !== 'function') { @@ -80601,14 +79950,14 @@ module.exports = function defineProperty(obj, prop, val) { /***/ }), -/* 677 */ +/* 670 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var regex = __webpack_require__(534); -var Cache = __webpack_require__(656); +var regex = __webpack_require__(545); +var Cache = __webpack_require__(649); /** * Utils @@ -80677,7 +80026,7 @@ utils.createRegex = function(str) { /***/ }), -/* 678 */ +/* 671 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -80687,16 +80036,16 @@ utils.createRegex = function(str) { * Module dependencies */ -var Snapdragon = __webpack_require__(566); -var define = __webpack_require__(676); -var extend = __webpack_require__(535); +var Snapdragon = __webpack_require__(569); +var define = __webpack_require__(669); +var extend = __webpack_require__(549); /** * Local dependencies */ -var compilers = __webpack_require__(664); -var parsers = __webpack_require__(675); +var compilers = __webpack_require__(657); +var parsers = __webpack_require__(668); /** * Customize Snapdragon parser and renderer @@ -80762,16 +80111,16 @@ module.exports = Extglob; /***/ }), -/* 679 */ +/* 672 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var extglob = __webpack_require__(663); -var nanomatch = __webpack_require__(647); -var regexNot = __webpack_require__(534); -var toRegex = __webpack_require__(635); +var extglob = __webpack_require__(656); +var nanomatch = __webpack_require__(641); +var regexNot = __webpack_require__(545); +var toRegex = __webpack_require__(526); var not; /** @@ -80852,14 +80201,14 @@ function textRegex(pattern) { /***/ }), -/* 680 */ +/* 673 */ /***/ (function(module, exports, __webpack_require__) { -module.exports = new (__webpack_require__(656))(); +module.exports = new (__webpack_require__(649))(); /***/ }), -/* 681 */ +/* 674 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -80872,13 +80221,13 @@ var path = __webpack_require__(4); * Module dependencies */ -var Snapdragon = __webpack_require__(566); -utils.define = __webpack_require__(642); -utils.diff = __webpack_require__(660); -utils.extend = __webpack_require__(643); -utils.pick = __webpack_require__(661); -utils.typeOf = __webpack_require__(682); -utils.unique = __webpack_require__(537); +var Snapdragon = __webpack_require__(569); +utils.define = __webpack_require__(675); +utils.diff = __webpack_require__(653); +utils.extend = __webpack_require__(638); +utils.pick = __webpack_require__(654); +utils.typeOf = __webpack_require__(676); +utils.unique = __webpack_require__(548); /** * Returns true if the platform is windows, or `path.sep` is `\\`. @@ -81175,7 +80524,52 @@ utils.unixify = function(options) { /***/ }), -/* 682 */ +/* 675 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +/*! + * define-property + * + * Copyright (c) 2015-2018, Jon Schlinkert. + * Released under the MIT License. + */ + + + +var isobject = __webpack_require__(534); +var isDescriptor = __webpack_require__(535); +var define = (typeof Reflect !== 'undefined' && Reflect.defineProperty) + ? Reflect.defineProperty + : Object.defineProperty; + +module.exports = function defineProperty(obj, key, val) { + if (!isobject(obj) && typeof obj !== 'function' && !Array.isArray(obj)) { + throw new TypeError('expected an object, function, or array'); + } + + if (typeof key !== 'string') { + throw new TypeError('expected "key" to be a string'); + } + + if (isDescriptor(val)) { + define(obj, key, val); + return obj; + } + + define(obj, key, { + configurable: true, + enumerable: false, + writable: true, + value: val + }); + + return obj; +}; + + +/***/ }), +/* 676 */ /***/ (function(module, exports) { var toString = Object.prototype.toString; @@ -81310,7 +80704,7 @@ function isBuffer(val) { /***/ }), -/* 683 */ +/* 677 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -81329,9 +80723,9 @@ var __extends = (this && this.__extends) || (function () { }; })(); Object.defineProperty(exports, "__esModule", { value: true }); -var readdir = __webpack_require__(684); -var reader_1 = __webpack_require__(697); -var fs_stream_1 = __webpack_require__(701); +var readdir = __webpack_require__(678); +var reader_1 = __webpack_require__(691); +var fs_stream_1 = __webpack_require__(695); var ReaderAsync = /** @class */ (function (_super) { __extends(ReaderAsync, _super); function ReaderAsync() { @@ -81392,15 +80786,15 @@ exports.default = ReaderAsync; /***/ }), -/* 684 */ +/* 678 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const readdirSync = __webpack_require__(685); -const readdirAsync = __webpack_require__(693); -const readdirStream = __webpack_require__(696); +const readdirSync = __webpack_require__(679); +const readdirAsync = __webpack_require__(687); +const readdirStream = __webpack_require__(690); module.exports = exports = readdirAsyncPath; exports.readdir = exports.readdirAsync = exports.async = readdirAsyncPath; @@ -81484,7 +80878,7 @@ function readdirStreamStat (dir, options) { /***/ }), -/* 685 */ +/* 679 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -81492,11 +80886,11 @@ function readdirStreamStat (dir, options) { module.exports = readdirSync; -const DirectoryReader = __webpack_require__(686); +const DirectoryReader = __webpack_require__(680); let syncFacade = { - fs: __webpack_require__(691), - forEach: __webpack_require__(692), + fs: __webpack_require__(685), + forEach: __webpack_require__(686), sync: true }; @@ -81525,18 +80919,18 @@ function readdirSync (dir, options, internalOptions) { /***/ }), -/* 686 */ +/* 680 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const Readable = __webpack_require__(137).Readable; -const EventEmitter = __webpack_require__(155).EventEmitter; +const Readable = __webpack_require__(138).Readable; +const EventEmitter = __webpack_require__(156).EventEmitter; const path = __webpack_require__(4); -const normalizeOptions = __webpack_require__(687); -const stat = __webpack_require__(689); -const call = __webpack_require__(690); +const normalizeOptions = __webpack_require__(681); +const stat = __webpack_require__(683); +const call = __webpack_require__(684); /** * Asynchronously reads the contents of a directory and streams the results @@ -81912,14 +81306,14 @@ module.exports = DirectoryReader; /***/ }), -/* 687 */ +/* 681 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const path = __webpack_require__(4); -const globToRegExp = __webpack_require__(688); +const globToRegExp = __webpack_require__(682); module.exports = normalizeOptions; @@ -82096,7 +81490,7 @@ function normalizeOptions (options, internalOptions) { /***/ }), -/* 688 */ +/* 682 */ /***/ (function(module, exports) { module.exports = function (glob, opts) { @@ -82233,13 +81627,13 @@ module.exports = function (glob, opts) { /***/ }), -/* 689 */ +/* 683 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const call = __webpack_require__(690); +const call = __webpack_require__(684); module.exports = stat; @@ -82314,7 +81708,7 @@ function symlinkStat (fs, path, lstats, callback) { /***/ }), -/* 690 */ +/* 684 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -82375,14 +81769,14 @@ function callOnce (fn) { /***/ }), -/* 691 */ +/* 685 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const fs = __webpack_require__(133); -const call = __webpack_require__(690); +const fs = __webpack_require__(134); +const call = __webpack_require__(684); /** * A facade around {@link fs.readdirSync} that allows it to be called @@ -82446,7 +81840,7 @@ exports.lstat = function (path, callback) { /***/ }), -/* 692 */ +/* 686 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -82475,7 +81869,7 @@ function syncForEach (array, iterator, done) { /***/ }), -/* 693 */ +/* 687 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -82483,12 +81877,12 @@ function syncForEach (array, iterator, done) { module.exports = readdirAsync; -const maybe = __webpack_require__(694); -const DirectoryReader = __webpack_require__(686); +const maybe = __webpack_require__(688); +const DirectoryReader = __webpack_require__(680); let asyncFacade = { - fs: __webpack_require__(133), - forEach: __webpack_require__(695), + fs: __webpack_require__(134), + forEach: __webpack_require__(689), async: true }; @@ -82530,7 +81924,7 @@ function readdirAsync (dir, options, callback, internalOptions) { /***/ }), -/* 694 */ +/* 688 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -82557,7 +81951,7 @@ module.exports = function maybe (cb, promise) { /***/ }), -/* 695 */ +/* 689 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -82593,7 +81987,7 @@ function asyncForEach (array, iterator, done) { /***/ }), -/* 696 */ +/* 690 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -82601,11 +81995,11 @@ function asyncForEach (array, iterator, done) { module.exports = readdirStream; -const DirectoryReader = __webpack_require__(686); +const DirectoryReader = __webpack_require__(680); let streamFacade = { - fs: __webpack_require__(133), - forEach: __webpack_require__(695), + fs: __webpack_require__(134), + forEach: __webpack_require__(689), async: true }; @@ -82625,16 +82019,16 @@ function readdirStream (dir, options, internalOptions) { /***/ }), -/* 697 */ +/* 691 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var path = __webpack_require__(4); -var deep_1 = __webpack_require__(698); -var entry_1 = __webpack_require__(700); -var pathUtil = __webpack_require__(699); +var deep_1 = __webpack_require__(692); +var entry_1 = __webpack_require__(694); +var pathUtil = __webpack_require__(693); var Reader = /** @class */ (function () { function Reader(options) { this.options = options; @@ -82700,14 +82094,14 @@ exports.default = Reader; /***/ }), -/* 698 */ +/* 692 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -var pathUtils = __webpack_require__(699); -var patternUtils = __webpack_require__(516); +var pathUtils = __webpack_require__(693); +var patternUtils = __webpack_require__(520); var DeepFilter = /** @class */ (function () { function DeepFilter(options, micromatchOptions) { this.options = options; @@ -82790,7 +82184,7 @@ exports.default = DeepFilter; /***/ }), -/* 699 */ +/* 693 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -82821,14 +82215,14 @@ exports.makeAbsolute = makeAbsolute; /***/ }), -/* 700 */ +/* 694 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -var pathUtils = __webpack_require__(699); -var patternUtils = __webpack_require__(516); +var pathUtils = __webpack_require__(693); +var patternUtils = __webpack_require__(520); var EntryFilter = /** @class */ (function () { function EntryFilter(options, micromatchOptions) { this.options = options; @@ -82913,7 +82307,7 @@ exports.default = EntryFilter; /***/ }), -/* 701 */ +/* 695 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -82932,9 +82326,9 @@ var __extends = (this && this.__extends) || (function () { }; })(); Object.defineProperty(exports, "__esModule", { value: true }); -var stream = __webpack_require__(137); -var fsStat = __webpack_require__(702); -var fs_1 = __webpack_require__(706); +var stream = __webpack_require__(138); +var fsStat = __webpack_require__(696); +var fs_1 = __webpack_require__(700); var FileSystemStream = /** @class */ (function (_super) { __extends(FileSystemStream, _super); function FileSystemStream() { @@ -82984,14 +82378,14 @@ exports.default = FileSystemStream; /***/ }), -/* 702 */ +/* 696 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const optionsManager = __webpack_require__(703); -const statProvider = __webpack_require__(705); +const optionsManager = __webpack_require__(697); +const statProvider = __webpack_require__(699); /** * Asynchronous API. */ @@ -83022,13 +82416,13 @@ exports.statSync = statSync; /***/ }), -/* 703 */ +/* 697 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const fsAdapter = __webpack_require__(704); +const fsAdapter = __webpack_require__(698); function prepare(opts) { const options = Object.assign({ fs: fsAdapter.getFileSystemAdapter(opts ? opts.fs : undefined), @@ -83041,13 +82435,13 @@ exports.prepare = prepare; /***/ }), -/* 704 */ +/* 698 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const fs = __webpack_require__(133); +const fs = __webpack_require__(134); exports.FILE_SYSTEM_ADAPTER = { lstat: fs.lstat, stat: fs.stat, @@ -83064,7 +82458,7 @@ exports.getFileSystemAdapter = getFileSystemAdapter; /***/ }), -/* 705 */ +/* 699 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -83116,7 +82510,7 @@ exports.isFollowedSymlink = isFollowedSymlink; /***/ }), -/* 706 */ +/* 700 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -83147,7 +82541,7 @@ exports.default = FileSystem; /***/ }), -/* 707 */ +/* 701 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -83166,10 +82560,10 @@ var __extends = (this && this.__extends) || (function () { }; })(); Object.defineProperty(exports, "__esModule", { value: true }); -var stream = __webpack_require__(137); -var readdir = __webpack_require__(684); -var reader_1 = __webpack_require__(697); -var fs_stream_1 = __webpack_require__(701); +var stream = __webpack_require__(138); +var readdir = __webpack_require__(678); +var reader_1 = __webpack_require__(691); +var fs_stream_1 = __webpack_require__(695); var TransformStream = /** @class */ (function (_super) { __extends(TransformStream, _super); function TransformStream(reader) { @@ -83237,7 +82631,7 @@ exports.default = ReaderStream; /***/ }), -/* 708 */ +/* 702 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -83256,9 +82650,9 @@ var __extends = (this && this.__extends) || (function () { }; })(); Object.defineProperty(exports, "__esModule", { value: true }); -var readdir = __webpack_require__(684); -var reader_1 = __webpack_require__(697); -var fs_sync_1 = __webpack_require__(709); +var readdir = __webpack_require__(678); +var reader_1 = __webpack_require__(691); +var fs_sync_1 = __webpack_require__(703); var ReaderSync = /** @class */ (function (_super) { __extends(ReaderSync, _super); function ReaderSync() { @@ -83318,7 +82712,7 @@ exports.default = ReaderSync; /***/ }), -/* 709 */ +/* 703 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -83337,8 +82731,8 @@ var __extends = (this && this.__extends) || (function () { }; })(); Object.defineProperty(exports, "__esModule", { value: true }); -var fsStat = __webpack_require__(702); -var fs_1 = __webpack_require__(706); +var fsStat = __webpack_require__(696); +var fs_1 = __webpack_require__(700); var FileSystemSync = /** @class */ (function (_super) { __extends(FileSystemSync, _super); function FileSystemSync() { @@ -83384,7 +82778,7 @@ exports.default = FileSystemSync; /***/ }), -/* 710 */ +/* 704 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -83400,13 +82794,13 @@ exports.flatten = flatten; /***/ }), -/* 711 */ +/* 705 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -var merge2 = __webpack_require__(291); +var merge2 = __webpack_require__(284); /** * Merge multiple streams and propagate their errors into one stream in parallel. */ @@ -83421,13 +82815,13 @@ exports.merge = merge; /***/ }), -/* 712 */ +/* 706 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const path = __webpack_require__(4); -const pathType = __webpack_require__(713); +const pathType = __webpack_require__(707); const getExtensions = extensions => extensions.length > 1 ? `{${extensions.join(',')}}` : extensions[0]; @@ -83493,13 +82887,13 @@ module.exports.sync = (input, opts) => { /***/ }), -/* 713 */ +/* 707 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const fs = __webpack_require__(133); -const pify = __webpack_require__(714); +const fs = __webpack_require__(134); +const pify = __webpack_require__(708); function type(fn, fn2, fp) { if (typeof fp !== 'string') { @@ -83542,7 +82936,7 @@ exports.symlinkSync = typeSync.bind(null, 'lstatSync', 'isSymbolicLink'); /***/ }), -/* 714 */ +/* 708 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -83633,17 +83027,17 @@ module.exports = (obj, opts) => { /***/ }), -/* 715 */ +/* 709 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const fs = __webpack_require__(133); +const fs = __webpack_require__(134); const path = __webpack_require__(4); -const fastGlob = __webpack_require__(512); -const gitIgnore = __webpack_require__(716); -const pify = __webpack_require__(717); -const slash = __webpack_require__(718); +const fastGlob = __webpack_require__(516); +const gitIgnore = __webpack_require__(710); +const pify = __webpack_require__(711); +const slash = __webpack_require__(712); const DEFAULT_IGNORE = [ '**/node_modules/**', @@ -83741,7 +83135,7 @@ module.exports.sync = options => { /***/ }), -/* 716 */ +/* 710 */ /***/ (function(module, exports) { // A simple implementation of make-array @@ -84210,7 +83604,7 @@ module.exports = options => new IgnoreBase(options) /***/ }), -/* 717 */ +/* 711 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -84285,7 +83679,7 @@ module.exports = (input, options) => { /***/ }), -/* 718 */ +/* 712 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -84303,71 +83697,17 @@ module.exports = input => { /***/ }), -/* 719 */ -/***/ (function(module, exports, __webpack_require__) { - -/*! - * is-glob - * - * Copyright (c) 2014-2017, Jon Schlinkert. - * Released under the MIT License. - */ - -var isExtglob = __webpack_require__(302); -var chars = { '{': '}', '(': ')', '[': ']'}; -var strictRegex = /\\(.)|(^!|\*|[\].+)]\?|\[[^\\\]]+\]|\{[^\\}]+\}|\(\?[:!=][^\\)]+\)|\([^|]+\|[^\\)]+\))/; -var relaxedRegex = /\\(.)|(^!|[*?{}()[\]]|\(\?)/; - -module.exports = function isGlob(str, options) { - if (typeof str !== 'string' || str === '') { - return false; - } - - if (isExtglob(str)) { - return true; - } - - var regex = strictRegex; - var match; - - // optionally relax regex - if (options && options.strict === false) { - regex = relaxedRegex; - } - - while ((match = regex.exec(str))) { - if (match[2]) return true; - var idx = match.index + match[0].length; - - // if an open bracket/brace/paren is escaped, - // set the index to the next closing character - var open = match[1]; - var close = open ? chars[open] : null; - if (open && close) { - var n = str.indexOf(close, idx); - if (n !== -1) { - idx = n + 1; - } - } - - str = str.slice(idx); - } - return false; -}; - - -/***/ }), -/* 720 */ +/* 713 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const path = __webpack_require__(4); -const {constants: fsConstants} = __webpack_require__(133); -const pEvent = __webpack_require__(721); -const CpFileError = __webpack_require__(724); -const fs = __webpack_require__(728); -const ProgressEmitter = __webpack_require__(731); +const {constants: fsConstants} = __webpack_require__(134); +const pEvent = __webpack_require__(714); +const CpFileError = __webpack_require__(717); +const fs = __webpack_require__(719); +const ProgressEmitter = __webpack_require__(722); const cpFileAsync = async (source, destination, options, progressEmitter) => { let readError; @@ -84481,12 +83821,12 @@ module.exports.sync = (source, destination, options) => { /***/ }), -/* 721 */ +/* 714 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const pTimeout = __webpack_require__(722); +const pTimeout = __webpack_require__(715); const symbolAsyncIterator = Symbol.asyncIterator || '@@asyncIterator'; @@ -84777,12 +84117,12 @@ module.exports.iterator = (emitter, event, options) => { /***/ }), -/* 722 */ +/* 715 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const pFinally = __webpack_require__(723); +const pFinally = __webpack_require__(716); class TimeoutError extends Error { constructor(message) { @@ -84828,7 +84168,7 @@ module.exports.TimeoutError = TimeoutError; /***/ }), -/* 723 */ +/* 716 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -84850,12 +84190,12 @@ module.exports = (promise, onFinally) => { /***/ }), -/* 724 */ +/* 717 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const NestedError = __webpack_require__(725); +const NestedError = __webpack_require__(718); class CpFileError extends NestedError { constructor(message, nested) { @@ -84869,15 +84209,17 @@ module.exports = CpFileError; /***/ }), -/* 725 */ +/* 718 */ /***/ (function(module, exports, __webpack_require__) { -var inherits = __webpack_require__(726); +var inherits = __webpack_require__(112).inherits; var NestedError = function (message, nested) { this.nested = nested; - if (typeof message !== 'undefined') { + if (message instanceof Error) { + nested = message; + } else if (typeof message !== 'undefined') { Object.defineProperty(this, 'message', { value: message, writable: true, @@ -84923,58 +84265,16 @@ module.exports = NestedError; /***/ }), -/* 726 */ -/***/ (function(module, exports, __webpack_require__) { - -try { - var util = __webpack_require__(111); - if (typeof util.inherits !== 'function') throw ''; - module.exports = util.inherits; -} catch (e) { - module.exports = __webpack_require__(727); -} - - -/***/ }), -/* 727 */ -/***/ (function(module, exports) { - -if (typeof Object.create === 'function') { - // implementation from standard node.js 'util' module - module.exports = function inherits(ctor, superCtor) { - ctor.super_ = superCtor - ctor.prototype = Object.create(superCtor.prototype, { - constructor: { - value: ctor, - enumerable: false, - writable: true, - configurable: true - } - }); - }; -} else { - // old school shim for old browsers - module.exports = function inherits(ctor, superCtor) { - ctor.super_ = superCtor - var TempCtor = function () {} - TempCtor.prototype = superCtor.prototype - ctor.prototype = new TempCtor() - ctor.prototype.constructor = ctor - } -} - - -/***/ }), -/* 728 */ +/* 719 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const {promisify} = __webpack_require__(111); -const fs = __webpack_require__(132); -const makeDir = __webpack_require__(729); -const pEvent = __webpack_require__(721); -const CpFileError = __webpack_require__(724); +const {promisify} = __webpack_require__(112); +const fs = __webpack_require__(133); +const makeDir = __webpack_require__(720); +const pEvent = __webpack_require__(714); +const CpFileError = __webpack_require__(717); const stat = promisify(fs.stat); const lstat = promisify(fs.lstat); @@ -85071,15 +84371,15 @@ exports.copyFileSync = (source, destination, flags) => { /***/ }), -/* 729 */ +/* 720 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const fs = __webpack_require__(133); +const fs = __webpack_require__(134); const path = __webpack_require__(4); -const {promisify} = __webpack_require__(111); -const semver = __webpack_require__(730); +const {promisify} = __webpack_require__(112); +const semver = __webpack_require__(721); const useNativeRecursiveOption = semver.satisfies(process.version, '>=10.12.0'); @@ -85234,7 +84534,7 @@ module.exports.sync = (input, options) => { /***/ }), -/* 730 */ +/* 721 */ /***/ (function(module, exports) { exports = module.exports = SemVer @@ -86836,12 +86136,12 @@ function coerce (version, options) { /***/ }), -/* 731 */ +/* 722 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const EventEmitter = __webpack_require__(155); +const EventEmitter = __webpack_require__(156); const written = new WeakMap(); @@ -86877,7 +86177,7 @@ module.exports = ProgressEmitter; /***/ }), -/* 732 */ +/* 723 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -86923,12 +86223,12 @@ exports.default = module.exports; /***/ }), -/* 733 */ +/* 724 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const NestedError = __webpack_require__(734); +const NestedError = __webpack_require__(718); class CpyError extends NestedError { constructor(message, nested) { @@ -86941,61 +86241,5 @@ class CpyError extends NestedError { module.exports = CpyError; -/***/ }), -/* 734 */ -/***/ (function(module, exports, __webpack_require__) { - -var inherits = __webpack_require__(111).inherits; - -var NestedError = function (message, nested) { - this.nested = nested; - - if (message instanceof Error) { - nested = message; - } else if (typeof message !== 'undefined') { - Object.defineProperty(this, 'message', { - value: message, - writable: true, - enumerable: false, - configurable: true - }); - } - - Error.captureStackTrace(this, this.constructor); - var oldStackDescriptor = Object.getOwnPropertyDescriptor(this, 'stack'); - var stackDescriptor = buildStackDescriptor(oldStackDescriptor, nested); - Object.defineProperty(this, 'stack', stackDescriptor); -}; - -function buildStackDescriptor(oldStackDescriptor, nested) { - if (oldStackDescriptor.get) { - return { - get: function () { - var stack = oldStackDescriptor.get.call(this); - return buildCombinedStacks(stack, this.nested); - } - }; - } else { - var stack = oldStackDescriptor.value; - return { - value: buildCombinedStacks(stack, nested) - }; - } -} - -function buildCombinedStacks(stack, nested) { - if (nested) { - stack += '\nCaused By: ' + nested.stack; - } - return stack; -} - -inherits(NestedError, Error); -NestedError.prototype.name = 'NestedError'; - - -module.exports = NestedError; - - /***/ }) /******/ ]); \ No newline at end of file diff --git a/packages/kbn-pm/package.json b/packages/kbn-pm/package.json index 1fb94e4c92ce1..8ffd86b84bf76 100644 --- a/packages/kbn-pm/package.json +++ b/packages/kbn-pm/package.json @@ -10,7 +10,7 @@ "prettier": "prettier --write './src/**/*.ts'" }, "devDependencies": { - "@babel/core": "^7.11.1", + "@babel/core": "^7.11.6", "@babel/plugin-proposal-class-properties": "^7.10.4", "@babel/plugin-proposal-object-rest-spread": "^7.11.0", "@babel/preset-env": "^7.11.0", @@ -19,8 +19,8 @@ "@types/cpy": "^5.1.0", "@types/dedent": "^0.7.0", "@types/getopts": "^2.0.1", - "@types/glob": "^5.0.35", - "@types/globby": "^6.1.0", + "@types/glob": "^7.1.2", + "@types/globby": "^8.0.0", "@types/has-ansi": "^3.0.0", "@types/lodash": "^4.14.159", "@types/log-symbols": "^2.0.0", @@ -28,7 +28,7 @@ "@types/node": ">=10.17.17 <10.20.0", "@types/ora": "^1.3.5", "@types/read-pkg": "^4.0.0", - "@types/strip-ansi": "^3.0.0", + "@types/strip-ansi": "^5.2.1", "@types/strong-log-transformer": "^1.0.0", "@types/tempy": "^0.2.0", "@types/write-pkg": "^3.1.0", @@ -41,22 +41,22 @@ "dedent": "^0.7.0", "del": "^5.1.0", "execa": "^4.0.2", - "getopts": "^2.2.4", + "getopts": "^2.2.5", "glob": "^7.1.2", "globby": "^8.0.1", "has-ansi": "^3.0.0", "is-path-inside": "^3.0.2", - "lodash": "^4.17.15", + "lodash": "^4.17.20", "log-symbols": "^2.2.0", "multimatch": "^4.0.0", "ncp": "^2.0.0", - "ora": "^1.4.0", + "ora": "^4.0.4", "prettier": "^2.1.1", "read-pkg": "^5.2.0", "rxjs": "^6.5.5", "spawn-sync": "^1.0.15", "string-replace-loader": "^2.2.0", - "strip-ansi": "^4.0.0", + "strip-ansi": "^6.0.0", "strong-log-transformer": "^2.1.0", "tempy": "^0.3.0", "typescript": "4.0.2", diff --git a/packages/kbn-pm/src/cli.ts b/packages/kbn-pm/src/cli.ts index 816e84c13bbe9..92ddf3d957cd5 100644 --- a/packages/kbn-pm/src/cli.ts +++ b/packages/kbn-pm/src/cli.ts @@ -47,6 +47,7 @@ function help() { --oss Do not include the x-pack when running command. --skip-kibana-plugins Filter all plugins in ./plugins and ../kibana-extra when running command. --no-cache Disable the bootstrap cache + --no-validate Disable the bootstrap yarn.lock validation --verbose Set log level to verbose --debug Set log level to debug --quiet Set log level to error @@ -80,8 +81,9 @@ export async function run(argv: string[]) { }, default: { cache: true, + validate: true, }, - boolean: ['prefer-offline', 'frozen-lockfile', 'cache'], + boolean: ['prefer-offline', 'frozen-lockfile', 'cache', 'validate'], }); const args = options._; diff --git a/packages/kbn-pm/src/commands/__snapshots__/bootstrap.test.ts.snap b/packages/kbn-pm/src/commands/__snapshots__/bootstrap.test.ts.snap deleted file mode 100644 index be146d710c87a..0000000000000 --- a/packages/kbn-pm/src/commands/__snapshots__/bootstrap.test.ts.snap +++ /dev/null @@ -1,159 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`calls "kbn:bootstrap" scripts and links executables after installing deps: link bins 1`] = ` -Array [ - Array [ - Map { - "kibana" => Project { - "allDependencies": Object { - "bar": "1.0.0", - }, - "devDependencies": Object {}, - "isWorkspaceProject": false, - "isWorkspaceRoot": true, - "json": Object { - "dependencies": Object { - "bar": "1.0.0", - }, - "name": "kibana", - "version": "1.0.0", - "workspaces": Object { - "packages": Array [ - "packages/*", - ], - }, - }, - "nodeModulesLocation": "/packages/kbn-pm/src/commands/node_modules", - "packageJsonLocation": "/packages/kbn-pm/src/commands/package.json", - "path": "/packages/kbn-pm/src/commands", - "productionDependencies": Object { - "bar": "1.0.0", - }, - "scripts": Object {}, - "targetLocation": "/packages/kbn-pm/src/commands/target", - "version": "1.0.0", - }, - "bar" => Project { - "allDependencies": Object {}, - "devDependencies": Object {}, - "isWorkspaceProject": false, - "isWorkspaceRoot": false, - "json": Object { - "name": "bar", - "scripts": Object { - "kbn:bootstrap": "node ./bar.js", - }, - "version": "1.0.0", - }, - "nodeModulesLocation": "/packages/kbn-pm/src/commands/packages/bar/node_modules", - "packageJsonLocation": "/packages/kbn-pm/src/commands/packages/bar/package.json", - "path": "/packages/kbn-pm/src/commands/packages/bar", - "productionDependencies": Object {}, - "scripts": Object { - "kbn:bootstrap": "node ./bar.js", - }, - "targetLocation": "/packages/kbn-pm/src/commands/packages/bar/target", - "version": "1.0.0", - }, - }, - Map { - "kibana" => Array [ - Project { - "allDependencies": Object {}, - "devDependencies": Object {}, - "isWorkspaceProject": false, - "isWorkspaceRoot": false, - "json": Object { - "name": "bar", - "scripts": Object { - "kbn:bootstrap": "node ./bar.js", - }, - "version": "1.0.0", - }, - "nodeModulesLocation": "/packages/kbn-pm/src/commands/packages/bar/node_modules", - "packageJsonLocation": "/packages/kbn-pm/src/commands/packages/bar/package.json", - "path": "/packages/kbn-pm/src/commands/packages/bar", - "productionDependencies": Object {}, - "scripts": Object { - "kbn:bootstrap": "node ./bar.js", - }, - "targetLocation": "/packages/kbn-pm/src/commands/packages/bar/target", - "version": "1.0.0", - }, - ], - "bar" => Array [], - }, - ], -] -`; - -exports[`calls "kbn:bootstrap" scripts and links executables after installing deps: script 1`] = ` -Array [ - Array [ - Object { - "args": Array [], - "debug": undefined, - "pkg": Project { - "allDependencies": Object {}, - "devDependencies": Object {}, - "isWorkspaceProject": false, - "isWorkspaceRoot": false, - "json": Object { - "name": "bar", - "scripts": Object { - "kbn:bootstrap": "node ./bar.js", - }, - "version": "1.0.0", - }, - "nodeModulesLocation": "/packages/kbn-pm/src/commands/packages/bar/node_modules", - "packageJsonLocation": "/packages/kbn-pm/src/commands/packages/bar/package.json", - "path": "/packages/kbn-pm/src/commands/packages/bar", - "productionDependencies": Object {}, - "scripts": Object { - "kbn:bootstrap": "node ./bar.js", - }, - "targetLocation": "/packages/kbn-pm/src/commands/packages/bar/target", - "version": "1.0.0", - }, - "script": "kbn:bootstrap", - }, - ], -] -`; - -exports[`does not run installer if no deps in package: install in dir 1`] = ` -Array [ - Array [ - "/packages/kbn-pm/src/commands", - Array [], - ], -] -`; - -exports[`handles "frozen-lockfile": install in dir 1`] = ` -Array [ - Array [ - "/packages/kbn-pm/src/commands", - Array [ - "--frozen-lockfile", - ], - ], -] -`; - -exports[`handles dependencies of dependencies: install in dir 1`] = ` -Array [ - Array [ - "/packages/kbn-pm/src/commands", - Array [], - ], - Array [ - "/packages/kbn-pm/src/commands/packages/bar", - Array [], - ], - Array [ - "/packages/kbn-pm/src/commands/packages/foo", - Array [], - ], -] -`; diff --git a/packages/kbn-pm/src/commands/bootstrap.test.ts b/packages/kbn-pm/src/commands/bootstrap.test.ts deleted file mode 100644 index 97505a66a1fff..0000000000000 --- a/packages/kbn-pm/src/commands/bootstrap.test.ts +++ /dev/null @@ -1,245 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -jest.mock('../utils/scripts'); -jest.mock('../utils/link_project_executables'); - -import { resolve } from 'path'; - -import { ToolingLogCollectingWriter } from '@kbn/dev-utils/tooling_log'; - -import { absolutePathSnapshotSerializer, stripAnsiSnapshotSerializer } from '../test_helpers'; -import { linkProjectExecutables } from '../utils/link_project_executables'; -import { IPackageJson } from '../utils/package_json'; -import { Project } from '../utils/project'; -import { buildProjectGraph } from '../utils/projects'; -import { installInDir, runScriptInPackageStreaming, yarnWorkspacesInfo } from '../utils/scripts'; -import { BootstrapCommand } from './bootstrap'; -import { Kibana } from '../utils/kibana'; -import { log } from '../utils/log'; - -const mockInstallInDir = installInDir as jest.Mock; -const mockRunScriptInPackageStreaming = runScriptInPackageStreaming as jest.Mock; -const mockLinkProjectExecutables = linkProjectExecutables as jest.Mock; -const mockYarnWorkspacesInfo = yarnWorkspacesInfo as jest.Mock; - -const logWriter = new ToolingLogCollectingWriter('debug'); -log.setLogLevel('silent'); -log.setWriters([logWriter]); -beforeEach(() => { - logWriter.messages.length = 0; -}); - -const createProject = (packageJson: IPackageJson, path = '.') => { - const project = new Project( - { - name: 'kibana', - version: '1.0.0', - ...packageJson, - }, - resolve(__dirname, path) - ); - - if (packageJson.workspaces) { - project.isWorkspaceRoot = true; - } - - return project; -}; -expect.addSnapshotSerializer(absolutePathSnapshotSerializer); -expect.addSnapshotSerializer(stripAnsiSnapshotSerializer); - -beforeEach(() => { - mockYarnWorkspacesInfo.mockResolvedValue({}); -}); - -afterEach(() => { - jest.resetAllMocks(); - jest.restoreAllMocks(); -}); - -test('handles dependencies of dependencies', async () => { - const kibana = createProject({ - dependencies: { - bar: '1.0.0', - }, - workspaces: { - packages: ['packages/*'], - }, - }); - const foo = createProject( - { - dependencies: { - bar: 'link:../bar', - }, - name: 'foo', - }, - 'packages/foo' - ); - const bar = createProject( - { - dependencies: { - baz: 'link:../baz', - }, - name: 'bar', - }, - 'packages/bar' - ); - const baz = createProject( - { - name: 'baz', - }, - 'packages/baz' - ); - - const projects = new Map([ - ['kibana', kibana], - ['foo', foo], - ['bar', bar], - ['baz', baz], - ]); - const kbn = new Kibana(projects); - const projectGraph = buildProjectGraph(projects); - - await BootstrapCommand.run(projects, projectGraph, { - extraArgs: [], - options: {}, - rootPath: '', - kbn, - }); - - expect(mockInstallInDir.mock.calls).toMatchSnapshot('install in dir'); - expect(logWriter.messages).toMatchInlineSnapshot(` - Array [ - info [kibana] running yarn, - "", - "", - info [bar] running yarn, - "", - "", - info [foo] running yarn, - "", - "", - ] - `); -}); - -test('does not run installer if no deps in package', async () => { - const kibana = createProject({ - dependencies: { - bar: '1.0.0', - }, - workspaces: { - packages: ['packages/*'], - }, - }); - // bar has no dependencies - const bar = createProject( - { - name: 'bar', - }, - 'packages/bar' - ); - - const projects = new Map([ - ['kibana', kibana], - ['bar', bar], - ]); - const kbn = new Kibana(projects); - const projectGraph = buildProjectGraph(projects); - - await BootstrapCommand.run(projects, projectGraph, { - extraArgs: [], - options: {}, - rootPath: '', - kbn, - }); - - expect(mockInstallInDir.mock.calls).toMatchSnapshot('install in dir'); - expect(logWriter.messages).toMatchInlineSnapshot(` - Array [ - info [kibana] running yarn, - "", - "", - ] - `); -}); - -test('handles "frozen-lockfile"', async () => { - const kibana = createProject({ - dependencies: { - foo: '2.2.0', - }, - workspaces: { - packages: ['packages/*'], - }, - }); - - const projects = new Map([['kibana', kibana]]); - const kbn = new Kibana(projects); - const projectGraph = buildProjectGraph(projects); - - await BootstrapCommand.run(projects, projectGraph, { - extraArgs: [], - options: { - 'frozen-lockfile': true, - }, - rootPath: '', - kbn, - }); - - expect(mockInstallInDir.mock.calls).toMatchSnapshot('install in dir'); -}); - -test('calls "kbn:bootstrap" scripts and links executables after installing deps', async () => { - const kibana = createProject({ - dependencies: { - bar: '1.0.0', - }, - workspaces: { - packages: ['packages/*'], - }, - }); - const bar = createProject( - { - name: 'bar', - scripts: { - 'kbn:bootstrap': 'node ./bar.js', - }, - }, - 'packages/bar' - ); - - const projects = new Map([ - ['kibana', kibana], - ['bar', bar], - ]); - const kbn = new Kibana(projects); - const projectGraph = buildProjectGraph(projects); - - await BootstrapCommand.run(projects, projectGraph, { - extraArgs: [], - options: {}, - rootPath: '', - kbn, - }); - - expect(mockLinkProjectExecutables.mock.calls).toMatchSnapshot('link bins'); - expect(mockRunScriptInPackageStreaming.mock.calls).toMatchSnapshot('script'); -}); diff --git a/packages/kbn-pm/src/commands/bootstrap.ts b/packages/kbn-pm/src/commands/bootstrap.ts index a559f9a20432a..0fa3f355ae9d6 100644 --- a/packages/kbn-pm/src/commands/bootstrap.ts +++ b/packages/kbn-pm/src/commands/bootstrap.ts @@ -25,6 +25,8 @@ import { Project } from '../utils/project'; import { ICommand } from './'; import { getAllChecksums } from '../utils/project_checksums'; import { BootstrapCacheFile } from '../utils/bootstrap_cache_file'; +import { readYarnLock } from '../utils/yarn_lock'; +import { validateYarnLock } from '../utils/validate_yarn_lock'; export const BootstrapCommand: ICommand = { description: 'Install dependencies and crosslink projects', @@ -54,6 +56,12 @@ export const BootstrapCommand: ICommand = { } } + const yarnLock = await readYarnLock(kbn); + + if (options.validate) { + await validateYarnLock(kbn, yarnLock); + } + await linkProjectExecutables(projects, projectGraph); /** @@ -63,7 +71,7 @@ export const BootstrapCommand: ICommand = { * have to, as it will slow down the bootstrapping process. */ - const checksums = await getAllChecksums(kbn, log); + const checksums = await getAllChecksums(kbn, log, yarnLock); const caches = new Map(); let cachedProjectCount = 0; diff --git a/packages/kbn-pm/src/utils/__snapshots__/link_project_executables.test.ts.snap b/packages/kbn-pm/src/utils/__snapshots__/link_project_executables.test.ts.snap index 5bda7b544e201..311e350f6e865 100644 --- a/packages/kbn-pm/src/utils/__snapshots__/link_project_executables.test.ts.snap +++ b/packages/kbn-pm/src/utils/__snapshots__/link_project_executables.test.ts.snap @@ -18,6 +18,7 @@ Object { "mkdirp": Array [], "readFile": Array [], "unlink": Array [], + "writeFile": Array [], } `; @@ -66,5 +67,6 @@ Object { ], "readFile": Array [], "unlink": Array [], + "writeFile": Array [], } `; diff --git a/packages/kbn-pm/src/utils/fs.ts b/packages/kbn-pm/src/utils/fs.ts index 44fc59bdeba96..21fd2c32b9c7b 100644 --- a/packages/kbn-pm/src/utils/fs.ts +++ b/packages/kbn-pm/src/utils/fs.ts @@ -25,6 +25,7 @@ import { promisify } from 'util'; const lstat = promisify(fs.lstat); export const readFile = promisify(fs.readFile); +export const writeFile = promisify(fs.writeFile); const symlink = promisify(fs.symlink); export const chmod = promisify(fs.chmod); const cmdShim = promisify(cmdShimCb); diff --git a/packages/kbn-pm/src/utils/kibana.ts b/packages/kbn-pm/src/utils/kibana.ts index 7fca4bd01822b..e48b61611d63f 100644 --- a/packages/kbn-pm/src/utils/kibana.ts +++ b/packages/kbn-pm/src/utils/kibana.ts @@ -22,6 +22,8 @@ import Path from 'path'; import multimatch from 'multimatch'; import isPathInside from 'is-path-inside'; +import { resolveDepsForProject, YarnLock } from './yarn_lock'; +import { Log } from './log'; import { ProjectMap, getProjects, includeTransitiveProjects } from './projects'; import { Project } from './project'; import { getProjectPaths } from '../config'; @@ -133,4 +135,26 @@ export class Kibana { isOutsideRepo(project: Project) { return !this.isPartOfRepo(project); } + + resolveAllProductionDependencies(yarnLock: YarnLock, log: Log) { + const kibanaDeps = resolveDepsForProject({ + project: this.kibanaProject, + yarnLock, + kbn: this, + includeDependentProject: true, + productionDepsOnly: true, + log, + })!; + + const xpackDeps = resolveDepsForProject({ + project: this.getProject('x-pack')!, + yarnLock, + kbn: this, + includeDependentProject: true, + productionDepsOnly: true, + log, + })!; + + return new Map([...kibanaDeps.entries(), ...xpackDeps.entries()]); + } } diff --git a/packages/kbn-pm/src/utils/project_checksums.ts b/packages/kbn-pm/src/utils/project_checksums.ts index 839c44f4f18c4..c13788c89bfaa 100644 --- a/packages/kbn-pm/src/utils/project_checksums.ts +++ b/packages/kbn-pm/src/utils/project_checksums.ts @@ -24,7 +24,7 @@ import { promisify } from 'util'; import execa from 'execa'; -import { readYarnLock, YarnLock } from './yarn_lock'; +import { YarnLock, resolveDepsForProject } from './yarn_lock'; import { ProjectMap } from '../utils/projects'; import { Project } from '../utils/project'; import { Kibana } from '../utils/kibana'; @@ -145,51 +145,6 @@ async function getLatestSha(project: Project, kbn: Kibana) { return stdout.trim() || undefined; } -/** - * Get a list of the absolute dependencies of this project, as resolved - * in the yarn.lock file, does not include other projects in the workspace - * or their dependencies - */ -function resolveDepsForProject(project: Project, yarnLock: YarnLock, kbn: Kibana, log: Log) { - /** map of [name@range, name@resolved] */ - const resolved = new Map(); - - const queue: Array<[string, string]> = Object.entries(project.allDependencies); - - while (queue.length) { - const [name, versionRange] = queue.shift()!; - const req = `${name}@${versionRange}`; - - if (resolved.has(req)) { - continue; - } - - if (!kbn.hasProject(name)) { - const pkg = yarnLock[req]; - if (!pkg) { - log.warning( - 'yarn.lock file is out of date, please run `yarn kbn bootstrap` to re-enable caching' - ); - return; - } - - const res = `${name}@${pkg.version}`; - resolved.set(req, res); - - const allDepsEntries = [ - ...Object.entries(pkg.dependencies || {}), - ...Object.entries(pkg.optionalDependencies || {}), - ]; - - for (const [childName, childVersionRange] of allDepsEntries) { - queue.push([childName, childVersionRange]); - } - } - } - - return Array.from(resolved.values()).sort((a, b) => a.localeCompare(b)); -} - /** * Get the checksum for a specific project in the workspace */ @@ -224,11 +179,22 @@ async function getChecksum( }) ); - const deps = await resolveDepsForProject(project, yarnLock, kbn, log); - if (!deps) { + const depMap = resolveDepsForProject({ + project, + yarnLock, + kbn, + log, + includeDependentProject: false, + productionDepsOnly: false, + }); + if (!depMap) { return; } + const deps = Array.from(depMap.values()) + .map(({ name, version }) => `${name}@${version}`) + .sort((a, b) => a.localeCompare(b)); + log.verbose(`[${project.name}] resolved %d deps`, deps.length); const checksum = JSON.stringify( @@ -256,10 +222,9 @@ async function getChecksum( * - un-committed changes * - resolved dependencies from yarn.lock referenced by project package.json */ -export async function getAllChecksums(kbn: Kibana, log: Log) { +export async function getAllChecksums(kbn: Kibana, log: Log, yarnLock: YarnLock) { const projects = kbn.getAllProjects(); const changesByProject = await getChangesForProjects(projects, kbn, log); - const yarnLock = await readYarnLock(kbn); /** map of [project.name, cacheKey] */ const cacheKeys: ChecksumMap = new Map(); diff --git a/packages/kbn-pm/src/utils/validate_yarn_lock.ts b/packages/kbn-pm/src/utils/validate_yarn_lock.ts new file mode 100644 index 0000000000000..ec853a3a958fb --- /dev/null +++ b/packages/kbn-pm/src/utils/validate_yarn_lock.ts @@ -0,0 +1,161 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +// @ts-expect-error published types are useless +import { stringify as stringifyLockfile } from '@yarnpkg/lockfile'; +import dedent from 'dedent'; + +import { writeFile } from './fs'; +import { Kibana } from './kibana'; +import { YarnLock } from './yarn_lock'; +import { log } from './log'; +import { Project } from './project'; + +export async function validateYarnLock(kbn: Kibana, yarnLock: YarnLock) { + // look through all of the packages in the yarn.lock file to see if + // we have accidentally installed multiple lodash v4 versions + const lodash4Versions = new Set(); + const lodash4Reqs = new Set(); + for (const [req, dep] of Object.entries(yarnLock)) { + if (req.startsWith('lodash@') && dep.version.startsWith('4.')) { + lodash4Reqs.add(req); + lodash4Versions.add(dep.version); + } + } + + // if we find more than one lodash v4 version installed then delete + // lodash v4 requests from the yarn.lock file and prompt the user to + // retry bootstrap so that a single v4 version will be installed + if (lodash4Versions.size > 1) { + for (const req of lodash4Reqs) { + delete yarnLock[req]; + } + + await writeFile(kbn.getAbsolute('yarn.lock'), stringifyLockfile(yarnLock), 'utf8'); + + log.error(dedent` + + Multiple version of lodash v4 were detected, so they have been removed + from the yarn.lock file. Please rerun yarn kbn bootstrap to coalese the + lodash versions installed. + + If you still see this error when you re-bootstrap then you might need + to force a new dependency to use the latest version of lodash via the + "resolutions" field in package.json. + + If you have questions about this please reach out to the operations team. + + `); + + process.exit(1); + } + + // look through all the dependencies of production packages and production + // dependencies of those packages to determine if we're shipping any versions + // of lodash v3 in the distributable + const prodDependencies = kbn.resolveAllProductionDependencies(yarnLock, log); + const lodash3Versions = new Set(); + for (const dep of prodDependencies.values()) { + if (dep.name === 'lodash' && dep.version.startsWith('3.')) { + lodash3Versions.add(dep.version); + } + } + + // if any lodash v3 packages were found we abort and tell the user to fix things + if (lodash3Versions.size) { + log.error(dedent` + + Due to changes in the yarn.lock file and/or package.json files a version of + lodash 3 is now included in the production dependencies. To reduce the size of + our distributable and especially our front-end bundles we have decided to + prevent adding any new instances of lodash 3. + + Please inspect the changes to yarn.lock or package.json files to identify where + the lodash 3 version is coming from and remove it. + + If you have questions about this please reack out to the operations team. + + `); + + process.exit(1); + } + + // TODO: remove this once we move into a single package.json + // look through all the package.json files to find packages which have mismatched version ranges + const depRanges = new Map>(); + for (const project of kbn.getAllProjects().values()) { + for (const [dep, range] of Object.entries(project.allDependencies)) { + const existingDep = depRanges.get(dep); + if (!existingDep) { + depRanges.set(dep, [ + { + range, + projects: [project], + }, + ]); + continue; + } + + const existingRange = existingDep.find((existing) => existing.range === range); + if (!existingRange) { + existingDep.push({ + range, + projects: [project], + }); + continue; + } + + existingRange.projects.push(project); + } + } + + const duplicateRanges = Array.from(depRanges.entries()) + .filter(([, ranges]) => ranges.length > 1) + .reduce( + (acc: string[], [dep, ranges]) => [ + ...acc, + dep, + ...ranges.map( + ({ range, projects }) => ` ${range} => ${projects.map((p) => p.name).join(', ')}` + ), + ], + [] + ) + .join('\n '); + + if (duplicateRanges) { + log.error(dedent` + + [single_version_dependencies] Multiple version ranges for the same dependency + were found declared across different package.json files. Please consolidate + those to match across all package.json files. Different versions for the + same dependency is not supported. + + If you have questions about this please reach out to the operations team. + + The conflicting dependencies are: + + ${duplicateRanges} + `); + + process.exit(1); + } + + log.success('yarn.lock analysis completed without any issues'); +} diff --git a/packages/kbn-pm/src/utils/yarn_lock.ts b/packages/kbn-pm/src/utils/yarn_lock.ts index f46240c0e1d2e..953341915e232 100644 --- a/packages/kbn-pm/src/utils/yarn_lock.ts +++ b/packages/kbn-pm/src/utils/yarn_lock.ts @@ -17,14 +17,16 @@ * under the License. */ -// @ts-ignore published types are worthless +// @ts-expect-error published types are worthless import { parse as parseLockfile } from '@yarnpkg/lockfile'; import { readFile } from '../utils/fs'; import { Kibana } from '../utils/kibana'; +import { Project } from '../utils/project'; +import { Log } from '../utils/log'; export interface YarnLock { - /** a simple map of version@versionrange tags to metadata about a package */ + /** a simple map of name@versionrange tags to metadata about a package */ [key: string]: { /** resolved version installed for this pacakge */ version: string; @@ -61,3 +63,82 @@ export async function readYarnLock(kbn: Kibana): Promise { return {}; } + +/** + * Get a list of the absolute dependencies of this project, as resolved + * in the yarn.lock file, does not include other projects in the workspace + * or their dependencies + */ +export function resolveDepsForProject({ + project: rootProject, + yarnLock, + kbn, + log, + productionDepsOnly, + includeDependentProject, +}: { + project: Project; + yarnLock: YarnLock; + kbn: Kibana; + log: Log; + productionDepsOnly: boolean; + includeDependentProject: boolean; +}) { + /** map of [name@range, { name, version }] */ + const resolved = new Map(); + + const seenProjects = new Set(); + const projectQueue: Project[] = [rootProject]; + const depQueue: Array<[string, string]> = []; + + while (projectQueue.length) { + const project = projectQueue.shift()!; + if (seenProjects.has(project)) { + continue; + } + seenProjects.add(project); + + const projectDeps = Object.entries( + productionDepsOnly ? project.productionDependencies : project.allDependencies + ); + for (const [name, versionRange] of projectDeps) { + depQueue.push([name, versionRange]); + } + + while (depQueue.length) { + const [name, versionRange] = depQueue.shift()!; + const req = `${name}@${versionRange}`; + + if (resolved.has(req)) { + continue; + } + + if (includeDependentProject && kbn.hasProject(name)) { + projectQueue.push(kbn.getProject(name)!); + } + + if (!kbn.hasProject(name)) { + const pkg = yarnLock[req]; + if (!pkg) { + log.warning( + 'yarn.lock file is out of date, please run `yarn kbn bootstrap` to re-enable caching' + ); + return; + } + + resolved.set(req, { name, version: pkg.version }); + + const allDepsEntries = [ + ...Object.entries(pkg.dependencies || {}), + ...Object.entries(pkg.optionalDependencies || {}), + ]; + + for (const [childName, childVersionRange] of allDepsEntries) { + depQueue.push([childName, childVersionRange]); + } + } + } + } + + return resolved; +} diff --git a/packages/kbn-release-notes/package.json b/packages/kbn-release-notes/package.json index f8971fa02aa87..268530c22399a 100644 --- a/packages/kbn-release-notes/package.json +++ b/packages/kbn-release-notes/package.json @@ -13,7 +13,7 @@ "axios": "^0.19.2", "cheerio": "0.22.0", "dedent": "^0.7.0", - "graphql": "^14.0.0", + "graphql": "^0.13.2", "graphql-tag": "^2.10.3", "terminal-link": "^2.1.1" }, diff --git a/packages/kbn-release-notes/src/lib/get_note_from_description.test.ts b/packages/kbn-release-notes/src/lib/get_note_from_description.test.ts index 23dcb302f090d..22b9713b78332 100644 --- a/packages/kbn-release-notes/src/lib/get_note_from_description.test.ts +++ b/packages/kbn-release-notes/src/lib/get_note_from_description.test.ts @@ -35,7 +35,8 @@ it('extracts expected components from html', () => { ## Release Note: Checkout this feature - `) + `), + 'release note' ) ).toMatchInlineSnapshot(`"Checkout this feature"`); @@ -46,10 +47,11 @@ it('extracts expected components from html', () => { Fixes: #1234 - #### Release Note: + #### Dev docs: We fixed an issue - `) + `), + 'dev docs' ) ).toMatchInlineSnapshot(`"We fixed an issue"`); @@ -60,8 +62,9 @@ it('extracts expected components from html', () => { Fixes: #1234 - Release note: Checkout feature foo - `) + OTHER TITLE: Checkout feature foo + `), + 'other title' ) ).toMatchInlineSnapshot(`"Checkout feature foo"`); @@ -73,7 +76,8 @@ it('extracts expected components from html', () => { My PR description release note : bar - `) + `), + 'release note' ) ).toMatchInlineSnapshot(`"bar"`); }); diff --git a/packages/kbn-release-notes/src/lib/get_note_from_description.ts b/packages/kbn-release-notes/src/lib/get_note_from_description.ts index 57df203470a5a..0d9135c431e36 100644 --- a/packages/kbn-release-notes/src/lib/get_note_from_description.ts +++ b/packages/kbn-release-notes/src/lib/get_note_from_description.ts @@ -19,11 +19,12 @@ import cheerio from 'cheerio'; -export function getNoteFromDescription(descriptionHtml: string) { +export function getNoteFromDescription(descriptionHtml: string, header: string) { + const re = new RegExp(`^(\\s*${header.toLowerCase()}(?:s)?\\s*:?\\s*)`, 'i'); const $ = cheerio.load(descriptionHtml); for (const el of $('p,h1,h2,h3,h4,h5').toArray()) { const text = $(el).text(); - const match = text.match(/^(\s*release note(?:s)?\s*:?\s*)/i); + const match = text.match(re); if (!match) { continue; diff --git a/packages/kbn-release-notes/src/lib/pr_api.ts b/packages/kbn-release-notes/src/lib/pr_api.ts index 1f26aa7ad86c3..5fa3dfdba10ef 100644 --- a/packages/kbn-release-notes/src/lib/pr_api.ts +++ b/packages/kbn-release-notes/src/lib/pr_api.ts @@ -178,7 +178,9 @@ export class PrApi { versions: labels .map((l) => Version.fromLabel(l)) .filter((v): v is Version => v instanceof Version), - note: getNoteFromDescription(node.bodyHTML), + note: + getNoteFromDescription(node.bodyHTML, 'release note') || + getNoteFromDescription(node.bodyHTML, 'dev docs'), }; } diff --git a/packages/kbn-spec-to-console/package.json b/packages/kbn-spec-to-console/package.json index 63ce93ac54f46..557f38ec740fc 100644 --- a/packages/kbn-spec-to-console/package.json +++ b/packages/kbn-spec-to-console/package.json @@ -17,11 +17,11 @@ }, "homepage": "https://github.com/jbudz/spec-to-console#readme", "devDependencies": { - "jest": "^25.5.4", + "jest": "^26.4.2", "prettier": "^2.1.1" }, "dependencies": { - "commander": "^3.0.0", + "commander": "^3.0.2", "glob": "^7.1.2" } -} \ No newline at end of file +} diff --git a/packages/kbn-std/package.json b/packages/kbn-std/package.json index 2cc9fd72082be..a931dd3f3154d 100644 --- a/packages/kbn-std/package.json +++ b/packages/kbn-std/package.json @@ -15,6 +15,6 @@ }, "dependencies": { "@kbn/utility-types": "1.0.0", - "lodash": "^4.17.15" + "lodash": "^4.17.20" } } diff --git a/packages/kbn-std/src/index.ts b/packages/kbn-std/src/index.ts index 8cffcd43d7537..c111428017539 100644 --- a/packages/kbn-std/src/index.ts +++ b/packages/kbn-std/src/index.ts @@ -24,6 +24,7 @@ export { mapToObject } from './map_to_object'; export { merge } from './merge'; export { pick } from './pick'; export { withTimeout } from './promise'; -export { isRelativeUrl, modifyUrl, URLMeaningfulParts, ParsedQuery } from './url'; +export { isRelativeUrl, modifyUrl, getUrlOrigin, URLMeaningfulParts } from './url'; export { unset } from './unset'; export { getFlattenedObject } from './get_flattened_object'; +export * from './rxjs_7'; diff --git a/packages/kbn-std/src/merge.ts b/packages/kbn-std/src/merge.ts index c0de50544a34e..43878c27b1e19 100644 --- a/packages/kbn-std/src/merge.ts +++ b/packages/kbn-std/src/merge.ts @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -import isPlainObject from 'lodash/isPlainObject'; +import { isPlainObject } from 'lodash'; /** * Deeply merges two objects, omitting undefined values, and not deeply merging Arrays. * diff --git a/packages/kbn-std/src/rxjs_7.test.ts b/packages/kbn-std/src/rxjs_7.test.ts new file mode 100644 index 0000000000000..dcc73602613fa --- /dev/null +++ b/packages/kbn-std/src/rxjs_7.test.ts @@ -0,0 +1,93 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import * as Rx from 'rxjs'; + +import { firstValueFrom, lastValueFrom } from './rxjs_7'; + +// create an empty observable that completes with no notifications +// after a delay to ensure helpers aren't checking for the EMPTY constant +function empty() { + return new Rx.Observable((subscriber) => { + setTimeout(() => { + subscriber.complete(); + }, 0); + }); +} + +describe('firstValueFrom()', () => { + it('resolves to the first value from the observable', async () => { + await expect(firstValueFrom(Rx.of(1, 2, 3))).resolves.toBe(1); + }); + + it('rejects if the observable is empty', async () => { + await expect(firstValueFrom(empty())).rejects.toThrowErrorMatchingInlineSnapshot( + `"no elements in sequence"` + ); + }); + + it('does not unsubscribe from the source observable that emits synchronously', async () => { + const values = [1, 2, 3, 4]; + let unsubscribed = false; + const source = new Rx.Observable((subscriber) => { + while (!subscriber.closed && values.length) { + subscriber.next(values.shift()!); + } + unsubscribed = subscriber.closed; + subscriber.complete(); + }); + + await expect(firstValueFrom(source)).resolves.toMatchInlineSnapshot(`1`); + if (unsubscribed) { + throw new Error('expected source to not be unsubscribed'); + } + expect(values).toEqual([]); + }); + + it('unsubscribes from the source observable after first async notification', async () => { + const values = [1, 2, 3, 4]; + let unsubscribed = false; + const source = new Rx.Observable((subscriber) => { + setTimeout(() => { + while (!subscriber.closed) { + subscriber.next(values.shift()!); + } + unsubscribed = subscriber.closed; + }); + }); + + await expect(firstValueFrom(source)).resolves.toMatchInlineSnapshot(`1`); + if (!unsubscribed) { + throw new Error('expected source to be unsubscribed'); + } + expect(values).toEqual([2, 3, 4]); + }); +}); + +describe('lastValueFrom()', () => { + it('resolves to the last value from the observable', async () => { + await expect(lastValueFrom(Rx.of(1, 2, 3))).resolves.toBe(3); + }); + + it('rejects if the observable is empty', async () => { + await expect(lastValueFrom(empty())).rejects.toThrowErrorMatchingInlineSnapshot( + `"no elements in sequence"` + ); + }); +}); diff --git a/packages/kbn-std/src/rxjs_7.ts b/packages/kbn-std/src/rxjs_7.ts new file mode 100644 index 0000000000000..f0a1be9125cc8 --- /dev/null +++ b/packages/kbn-std/src/rxjs_7.ts @@ -0,0 +1,251 @@ +/* eslint-disable @kbn/eslint/require-license-header */ + +/** + * @notice + * + * We include the `firstValueFrom()` and `lastValueFrom()` helpers + * extracted from the v7-beta.7 version of the RxJS library. + * + * Apache License + * Version 2.0, January 2004 + * http://www.apache.org/licenses/ + * + * TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + * + * 1. Definitions. + * + * "License" shall mean the terms and conditions for use, reproduction, + * and distribution as defined by Sections 1 through 9 of this document. + * + * "Licensor" shall mean the copyright owner or entity authorized by + * the copyright owner that is granting the License. + * + * "Legal Entity" shall mean the union of the acting entity and all + * other entities that control, are controlled by, or are under common + * control with that entity. For the purposes of this definition, + * "control" means (i) the power, direct or indirect, to cause the + * direction or management of such entity, whether by contract or + * otherwise, or (ii) ownership of fifty percent (50%) or more of the + * outstanding shares, or (iii) beneficial ownership of such entity. + * + * "You" (or "Your") shall mean an individual or Legal Entity + * exercising permissions granted by this License. + * + * "Source" form shall mean the preferred form for making modifications, + * including but not limited to software source code, documentation + * source, and configuration files. + * + * "Object" form shall mean any form resulting from mechanical + * transformation or translation of a Source form, including but + * not limited to compiled object code, generated documentation, + * and conversions to other media types. + * + * "Work" shall mean the work of authorship, whether in Source or + * Object form, made available under the License, as indicated by a + * copyright notice that is included in or attached to the work + * (an example is provided in the Appendix below). + * + * "Derivative Works" shall mean any work, whether in Source or Object + * form, that is based on (or derived from) the Work and for which the + * editorial revisions, annotations, elaborations, or other modifications + * represent, as a whole, an original work of authorship. For the purposes + * of this License, Derivative Works shall not include works that remain + * separable from, or merely link (or bind by name) to the interfaces of, + * the Work and Derivative Works thereof. + * + * "Contribution" shall mean any work of authorship, including + * the original version of the Work and any modifications or additions + * to that Work or Derivative Works thereof, that is intentionally + * submitted to Licensor for inclusion in the Work by the copyright owner + * or by an individual or Legal Entity authorized to submit on behalf of + * the copyright owner. For the purposes of this definition, "submitted" + * means any form of electronic, verbal, or written communication sent + * to the Licensor or its representatives, including but not limited to + * communication on electronic mailing lists, source code control systems, + * and issue tracking systems that are managed by, or on behalf of, the + * Licensor for the purpose of discussing and improving the Work, but + * excluding communication that is conspicuously marked or otherwise + * designated in writing by the copyright owner as "Not a Contribution." + * + * "Contributor" shall mean Licensor and any individual or Legal Entity + * on behalf of whom a Contribution has been received by Licensor and + * subsequently incorporated within the Work. + * + * 2. Grant of Copyright License. Subject to the terms and conditions of + * this License, each Contributor hereby grants to You a perpetual, + * worldwide, non-exclusive, no-charge, royalty-free, irrevocable + * copyright license to reproduce, prepare Derivative Works of, + * publicly display, publicly perform, sublicense, and distribute the + * Work and such Derivative Works in Source or Object form. + * + * 3. Grant of Patent License. Subject to the terms and conditions of + * this License, each Contributor hereby grants to You a perpetual, + * worldwide, non-exclusive, no-charge, royalty-free, irrevocable + * (except as stated in this section) patent license to make, have made, + * use, offer to sell, sell, import, and otherwise transfer the Work, + * where such license applies only to those patent claims licensable + * by such Contributor that are necessarily infringed by their + * Contribution(s) alone or by combination of their Contribution(s) + * with the Work to which such Contribution(s) was submitted. If You + * institute patent litigation against any entity (including a + * cross-claim or counterclaim in a lawsuit) alleging that the Work + * or a Contribution incorporated within the Work constitutes direct + * or contributory patent infringement, then any patent licenses + * granted to You under this License for that Work shall terminate + * as of the date such litigation is filed. + * + * 4. Redistribution. You may reproduce and distribute copies of the + * Work or Derivative Works thereof in any medium, with or without + * modifications, and in Source or Object form, provided that You + * meet the following conditions: + * + * (a) You must give any other recipients of the Work or + * Derivative Works a copy of this License; and + * + * (b) You must cause any modified files to carry prominent notices + * stating that You changed the files; and + * + * (c) You must retain, in the Source form of any Derivative Works + * that You distribute, all copyright, patent, trademark, and + * attribution notices from the Source form of the Work, + * excluding those notices that do not pertain to any part of + * the Derivative Works; and + * + * (d) If the Work includes a "NOTICE" text file as part of its + * distribution, then any Derivative Works that You distribute must + * include a readable copy of the attribution notices contained + * within such NOTICE file, excluding those notices that do not + * pertain to any part of the Derivative Works, in at least one + * of the following places: within a NOTICE text file distributed + * as part of the Derivative Works; within the Source form or + * documentation, if provided along with the Derivative Works; or, + * within a display generated by the Derivative Works, if and + * wherever such third-party notices normally appear. The contents + * of the NOTICE file are for informational purposes only and + * do not modify the License. You may add Your own attribution + * notices within Derivative Works that You distribute, alongside + * or as an addendum to the NOTICE text from the Work, provided + * that such additional attribution notices cannot be construed + * as modifying the License. + * + * You may add Your own copyright statement to Your modifications and + * may provide additional or different license terms and conditions + * for use, reproduction, or distribution of Your modifications, or + * for any such Derivative Works as a whole, provided Your use, + * reproduction, and distribution of the Work otherwise complies with + * the conditions stated in this License. + * + * 5. Submission of Contributions. Unless You explicitly state otherwise, + * any Contribution intentionally submitted for inclusion in the Work + * by You to the Licensor shall be under the terms and conditions of + * this License, without any additional terms or conditions. + * Notwithstanding the above, nothing herein shall supersede or modify + * the terms of any separate license agreement you may have executed + * with Licensor regarding such Contributions. + * + * 6. Trademarks. This License does not grant permission to use the trade + * names, trademarks, service marks, or product names of the Licensor, + * except as required for reasonable and customary use in describing the + * origin of the Work and reproducing the content of the NOTICE file. + * + * 7. Disclaimer of Warranty. Unless required by applicable law or + * agreed to in writing, Licensor provides the Work (and each + * Contributor provides its Contributions) on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied, including, without limitation, any warranties or conditions + * of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + * PARTICULAR PURPOSE. You are solely responsible for determining the + * appropriateness of using or redistributing the Work and assume any + * risks associated with Your exercise of permissions under this License. + * + * 8. Limitation of Liability. In no event and under no legal theory, + * whether in tort (including negligence), contract, or otherwise, + * unless required by applicable law (such as deliberate and grossly + * negligent acts) or agreed to in writing, shall any Contributor be + * liable to You for damages, including any direct, indirect, special, + * incidental, or consequential damages of any character arising as a + * result of this License or out of the use or inability to use the + * Work (including but not limited to damages for loss of goodwill, + * work stoppage, computer failure or malfunction, or any and all + * other commercial damages or losses), even if such Contributor + * has been advised of the possibility of such damages. + * + * 9. Accepting Warranty or Additional Liability. While redistributing + * the Work or Derivative Works thereof, You may choose to offer, + * and charge a fee for, acceptance of support, warranty, indemnity, + * or other liability obligations and/or rights consistent with this + * License. However, in accepting such obligations, You may act only + * on Your own behalf and on Your sole responsibility, not on behalf + * of any other Contributor, and only if You agree to indemnify, + * defend, and hold each Contributor harmless for any liability + * incurred by, or claims asserted against, such Contributor by reason + * of your accepting any such warranty or additional liability. + * + * END OF TERMS AND CONDITIONS + * + * APPENDIX: How to apply the Apache License to your work. + * + * To apply the Apache License to your work, attach the following + * boilerplate notice, with the fields enclosed by brackets "[]" + * replaced with your own identifying information. (Don't include + * the brackets!) The text should be enclosed in the appropriate + * comment syntax for the file format. We also recommend that a + * file or class name and description of purpose be included on the + * same "printed page" as the copyright notice for easier + * identification within third-party archives. + * + * Copyright (c) 2015-2018 Google, Inc., Netflix, Inc., Microsoft Corp. and contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Observable, Subscription, EmptyError } from 'rxjs'; + +export function firstValueFrom(source: Observable) { + return new Promise((resolve, reject) => { + const subs = new Subscription(); + subs.add( + source.subscribe({ + next: (value) => { + resolve(value); + subs.unsubscribe(); + }, + error: reject, + complete: () => { + reject(new EmptyError()); + }, + }) + ); + }); +} + +export function lastValueFrom(source: Observable) { + return new Promise((resolve, reject) => { + let _hasValue = false; + let _value: T; + source.subscribe({ + next: (value) => { + _value = value; + _hasValue = true; + }, + error: reject, + complete: () => { + if (_hasValue) { + resolve(_value); + } else { + reject(new EmptyError()); + } + }, + }); + }); +} diff --git a/packages/kbn-std/src/url.test.ts b/packages/kbn-std/src/url.test.ts index 7e9b6adfd3f49..4d5c5a1808c55 100644 --- a/packages/kbn-std/src/url.test.ts +++ b/packages/kbn-std/src/url.test.ts @@ -17,7 +17,7 @@ * under the License. */ -import { modifyUrl, isRelativeUrl } from './url'; +import { modifyUrl, isRelativeUrl, getUrlOrigin } from './url'; describe('modifyUrl()', () => { test('throws an error with invalid input', () => { @@ -83,3 +83,27 @@ describe('isRelativeUrl()', () => { expect(isRelativeUrl(' //evil.com')).toBe(false); }); }); + +describe('getOrigin', () => { + describe('when passing an absolute url', () => { + it('return origin without port when the url does not have a port', () => { + expect(getUrlOrigin('https://example.com/file/to/path?example')).toEqual( + 'https://example.com' + ); + }); + it('return origin with port when the url does have a port', () => { + expect(getUrlOrigin('http://example.com:80/path/to/file')).toEqual('http://example.com:80'); + }); + }); + describe('when passing a non absolute url', () => { + it('returns null for relative url', () => { + expect(getUrlOrigin('./path/to/file')).toBeNull(); + }); + it('returns null for absolute path', () => { + expect(getUrlOrigin('/path/to/file')).toBeNull(); + }); + it('returns null for empty url', () => { + expect(getUrlOrigin('')).toBeNull(); + }); + }); +}); diff --git a/packages/kbn-std/src/url.ts b/packages/kbn-std/src/url.ts index 7a0f08130816d..745ed05751b10 100644 --- a/packages/kbn-std/src/url.ts +++ b/packages/kbn-std/src/url.ts @@ -18,11 +18,7 @@ */ import { format as formatUrl, parse as parseUrl, UrlObject } from 'url'; - -// duplicate type from 'query-string' to avoid adding the d.ts file to all packages depending on kbn-std -export interface ParsedQuery { - [key: string]: T | T[] | null | undefined; -} +import type { ParsedQuery } from 'query-string'; /** * We define our own typings because the current version of @types/node @@ -129,3 +125,14 @@ export function isRelativeUrl(candidatePath: string) { } return true; } + +/** + * Returns the origin (protocol + host + port) from given `url` if `url` is a valid absolute url, or null otherwise + */ +export function getUrlOrigin(url: string): string | null { + const obj = parseUrl(url); + if (!obj.protocol && !obj.hostname) { + return null; + } + return `${obj.protocol}//${obj.hostname}${obj.port ? `:${obj.port}` : ''}`; +} diff --git a/packages/kbn-storybook/README.md b/packages/kbn-storybook/README.md index c9195f41ebf26..eea8912c8715e 100644 --- a/packages/kbn-storybook/README.md +++ b/packages/kbn-storybook/README.md @@ -2,32 +2,40 @@ This package provides ability to add [Storybook](https://storybook.js.org/) to any Kibana plugin. -- [Setup Instructions](#setup-instructions) - +- [Kibana Storybook](#kibana-storybook) + - [Setup Instructions](#setup-instructions) + - [Customizing configuration](#customizing-configuration) ## Setup Instructions -1. Add `storybook.js` launcher file to your plugin. For example, create a file at - `src/plugins//scripts/storybook.js`, with the following contents: - - ```js - import { join } from 'path'; - - // eslint-disable-next-line - require('@kbn/storybook').runStorybookCli({ - name: '', - storyGlobs: [join(__dirname, '..', 'public', 'components', '**', '*.examples.tsx')], - }); - ``` -2. Add your plugin alias to `src/dev/storybook/aliases.ts` config. -3. Create sample Storybook stories. For example, in your plugin create create a file at - `src/plugins//public/components/hello_world/__examples__/hello_world.examples.tsx` with - the following contents: - - ```jsx - import * as React from 'react'; - import { storiesOf } from '@storybook/react'; - - storiesOf('Hello world', module).add('default', () =>
Hello world!
); - ``` -4. Launch Storybook with `yarn storybook `. +- Add a `.storybook/main.js` configuration file to your plugin. For example, create a file at + `src/plugins//.storybook/main.js`, with the following contents: + + ```js + module.exports = require('@kbn/storybook').defaultConfig; + ``` + +- Add your plugin alias to `src/dev/storybook/aliases.ts` config. +- Create sample Storybook stories. For example, in your plugin create a file at + `src/plugins//public/components/hello_world/hello_world.stories.tsx` with + the following [Component Story Format](https://storybook.js.org/docs/react/api/csf) contents: + + ```jsx + import { MyComponent } from './my_component'; + + export default { + component: MyComponent, + title: 'Path/In/Side/Navigation/ToComponent', + }; + + export function Example() { + return ; + } + ``` + +- Launch Storybook with `yarn storybook `, or build a static site with `yarn storybook --site `. + +## Customizing configuration + +The `defaultConfig` object provided by the @kbn/storybook package should be all you need to get running, but you can +override this in your .storybook/main.js. Using [Storybook's configuration options](https://storybook.js.org/docs/react/configure/overview). diff --git a/packages/kbn-storybook/index.js b/packages/kbn-storybook/index.js deleted file mode 100644 index 77d457f2bb3c0..0000000000000 --- a/packages/kbn-storybook/index.js +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -const fs = require('fs'); -const { join } = require('path'); -const Rx = require('rxjs'); -const { first } = require('rxjs/operators'); -const storybook = require('@storybook/react/standalone'); -const { run } = require('@kbn/dev-utils'); -const { generateStorybookEntry } = require('./lib/storybook_entry'); -const { ASSET_DIR, CURRENT_CONFIG } = require('./lib/constants'); -const { buildDll } = require('./lib/dll'); - -exports.runStorybookCli = (config) => { - const { name, storyGlobs } = config; - run( - async ({ flags, log, procRunner }) => { - log.debug('Global config:\n', require('./lib/constants')); - - const currentConfig = JSON.stringify(config, null, 2); - const currentConfigDir = join(CURRENT_CONFIG, '..'); - await fs.promises.mkdir(currentConfigDir, { recursive: true }); - log.debug('Writing currentConfig:\n', CURRENT_CONFIG + '\n', currentConfig); - await fs.promises.writeFile(CURRENT_CONFIG, `exports.currentConfig = ${currentConfig};`); - - await buildDll({ - rebuildDll: flags.rebuildDll, - log, - procRunner, - }); - - const subj = new Rx.ReplaySubject(1); - generateStorybookEntry({ log, storyGlobs }).subscribe(subj); - - await subj.pipe(first()).toPromise(); - - await Promise.all([ - // route errors - subj.toPromise(), - - new Promise(async () => { - // storybook never completes, so neither will this promise - const configDir = join(__dirname, 'storybook_config'); - log.debug('Config dir:', configDir); - - const config = { - mode: flags.site ? 'static' : 'dev', - port: 9001, - configDir, - }; - if (flags.site) { - config.outputDir = join(ASSET_DIR, name); - } - - await storybook(config); - - // Line is only reached when building the static version - if (flags.site) process.exit(); - }), - ]); - }, - { - flags: { - boolean: ['rebuildDll', 'site'], - }, - description: ` - Run the storybook examples for ${name} - `, - } - ); -}; diff --git a/packages/kbn-storybook/index.ts b/packages/kbn-storybook/index.ts new file mode 100644 index 0000000000000..a0c944f9a6e28 --- /dev/null +++ b/packages/kbn-storybook/index.ts @@ -0,0 +1,21 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export { defaultConfig } from './lib/default_config'; +export { runStorybookCli } from './lib/run_storybook_cli'; diff --git a/packages/kbn-storybook/lib/constants.js b/packages/kbn-storybook/lib/constants.js deleted file mode 100644 index 4d8ca0adbfe17..0000000000000 --- a/packages/kbn-storybook/lib/constants.js +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -const { resolve } = require('path'); -const { REPO_ROOT } = require('@kbn/utils'); - -exports.ASSET_DIR = resolve(REPO_ROOT, 'built_assets/storybook'); -exports.CURRENT_CONFIG = resolve(exports.ASSET_DIR, 'current.config.js'); -exports.STORY_ENTRY_PATH = resolve(exports.ASSET_DIR, 'stories.entry.js'); -exports.DLL_DIST_DIR = resolve(exports.ASSET_DIR, 'dll'); -exports.DLL_NAME = 'storybook_dll'; diff --git a/packages/kbn-storybook/lib/constants.ts b/packages/kbn-storybook/lib/constants.ts new file mode 100644 index 0000000000000..7ca0ff349af97 --- /dev/null +++ b/packages/kbn-storybook/lib/constants.ts @@ -0,0 +1,24 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { resolve } from 'path'; +import { REPO_ROOT as KIBANA_ROOT } from '@kbn/dev-utils'; + +export const REPO_ROOT = KIBANA_ROOT; +export const ASSET_DIR = resolve(KIBANA_ROOT, 'built_assets/storybook'); diff --git a/packages/kbn-storybook/lib/default_config.ts b/packages/kbn-storybook/lib/default_config.ts new file mode 100644 index 0000000000000..1fad9e2a3e087 --- /dev/null +++ b/packages/kbn-storybook/lib/default_config.ts @@ -0,0 +1,28 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { StorybookConfig } from '@storybook/core/types'; + +export const defaultConfig: StorybookConfig = { + addons: ['@kbn/storybook/preset', '@storybook/addon-knobs', '@storybook/addon-essentials'], + stories: ['../**/*.stories.tsx'], + typescript: { + reactDocgen: false, + }, +}; diff --git a/packages/kbn-storybook/lib/dll.js b/packages/kbn-storybook/lib/dll.js deleted file mode 100644 index 55bc8e43a02ec..0000000000000 --- a/packages/kbn-storybook/lib/dll.js +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -const { resolve } = require('path'); -const { existsSync } = require('fs'); - -const { REPO_ROOT } = require('@kbn/utils'); -const { DLL_DIST_DIR } = require('./constants'); - -exports.buildDll = async ({ rebuildDll, log, procRunner }) => { - if (rebuildDll) { - log.info('rebuilding dll'); - } else if (!existsSync(resolve(DLL_DIST_DIR, 'dll.js'))) { - log.info('dll missing, rebuilding'); - } else { - log.info('dll exists'); - return; - } - - await procRunner.run('build dll ', { - cmd: require.resolve('webpack/bin/webpack'), - args: ['--config', require.resolve('./webpack.dll.config.js')], - cwd: REPO_ROOT, - wait: true, - }); -}; diff --git a/packages/kbn-storybook/lib/register.ts b/packages/kbn-storybook/lib/register.ts new file mode 100644 index 0000000000000..5121b6f614902 --- /dev/null +++ b/packages/kbn-storybook/lib/register.ts @@ -0,0 +1,35 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { addons } from '@storybook/addons'; +import { create } from '@storybook/theming'; + +// This configures the "Manager", or main outer view of Storybook. It is an +// addon that's loaded by the `managerEntries` part of the preset in ../preset.js. +addons.setConfig({ + theme: create({ + base: 'light', + brandTitle: 'Kibana Storybook', + brandUrl: 'https://github.com/elastic/kibana/tree/master/packages/kbn-storybook', + }), + showPanel: false, + isFullscreen: false, + panelPosition: 'bottom', + isToolshown: true, +}); diff --git a/packages/kbn-storybook/lib/run_storybook_cli.ts b/packages/kbn-storybook/lib/run_storybook_cli.ts new file mode 100644 index 0000000000000..3c4cdbf3dcf84 --- /dev/null +++ b/packages/kbn-storybook/lib/run_storybook_cli.ts @@ -0,0 +1,75 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { join } from 'path'; +import { logger } from '@storybook/node-logger'; +import buildStandalone from '@storybook/react/standalone'; +import { Flags, run } from '@kbn/dev-utils'; +import { distDir } from '@kbn/ui-shared-deps'; +import * as constants from './constants'; + +// Convert the flags to a Storybook loglevel +function getLogLevelFromFlags(flags: Flags) { + if (flags.debug) { + return 'silly'; + } + if (flags.verbose) { + return 'verbose'; + } + if (flags.quiet) { + return 'warn'; + } + if (flags.silent) { + return 'silent'; + } + return 'info'; +} + +export function runStorybookCli({ configDir, name }: { configDir: string; name: string }) { + run( + async ({ flags, log }) => { + log.debug('Global config:\n', constants); + + const staticDir = [distDir]; + const config: Record = { + configDir, + mode: flags.site ? 'static' : 'dev', + port: 9001, + staticDir, + }; + if (flags.site) { + config.outputDir = join(constants.ASSET_DIR, name); + } + + logger.setLevel(getLogLevelFromFlags(flags)); + await buildStandalone(config); + + // Line is only reached when building the static version + if (flags.site) process.exit(); + }, + { + flags: { + boolean: ['site'], + }, + description: ` + Run the storybook examples for ${name} + `, + } + ); +} diff --git a/packages/kbn-storybook/lib/storybook_entry.js b/packages/kbn-storybook/lib/storybook_entry.js deleted file mode 100644 index fc970b1ff9d2a..0000000000000 --- a/packages/kbn-storybook/lib/storybook_entry.js +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -const { resolve, relative, dirname } = require('path'); -const Fs = require('fs'); -const Rx = require('rxjs'); -const { mergeMap, map, debounceTime } = require('rxjs/operators'); -const normalize = require('normalize-path'); -const { promisify } = require('util'); - -const watch = require('glob-watcher'); -const mkdirp = require('mkdirp'); // eslint-disable-line -const glob = require('fast-glob'); -const { REPO_ROOT } = require('@kbn/utils'); - -const mkdirpAsync = promisify(mkdirp); -const writeFileAsync = promisify(Fs.writeFile); - -const { STORY_ENTRY_PATH } = require('./constants'); -const STORE_ENTRY_DIR = dirname(STORY_ENTRY_PATH); - -exports.generateStorybookEntry = ({ log, storyGlobs }) => { - const globs = [...storyGlobs]; - log.info('Storybook globs:\n', globs); - const norm = (p) => normalize(relative(STORE_ENTRY_DIR, p)); - - return Rx.defer(() => - glob(globs, { - absolute: true, - cwd: REPO_ROOT, - onlyFiles: true, - }) - ).pipe( - map((paths) => { - log.info('Discovered Storybook entry points:\n', paths); - return new Set(paths.map(norm)); - }), - mergeMap( - (paths) => - new Rx.Observable((observer) => { - observer.next(paths); - - const chokidar = watch(globs, { cwd: REPO_ROOT }) - .on('add', (path) => { - observer.next(paths.add(norm(resolve(REPO_ROOT, path)))); - }) - .on('unlink', (path) => { - observer.next(paths.delete(norm(resolve(REPO_ROOT, path)))); - }); - - return () => { - chokidar.close(); - }; - }) - ), - debounceTime(200), - mergeMap(async (paths, i) => { - await mkdirpAsync(STORE_ENTRY_DIR); - - let content = ''; - for (const path of paths) { - content += `require('${path}');\n`; - } - - await writeFileAsync(STORY_ENTRY_PATH, content); - - if (i === 0) { - log.info('%d paths written to entry file', paths.size); - } else { - log.info('entry file updated'); - } - }) - ); -}; diff --git a/packages/kbn-storybook/lib/templates/index.ejs b/packages/kbn-storybook/lib/templates/index.ejs new file mode 100644 index 0000000000000..a4f8204c95d7a --- /dev/null +++ b/packages/kbn-storybook/lib/templates/index.ejs @@ -0,0 +1,59 @@ + + + + + + <%= options.title || 'Storybook'%> + + <% if (files.favicon) { %> + + <% } %> + + + + + + + + + + + + <% if (typeof headHtmlSnippet !== 'undefined') { %> <%= headHtmlSnippet %> <% } %> <% + files.css.forEach(file => { %> + + <% }); %> + + + + + <% if (typeof bodyHtmlSnippet !== 'undefined') { %> <%= bodyHtmlSnippet %> <% } %> + +
+
+ + <% if (typeof globals !== 'undefined' && Object.keys(globals).length) { %> + + <% } %> <% dlls.forEach(file => { %> + + <% }); %> <% files.js.forEach(file => { %> + + <% }); %> + + diff --git a/packages/kbn-storybook/lib/webpack.dll.config.js b/packages/kbn-storybook/lib/webpack.dll.config.js deleted file mode 100644 index 6e3b4d41bd7f0..0000000000000 --- a/packages/kbn-storybook/lib/webpack.dll.config.js +++ /dev/null @@ -1,131 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -const webpack = require('webpack'); -const path = require('path'); -const MiniCssExtractPlugin = require('mini-css-extract-plugin'); -const { REPO_ROOT } = require('@kbn/utils'); - -const { DLL_NAME, DLL_DIST_DIR } = require('./constants'); - -// This is the Webpack config for the DLL of CSS and JS assets that are -// not expected to change during development. This saves compile and run -// times considerably. -module.exports = { - context: REPO_ROOT, - mode: 'development', - - // This is a (potentially growing) list of modules that can be safely - // included in the DLL. Only add to this list modules or other code - // which Storybook stories and their components would require, but don't - // change during development. - entry: [ - '@elastic/eui/dist/eui_theme_light.css', - '@kbn/ui-framework/dist/kui_light.css', - '@storybook/addon-info', - '@storybook/addon-knobs', - '@storybook/addon-knobs/react', - '@storybook/addon-knobs/register', - '@storybook/addon-options', - '@storybook/addon-options/register', - '@storybook/core', - '@storybook/core/dist/server/common/polyfills.js', - '@storybook/react', - '@storybook/theming', - 'angular-mocks', - 'angular', - 'brace', - 'chroma-js', - 'highlight.js', - 'html-entities', - 'jquery', - 'lodash', - 'markdown-it', - 'mocha', - 'prop-types', - 'react-ace', - 'react-beautiful-dnd', - 'react-dom', - 'react-focus-lock', - 'react-markdown', - 'react-resize-detector', - 'react-virtualized', - 'react', - 'recompose', - 'redux-actions', - 'remark-parse', - 'rxjs', - 'sinon', - 'tinycolor2', - ], - plugins: [ - // Produce the DLL and its manifest - new webpack.DllPlugin({ - name: DLL_NAME, - path: path.resolve(DLL_DIST_DIR, 'manifest.json'), - }), - // Produce the DLL CSS file - new MiniCssExtractPlugin({ - filename: 'dll.css', - }), - ], - // Output the DLL JS file - output: { - path: DLL_DIST_DIR, - filename: 'dll.js', - library: DLL_NAME, - }, - // Include a require alias for legacy UI code and styles - resolve: { - alias: { - ui: path.resolve(REPO_ROOT, 'src/legacy/ui/public'), - }, - mainFields: ['browser', 'main'], - }, - module: { - rules: [ - { - test: /\.css$/, - use: [ - { - loader: MiniCssExtractPlugin.loader, - options: {}, - }, - { loader: 'css-loader' }, - { - loader: 'string-replace-loader', - options: { - search: '__REPLACE_WITH_PUBLIC_PATH__', - replace: '/', - flags: 'g', - }, - }, - ], - }, - { - test: /\.(woff|woff2|ttf|eot|svg|ico)(\?|$)/, - loader: 'file-loader', - }, - ], - }, - node: { - fs: 'empty', - child_process: 'empty', - }, -}; diff --git a/packages/kbn-storybook/package.json b/packages/kbn-storybook/package.json index 5271ddb96d842..58359159e950d 100644 --- a/packages/kbn-storybook/package.json +++ b/packages/kbn-storybook/package.json @@ -3,18 +3,21 @@ "version": "1.0.0", "private": true, "license": "Apache-2.0", + "main": "./target/index.js", "dependencies": { - "@kbn/babel-preset": "1.0.0", "@kbn/dev-utils": "1.0.0", + "@storybook/addon-actions": "^6.0.16", + "@storybook/addon-essentials": "^6.0.16", + "@storybook/addon-knobs": "^6.0.16", + "@storybook/addon-storyshots": "^6.0.16", + "@storybook/core": "^6.0.16", + "@storybook/react": "^6.0.16", + "@storybook/theming": "^6.0.16", + "@types/loader-utils": "^1.1.3", + "@types/webpack": "^4.41.3", + "@types/webpack-env": "^1.15.2", + "@types/webpack-merge": "^4.1.5", "@kbn/utils": "1.0.0", - "@storybook/addon-actions": "^5.3.19", - "@storybook/addon-console": "^1.2.1", - "@storybook/addon-info": "^5.3.19", - "@storybook/addon-knobs": "^5.3.19", - "@storybook/addon-options": "^5.3.19", - "@storybook/addon-storyshots": "^5.3.19", - "@storybook/react": "^5.3.19", - "@storybook/theming": "^5.3.19", "babel-loader": "^8.0.6", "copy-webpack-plugin": "^6.0.2", "fast-glob": "2.2.7", @@ -22,12 +25,17 @@ "jest-specific-snapshot": "2.0.0", "jest-styled-components": "^7.0.2", "mkdirp": "0.5.1", - "mini-css-extract-plugin": "0.7.0", - "normalize-path": "3.0.0", - "react-docgen-typescript-loader": "3.1.0", - "rxjs": "6.5.5", + "mini-css-extract-plugin": "0.8.0", + "normalize-path": "^3.0.0", + "react-docgen-typescript-loader": "^3.1.1", + "rxjs": "^6.5.5", "serve-static": "1.14.1", "styled-components": "^5.1.0", "webpack": "^4.41.5" + }, + "scripts": { + "build": "tsc", + "kbn:bootstrap": "yarn build", + "watch": "yarn build --watch" } -} \ No newline at end of file +} diff --git a/packages/kbn-storybook/preset.js b/packages/kbn-storybook/preset.js new file mode 100644 index 0000000000000..8c17f78e208d8 --- /dev/null +++ b/packages/kbn-storybook/preset.js @@ -0,0 +1,29 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +const webpackConfig = require('./target/webpack.config').default; + +module.exports = { + managerEntries: (entry = []) => { + return [...entry, require.resolve('./target/lib/register')]; + }, + webpackFinal: (config) => { + return webpackConfig({ config }); + }, +}; diff --git a/packages/kbn-storybook/storybook_config/addons.js b/packages/kbn-storybook/storybook_config/addons.js deleted file mode 100644 index f439d1d8892f8..0000000000000 --- a/packages/kbn-storybook/storybook_config/addons.js +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import '@storybook/addon-options/register'; -import '@storybook/addon-actions/register'; -import '@storybook/addon-knobs/register'; -import '@storybook/addon-console'; diff --git a/packages/kbn-storybook/storybook_config/config.js b/packages/kbn-storybook/storybook_config/config.js deleted file mode 100644 index d97bd3f7c2dcc..0000000000000 --- a/packages/kbn-storybook/storybook_config/config.js +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { configure, addDecorator, addParameters } from '@storybook/react'; -import { withKnobs } from '@storybook/addon-knobs/react'; -import { withInfo } from '@storybook/addon-info'; -import { create } from '@storybook/theming'; - -// If we're running Storyshots, be sure to register the require context hook. -// Otherwise, add the other decorators. -if (process.env.NODE_ENV === 'test') { - // eslint-disable-next-line - require('babel-plugin-require-context-hook/register')(); -} else { - // Customize the info for each story. - addDecorator( - withInfo({ - inline: true, - styles: { - infoBody: { - margin: 20, - }, - infoStory: { - margin: '40px 60px', - }, - }, - }) - ); - - // Add optional knobs to customize each story. - addDecorator(withKnobs); -} - -// Set up the Storybook environment with custom settings. -addParameters({ - options: { - theme: create({ - base: 'light', - brandTitle: 'Kibana Storybook', - brandUrl: 'https://github.com/elastic/kibana/tree/master/packages/kbn-storybook', - }), - showPanel: false, - isFullscreen: false, - panelPosition: 'bottom', - isToolshown: true, - }, -}); - -configure(() => { - // eslint-disable-next-line - require('../../../built_assets/storybook/stories.entry.js'); -}, module); diff --git a/packages/kbn-storybook/storybook_config/middleware.js b/packages/kbn-storybook/storybook_config/middleware.js deleted file mode 100644 index 9410bb66030d9..0000000000000 --- a/packages/kbn-storybook/storybook_config/middleware.js +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -const serve = require('serve-static'); -const path = require('path'); - -// Extend the Storybook Middleware to include a route to access Legacy UI assets -module.exports = function (router) { - router.get('/ui', serve(path.resolve(__dirname, '../../../src/core/server/core_app/assets'))); -}; diff --git a/packages/kbn-storybook/storybook_config/mocks/absolute_to_parsed_url.js b/packages/kbn-storybook/storybook_config/mocks/absolute_to_parsed_url.js deleted file mode 100644 index 65a27b095f84e..0000000000000 --- a/packages/kbn-storybook/storybook_config/mocks/absolute_to_parsed_url.js +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -export const absoluteToParsedUrl = () => { - getAbsoluteUrl: () => - 'http://localhost:5601/kbp/app/canvas#/workpad/workpad-24d56dad-ae70-42b8-9ef1-c5350ecd426c/page/1'; -}; // noop diff --git a/packages/kbn-storybook/storybook_config/mocks/noop.js b/packages/kbn-storybook/storybook_config/mocks/noop.js deleted file mode 100755 index e78d222eaa560..0000000000000 --- a/packages/kbn-storybook/storybook_config/mocks/noop.js +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -export default function () {} diff --git a/packages/kbn-storybook/storybook_config/mocks/state_store.js b/packages/kbn-storybook/storybook_config/mocks/state_store.js deleted file mode 100644 index 11bdf6632321d..0000000000000 --- a/packages/kbn-storybook/storybook_config/mocks/state_store.js +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -export function getState() { - return { - assets: { - yay: { value: 'here is your image' }, - }, - }; -} diff --git a/packages/kbn-storybook/storybook_config/mocks/ui_storage.js b/packages/kbn-storybook/storybook_config/mocks/ui_storage.js deleted file mode 100644 index 4bd8cdeddfc22..0000000000000 --- a/packages/kbn-storybook/storybook_config/mocks/ui_storage.js +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -export class Storage { - get(key) { - return this[key]; - } - - set(key, value) { - this[key] = value; - } -} diff --git a/packages/kbn-storybook/storybook_config/preview-head.html b/packages/kbn-storybook/storybook_config/preview-head.html deleted file mode 100644 index 16754ad550da0..0000000000000 --- a/packages/kbn-storybook/storybook_config/preview-head.html +++ /dev/null @@ -1,6 +0,0 @@ - - - diff --git a/packages/kbn-storybook/storybook_config/webpack.config.js b/packages/kbn-storybook/storybook_config/webpack.config.js deleted file mode 100644 index 60b6b6add66d1..0000000000000 --- a/packages/kbn-storybook/storybook_config/webpack.config.js +++ /dev/null @@ -1,147 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -const { resolve } = require('path'); -const webpack = require('webpack'); -const webpackMerge = require('webpack-merge'); -const { stringifyRequest } = require('loader-utils'); -const CopyWebpackPlugin = require('copy-webpack-plugin'); -const { REPO_ROOT } = require('@kbn/utils'); -const { DLL_DIST_DIR } = require('../lib/constants'); -// eslint-disable-next-line import/no-unresolved -const { currentConfig } = require('../../../built_assets/storybook/current.config'); - -// Extend the Storybook Webpack config with some customizations -module.exports = async ({ config: storybookConfig }) => { - let config = { - module: { - rules: [ - // Include the React preset from Kibana for JS(X) and TS(X) - { - test: /\.(j|t)sx?$/, - exclude: /node_modules/, - loaders: 'babel-loader', - options: { - presets: [require.resolve('@kbn/babel-preset/webpack_preset')], - }, - }, - { - test: /\.(html|md|txt|tmpl)$/, - use: { - loader: 'raw-loader', - }, - }, - // Parse props data for .tsx files - // This is notoriously slow, and is making Storybook unusable. Disabling for now. - // See: https://github.com/storybookjs/storybook/issues/7998 - // - // { - // test: /\.tsx$/, - // // Exclude example files, as we don't display props info for them - // exclude: /\.stories.tsx$/, - // use: [ - // // Parse TS comments to create Props tables in the UI - // require.resolve('react-docgen-typescript-loader'), - // ], - // }, - { - test: /\.scss$/, - exclude: /\.module.(s(a|c)ss)$/, - use: [ - { loader: 'style-loader' }, - { loader: 'css-loader', options: { importLoaders: 2 } }, - { - loader: 'postcss-loader', - options: { - config: { - path: require.resolve('@kbn/optimizer/postcss.config.js'), - }, - }, - }, - { - loader: 'sass-loader', - options: { - prependData(loaderContext) { - return `@import ${stringifyRequest( - loaderContext, - resolve(REPO_ROOT, 'src/core/public/core_app/styles/_globals_v7light.scss') - )};\n`; - }, - sassOptions: { - includePaths: [resolve(REPO_ROOT, 'node_modules')], - }, - }, - }, - ], - }, - ], - }, - plugins: [ - // Reference the built DLL file of static(ish) dependencies, which are removed - // during kbn:bootstrap and rebuilt if missing. - new webpack.DllReferencePlugin({ - manifest: resolve(DLL_DIST_DIR, 'manifest.json'), - context: REPO_ROOT, - }), - // Copy the DLL files to the Webpack build for use in the Storybook UI - - new CopyWebpackPlugin({ - patterns: [ - { - from: resolve(DLL_DIST_DIR, 'dll.js'), - to: 'dll.js', - }, - { - from: resolve(DLL_DIST_DIR, 'dll.css'), - to: 'dll.css', - }, - ], - }), - ], - resolve: { - // Tell Webpack about the ts/x extensions - extensions: ['.ts', '.tsx', '.scss'], - alias: { - core_app_image_assets: resolve(REPO_ROOT, 'src/core/public/core_app/images'), - }, - }, - }; - - // Find and alter the CSS rule to replace the Kibana public path string with a path - // to the route we've added in middleware.js - const cssRule = storybookConfig.module.rules.find((rule) => rule.test.source.includes('.css$')); - cssRule.use.push({ - loader: 'string-replace-loader', - options: { - search: '__REPLACE_WITH_PUBLIC_PATH__', - replace: '/', - flags: 'g', - }, - }); - - config = webpackMerge(storybookConfig, config); - - // Load custom Webpack config specified by a plugin. - if (currentConfig.webpackHook) { - // eslint-disable-next-line import/no-dynamic-require - return await require(currentConfig.webpackHook)({ config }); - } - - return config; -}; diff --git a/packages/kbn-storybook/tsconfig.json b/packages/kbn-storybook/tsconfig.json new file mode 100644 index 0000000000000..814a3963c9f49 --- /dev/null +++ b/packages/kbn-storybook/tsconfig.json @@ -0,0 +1,9 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "declaration": true, + "outDir": "target", + "skipLibCheck": true + }, + "include": ["*.ts", "lib/*.ts"] +} diff --git a/packages/kbn-storybook/typings.d.ts b/packages/kbn-storybook/typings.d.ts new file mode 100644 index 0000000000000..a20af34a0eb06 --- /dev/null +++ b/packages/kbn-storybook/typings.d.ts @@ -0,0 +1,21 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +// Storybook react doesn't declare this in its typings, but it's there. +declare module '@storybook/react/standalone'; diff --git a/packages/kbn-storybook/webpack.config.ts b/packages/kbn-storybook/webpack.config.ts new file mode 100644 index 0000000000000..84f8cfaefd669 --- /dev/null +++ b/packages/kbn-storybook/webpack.config.ts @@ -0,0 +1,104 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { resolve } from 'path'; +import { stringifyRequest } from 'loader-utils'; +import { Configuration, Stats } from 'webpack'; +import webpackMerge from 'webpack-merge'; +import { externals } from '@kbn/ui-shared-deps'; +import { REPO_ROOT } from './lib/constants'; + +const stats = { + ...Stats.presetToOptions('minimal'), + colors: true, + errorDetails: true, + errors: true, + moduleTrace: true, + warningsFilter: /(export .* was not found in)|(entrypoint size limit)/, +}; + +// Extend the Storybook Webpack config with some customizations +/* eslint-disable import/no-default-export */ +export default function ({ config: storybookConfig }: { config: Configuration }) { + const config = { + devServer: { + stats, + }, + externals, + module: { + rules: [ + { + test: /\.(html|md|txt|tmpl)$/, + use: { + loader: 'raw-loader', + }, + }, + { + test: /\.scss$/, + exclude: /\.module.(s(a|c)ss)$/, + use: [ + { loader: 'style-loader' }, + { loader: 'css-loader', options: { importLoaders: 2 } }, + { + loader: 'postcss-loader', + options: { + config: { + path: require.resolve('@kbn/optimizer/postcss.config.js'), + }, + }, + }, + { + loader: 'sass-loader', + options: { + prependData(loaderContext: any) { + return `@import ${stringifyRequest( + loaderContext, + resolve(REPO_ROOT, 'src/core/public/core_app/styles/_globals_v7light.scss') + )};\n`; + }, + sassOptions: { + includePaths: [resolve(REPO_ROOT, 'node_modules')], + }, + }, + }, + ], + }, + ], + }, + resolve: { + // Tell Webpack about the scss extension + extensions: ['.scss'], + alias: { + core_app_image_assets: resolve(REPO_ROOT, 'src/core/public/core_app/images'), + }, + }, + stats, + }; + + // This is the hacky part. We find something that looks like the + // HtmlWebpackPlugin and mutate its `options.template` to point at our + // revised template. + const htmlWebpackPlugin: any = (storybookConfig.plugins || []).find((plugin: any) => { + return plugin.options && typeof plugin.options.template === 'string'; + }); + if (htmlWebpackPlugin) { + htmlWebpackPlugin.options.template = require.resolve('../lib/templates/index.ejs'); + } + return webpackMerge(storybookConfig, config); +} diff --git a/packages/kbn-telemetry-tools/src/cli/run_telemetry_check.ts b/packages/kbn-telemetry-tools/src/cli/run_telemetry_check.ts index 87ba68c1bcb27..9f7ff5ac80c9f 100644 --- a/packages/kbn-telemetry-tools/src/cli/run_telemetry_check.ts +++ b/packages/kbn-telemetry-tools/src/cli/run_telemetry_check.ts @@ -88,7 +88,7 @@ export function runTelemetryCheck() { task: (context) => new Listr(checkCompatibleTypesTask(context), { exitOnError: true }), }, { - enabled: (_) => !!ignoreStoredJson, + enabled: (_) => fix || !ignoreStoredJson, title: 'Checking Matching collector.schema against stored json files', task: (context) => new Listr(checkMatchingSchemasTask(context, !fix), { exitOnError: true }), @@ -96,7 +96,10 @@ export function runTelemetryCheck() { { enabled: (_) => fix, skip: ({ roots }: TaskContext) => { - return roots.every(({ esMappingDiffs }) => !esMappingDiffs || !esMappingDiffs.length); + const noDiffs = roots.every( + ({ esMappingDiffs }) => !esMappingDiffs || !esMappingDiffs.length + ); + return noDiffs && 'No changes needed.'; }, title: 'Generating new telemetry mappings', task: (context) => new Listr(generateSchemasTask(context), { exitOnError: true }), @@ -104,7 +107,10 @@ export function runTelemetryCheck() { { enabled: (_) => fix, skip: ({ roots }: TaskContext) => { - return roots.every(({ esMappingDiffs }) => !esMappingDiffs || !esMappingDiffs.length); + const noDiffs = roots.every( + ({ esMappingDiffs }) => !esMappingDiffs || !esMappingDiffs.length + ); + return noDiffs && 'No changes needed.'; }, title: 'Updating telemetry mapping files', task: (context) => new Listr(writeToFileTask(context), { exitOnError: true }), diff --git a/packages/kbn-telemetry-tools/src/tools/__fixture__/mock_schema.json b/packages/kbn-telemetry-tools/src/tools/__fixture__/mock_schema.json index 2e69d3625d7ff..51e5df9bf7dc0 100644 --- a/packages/kbn-telemetry-tools/src/tools/__fixture__/mock_schema.json +++ b/packages/kbn-telemetry-tools/src/tools/__fixture__/mock_schema.json @@ -35,16 +35,19 @@ } }, "my_array": { - "properties": { - "total": { - "type": "number" - }, - "type": { - "type": "boolean" + "type": "array", + "items": { + "properties": { + "total": { + "type": "number" + }, + "type": { + "type": "boolean" + } } } }, - "my_str_array": { "type": "keyword" } + "my_str_array": { "type": "array", "items": { "type": "keyword" } } } } } diff --git a/packages/kbn-telemetry-tools/src/tools/__fixture__/parsed_schema_defined_with_spreads_collector.ts b/packages/kbn-telemetry-tools/src/tools/__fixture__/parsed_schema_defined_with_spreads_collector.ts new file mode 100644 index 0000000000000..833344fa368b0 --- /dev/null +++ b/packages/kbn-telemetry-tools/src/tools/__fixture__/parsed_schema_defined_with_spreads_collector.ts @@ -0,0 +1,69 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { SyntaxKind } from 'typescript'; +import { ParsedUsageCollection } from '../ts_parser'; + +export const parsedSchemaDefinedWithSpreadsCollector: ParsedUsageCollection = [ + 'src/fixtures/telemetry_collectors/schema_defined_with_spreads_collector.ts', + { + collectorName: 'schema_defined_with_spreads', + schema: { + value: { + flat: { + type: 'keyword', + }, + my_str: { + type: 'text', + }, + my_objects: { + total: { + type: 'number', + }, + type: { + type: 'boolean', + }, + }, + }, + }, + fetch: { + typeName: 'Usage', + typeDescriptor: { + flat: { + kind: SyntaxKind.StringKeyword, + type: 'StringKeyword', + }, + my_str: { + kind: SyntaxKind.StringKeyword, + type: 'StringKeyword', + }, + my_objects: { + total: { + kind: SyntaxKind.NumberKeyword, + type: 'NumberKeyword', + }, + type: { + kind: SyntaxKind.BooleanKeyword, + type: 'BooleanKeyword', + }, + }, + }, + }, + }, +]; diff --git a/packages/kbn-telemetry-tools/src/tools/__fixture__/parsed_working_collector.ts b/packages/kbn-telemetry-tools/src/tools/__fixture__/parsed_working_collector.ts index b238c5aa346ad..acf984b7d10ee 100644 --- a/packages/kbn-telemetry-tools/src/tools/__fixture__/parsed_working_collector.ts +++ b/packages/kbn-telemetry-tools/src/tools/__fixture__/parsed_working_collector.ts @@ -55,12 +55,15 @@ export const parsedWorkingCollector: ParsedUsageCollection = [ }, }, my_array: { - total: { - type: 'number', + type: 'array', + items: { + total: { + type: 'number', + }, + type: { type: 'boolean' }, }, - type: { type: 'boolean' }, }, - my_str_array: { type: 'keyword' }, + my_str_array: { type: 'array', items: { type: 'keyword' } }, }, }, fetch: { @@ -75,11 +78,9 @@ export const parsedWorkingCollector: ParsedUsageCollection = [ type: 'StringKeyword', }, my_index_signature_prop: { - '': { - '@@INDEX@@': { - kind: SyntaxKind.NumberKeyword, - type: 'NumberKeyword', - }, + '@@INDEX@@': { + kind: SyntaxKind.NumberKeyword, + type: 'NumberKeyword', }, }, my_objects: { @@ -93,18 +94,22 @@ export const parsedWorkingCollector: ParsedUsageCollection = [ }, }, my_array: { - total: { - kind: SyntaxKind.NumberKeyword, - type: 'NumberKeyword', - }, - type: { - kind: SyntaxKind.BooleanKeyword, - type: 'BooleanKeyword', + items: { + total: { + kind: SyntaxKind.NumberKeyword, + type: 'NumberKeyword', + }, + type: { + kind: SyntaxKind.BooleanKeyword, + type: 'BooleanKeyword', + }, }, }, my_str_array: { - kind: SyntaxKind.StringKeyword, - type: 'StringKeyword', + items: { + kind: SyntaxKind.StringKeyword, + type: 'StringKeyword', + }, }, }, }, diff --git a/packages/kbn-telemetry-tools/src/tools/__snapshots__/extract_collectors.test.ts.snap b/packages/kbn-telemetry-tools/src/tools/__snapshots__/extract_collectors.test.ts.snap index 68b068b0cfe06..4725be77533af 100644 --- a/packages/kbn-telemetry-tools/src/tools/__snapshots__/extract_collectors.test.ts.snap +++ b/packages/kbn-telemetry-tools/src/tools/__snapshots__/extract_collectors.test.ts.snap @@ -96,16 +96,14 @@ Array [ "collectorName": "indexed_interface_with_not_matching_schema", "fetch": Object { "typeDescriptor": Object { - "": Object { - "@@INDEX@@": Object { - "count_1": Object { - "kind": 143, - "type": "NumberKeyword", - }, - "count_2": Object { - "kind": 143, - "type": "NumberKeyword", - }, + "@@INDEX@@": Object { + "count_1": Object { + "kind": 143, + "type": "NumberKeyword", + }, + "count_2": Object { + "kind": 143, + "type": "NumberKeyword", }, }, }, @@ -145,16 +143,16 @@ Array [ }, ], Array [ - "src/fixtures/telemetry_collectors/working_collector.ts", + "src/fixtures/telemetry_collectors/schema_defined_with_spreads_collector.ts", Object { - "collectorName": "my_working_collector", + "collectorName": "schema_defined_with_spreads", "fetch": Object { "typeDescriptor": Object { "flat": Object { "kind": 146, "type": "StringKeyword", }, - "my_array": Object { + "my_objects": Object { "total": Object { "kind": 143, "type": "NumberKeyword", @@ -164,12 +162,59 @@ Array [ "type": "BooleanKeyword", }, }, - "my_index_signature_prop": Object { - "": Object { - "@@INDEX@@": Object { + "my_str": Object { + "kind": 146, + "type": "StringKeyword", + }, + }, + "typeName": "Usage", + }, + "schema": Object { + "value": Object { + "flat": Object { + "type": "keyword", + }, + "my_objects": Object { + "total": Object { + "type": "number", + }, + "type": Object { + "type": "boolean", + }, + }, + "my_str": Object { + "type": "text", + }, + }, + }, + }, + ], + Array [ + "src/fixtures/telemetry_collectors/working_collector.ts", + Object { + "collectorName": "my_working_collector", + "fetch": Object { + "typeDescriptor": Object { + "flat": Object { + "kind": 146, + "type": "StringKeyword", + }, + "my_array": Object { + "items": Object { + "total": Object { "kind": 143, "type": "NumberKeyword", }, + "type": Object { + "kind": 131, + "type": "BooleanKeyword", + }, + }, + }, + "my_index_signature_prop": Object { + "@@INDEX@@": Object { + "kind": 143, + "type": "NumberKeyword", }, }, "my_objects": Object { @@ -187,8 +232,10 @@ Array [ "type": "StringKeyword", }, "my_str_array": Object { - "kind": 146, - "type": "StringKeyword", + "items": Object { + "kind": 146, + "type": "StringKeyword", + }, }, }, "typeName": "Usage", @@ -199,12 +246,15 @@ Array [ "type": "keyword", }, "my_array": Object { - "total": Object { - "type": "number", - }, - "type": Object { - "type": "boolean", + "items": Object { + "total": Object { + "type": "number", + }, + "type": Object { + "type": "boolean", + }, }, + "type": "array", }, "my_index_signature_prop": Object { "avg": Object { @@ -232,7 +282,10 @@ Array [ "type": "text", }, "my_str_array": Object { - "type": "keyword", + "items": Object { + "type": "keyword", + }, + "type": "array", }, }, }, diff --git a/packages/kbn-telemetry-tools/src/tools/__snapshots__/ts_parser.test.ts.snap b/packages/kbn-telemetry-tools/src/tools/__snapshots__/ts_parser.test.ts.snap index 5b1b3d9d35299..829b45496925c 100644 --- a/packages/kbn-telemetry-tools/src/tools/__snapshots__/ts_parser.test.ts.snap +++ b/packages/kbn-telemetry-tools/src/tools/__snapshots__/ts_parser.test.ts.snap @@ -1,5 +1,10 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP +exports[`parseUsageCollection throws when \`makeUsageCollector\` argument is a function call 1`] = ` +"Error extracting collector in src/fixtures/telemetry_collectors/externally_defined_usage_collector/index.ts +Error: makeUsageCollector argument must be an object." +`; + exports[`parseUsageCollection throws when mapping fields is not defined 1`] = ` "Error extracting collector in src/fixtures/telemetry_collectors/unmapped_collector.ts Error: usageCollector.schema must be defined." diff --git a/packages/kbn-telemetry-tools/src/tools/check_collector_integrity.ts b/packages/kbn-telemetry-tools/src/tools/check_collector_integrity.ts index 3205edb87aa29..8a5752f77d7fc 100644 --- a/packages/kbn-telemetry-tools/src/tools/check_collector_integrity.ts +++ b/packages/kbn-telemetry-tools/src/tools/check_collector_integrity.ts @@ -47,6 +47,7 @@ export function checkCompatibleTypeDescriptor( const typeDescriptorKinds = reduce( typeDescriptorTypes, (acc: any, type: number, key: string) => { + key = key.replace(/'/g, ''); try { acc[key] = kindToDescriptorName(type); } catch (err) { @@ -61,6 +62,7 @@ export function checkCompatibleTypeDescriptor( const transformedMappingKinds = reduce( schemaTypes, (acc: any, type: string, key: string) => { + key = key.replace(/'/g, ''); try { acc[key.replace(/.type$/, '.kind')] = compatibleSchemaTypes(type as any); } catch (err) { diff --git a/packages/kbn-telemetry-tools/src/tools/config.test.ts b/packages/kbn-telemetry-tools/src/tools/config.test.ts index 51ca0493cbb5a..ad2d1bce885ea 100644 --- a/packages/kbn-telemetry-tools/src/tools/config.test.ts +++ b/packages/kbn-telemetry-tools/src/tools/config.test.ts @@ -33,7 +33,10 @@ describe('parseTelemetryRC', () => { { root: configRoot, output: configRoot, - exclude: [path.resolve(configRoot, './unmapped_collector.ts')], + exclude: [ + path.resolve(configRoot, './unmapped_collector.ts'), + path.resolve(configRoot, './externally_defined_usage_collector/index.ts'), + ], }, ]); }); diff --git a/packages/kbn-telemetry-tools/src/tools/extract_collectors.test.ts b/packages/kbn-telemetry-tools/src/tools/extract_collectors.test.ts index 0517cb9034d0a..b03db75b219f6 100644 --- a/packages/kbn-telemetry-tools/src/tools/extract_collectors.test.ts +++ b/packages/kbn-telemetry-tools/src/tools/extract_collectors.test.ts @@ -34,7 +34,7 @@ describe('extractCollectors', () => { const programPaths = await getProgramPaths(configs[0]); const results = [...extractCollectors(programPaths, tsConfig)]; - expect(results).toHaveLength(7); + expect(results).toHaveLength(8); expect(results).toMatchSnapshot(); }); }); diff --git a/packages/kbn-telemetry-tools/src/tools/manage_schema.ts b/packages/kbn-telemetry-tools/src/tools/manage_schema.ts index d422837140d80..7721492fdb691 100644 --- a/packages/kbn-telemetry-tools/src/tools/manage_schema.ts +++ b/packages/kbn-telemetry-tools/src/tools/manage_schema.ts @@ -28,7 +28,7 @@ export type AllowedSchemaTypes = | 'date' | 'float'; -export function compatibleSchemaTypes(type: AllowedSchemaTypes) { +export function compatibleSchemaTypes(type: AllowedSchemaTypes | 'array') { switch (type) { case 'keyword': case 'text': @@ -40,6 +40,8 @@ export function compatibleSchemaTypes(type: AllowedSchemaTypes) { case 'float': case 'long': return 'number'; + case 'array': + return 'array'; default: throw new Error(`Unknown schema type ${type}`); } @@ -66,10 +68,22 @@ export function isObjectMapping(entity: any) { return false; } +function isArrayMapping(entity: any): entity is { type: 'array'; items: object } { + return typeof entity === 'object' && entity.type === 'array' && typeof entity.items === 'object'; +} + +function getValueMapping(value: any) { + return isObjectMapping(value) ? transformToEsMapping(value) : value; +} + function transformToEsMapping(usageMappingValue: any) { const fieldMapping: any = { properties: {} }; for (const [key, value] of Object.entries(usageMappingValue)) { - fieldMapping.properties[key] = isObjectMapping(value) ? transformToEsMapping(value) : value; + if (isArrayMapping(value)) { + fieldMapping.properties[key] = { ...value, items: getValueMapping(value.items) }; + } else { + fieldMapping.properties[key] = getValueMapping(value); + } } return fieldMapping; } diff --git a/packages/kbn-telemetry-tools/src/tools/serializer.test.ts b/packages/kbn-telemetry-tools/src/tools/serializer.test.ts index 9475574a44219..48c4d73c291fe 100644 --- a/packages/kbn-telemetry-tools/src/tools/serializer.test.ts +++ b/packages/kbn-telemetry-tools/src/tools/serializer.test.ts @@ -44,13 +44,13 @@ export function loadFixtureProgram(fixtureName: string) { } describe('getDescriptor', () => { - const usageInterfaces = new Map(); + const usageInterfaces = new Map(); let tsProgram: ts.Program; beforeAll(() => { const { program, sourceFile } = loadFixtureProgram('constants'); tsProgram = program; for (const node of traverseNodes(sourceFile)) { - if (ts.isInterfaceDeclaration(node)) { + if (ts.isInterfaceDeclaration(node) || ts.isTypeAliasDeclaration(node)) { const interfaceName = node.name.getText(); usageInterfaces.set(interfaceName, node); } @@ -84,8 +84,8 @@ describe('getDescriptor', () => { expect(descriptor).toEqual({ prop1: { kind: TelemetryKinds.MomentDate, type: 'MomentDate' }, prop2: { kind: TelemetryKinds.MomentDate, type: 'MomentDate' }, - prop3: { kind: TelemetryKinds.MomentDate, type: 'MomentDate' }, - prop4: { kind: TelemetryKinds.Date, type: 'Date' }, + prop3: { items: { kind: TelemetryKinds.MomentDate, type: 'MomentDate' } }, + prop4: { items: { kind: TelemetryKinds.Date, type: 'Date' } }, }); }); @@ -102,4 +102,69 @@ describe('getDescriptor', () => { 'Mapping does not support conflicting union types.' ); }); + + it('serializes TypeAliasDeclaration', () => { + const usageInterface = usageInterfaces.get('TypeAliasWithUnion')!; + const descriptor = getDescriptor(usageInterface, tsProgram); + expect(descriptor).toEqual({ + locale: { kind: ts.SyntaxKind.StringKeyword, type: 'StringKeyword' }, + prop1: { kind: ts.SyntaxKind.StringKeyword, type: 'StringKeyword' }, + prop2: { kind: ts.SyntaxKind.StringKeyword, type: 'StringKeyword' }, + prop3: { kind: ts.SyntaxKind.StringKeyword, type: 'StringKeyword' }, + prop4: { kind: ts.SyntaxKind.StringLiteral, type: 'StringLiteral' }, + prop5: { kind: ts.SyntaxKind.FirstLiteralToken, type: 'FirstLiteralToken' }, + }); + }); + + it('serializes Record entries', () => { + const usageInterface = usageInterfaces.get('TypeAliasWithRecord')!; + const descriptor = getDescriptor(usageInterface, tsProgram); + expect(descriptor).toEqual({ + locale: { kind: ts.SyntaxKind.StringKeyword, type: 'StringKeyword' }, + '@@INDEX@@': { kind: ts.SyntaxKind.NumberKeyword, type: 'NumberKeyword' }, + }); + }); + + it('serializes MappedTypes', () => { + const usageInterface = usageInterfaces.get('MappedTypes')!; + const descriptor = getDescriptor(usageInterface, tsProgram); + expect(descriptor).toEqual({ + mappedTypeWithExternallyDefinedProps: { + prop1: { kind: ts.SyntaxKind.NumberKeyword, type: 'NumberKeyword' }, + prop2: { kind: ts.SyntaxKind.NumberKeyword, type: 'NumberKeyword' }, + }, + mappedTypeWithOneInlineProp: { + prop3: { kind: ts.SyntaxKind.NumberKeyword, type: 'NumberKeyword' }, + }, + }); + }); + + it('serializes RecordWithKnownProps', () => { + const usageInterface = usageInterfaces.get('RecordWithKnownProps')!; + const descriptor = getDescriptor(usageInterface, tsProgram); + expect(descriptor).toEqual({ + prop1: { kind: ts.SyntaxKind.NumberKeyword, type: 'NumberKeyword' }, + prop2: { kind: ts.SyntaxKind.NumberKeyword, type: 'NumberKeyword' }, + }); + }); + + it('serializes RecordWithKnownAllProps', () => { + const usageInterface = usageInterfaces.get('RecordWithKnownAllProps')!; + const descriptor = getDescriptor(usageInterface, tsProgram); + expect(descriptor).toEqual({ + prop1: { kind: ts.SyntaxKind.NumberKeyword, type: 'NumberKeyword' }, + prop2: { kind: ts.SyntaxKind.NumberKeyword, type: 'NumberKeyword' }, + prop3: { kind: ts.SyntaxKind.NumberKeyword, type: 'NumberKeyword' }, + prop4: { kind: ts.SyntaxKind.NumberKeyword, type: 'NumberKeyword' }, + }); + }); + + it('serializes IndexedAccessType', () => { + const usageInterface = usageInterfaces.get('IndexedAccessType')!; + const descriptor = getDescriptor(usageInterface, tsProgram); + expect(descriptor).toEqual({ + prop1: { kind: ts.SyntaxKind.StringKeyword, type: 'StringKeyword' }, + prop2: { kind: ts.SyntaxKind.StringKeyword, type: 'StringKeyword' }, + }); + }); }); diff --git a/packages/kbn-telemetry-tools/src/tools/serializer.ts b/packages/kbn-telemetry-tools/src/tools/serializer.ts index 7afe828298b4b..d380e17759e21 100644 --- a/packages/kbn-telemetry-tools/src/tools/serializer.ts +++ b/packages/kbn-telemetry-tools/src/tools/serializer.ts @@ -18,7 +18,7 @@ */ import * as ts from 'typescript'; -import { uniqBy } from 'lodash'; +import { uniqBy, pick } from 'lodash'; import { getResolvedModuleSourceFile, getIdentifierDeclarationFromSource, @@ -71,6 +71,46 @@ export function kindToDescriptorName(kind: number) { } } +export function getConstraints(node: ts.Node, program: ts.Program): any { + if (ts.isTypeReferenceNode(node)) { + const typeChecker = program.getTypeChecker(); + const symbol = typeChecker.getSymbolAtLocation(node.typeName); + const declaration = (symbol?.getDeclarations() || [])[0]; + if (declaration) { + return getConstraints(declaration, program); + } + return getConstraints(node.typeName, program); + } + + if (ts.isTypeAliasDeclaration(node)) { + return getConstraints(node.type, program); + } + + if (ts.isUnionTypeNode(node)) { + const types = node.types.filter(discardNullOrUndefined); + return types.reduce((acc, typeNode) => { + const constraints = getConstraints(typeNode, program); + const contraintsArray = Array.isArray(constraints) ? constraints : [constraints]; + return [...acc, ...contraintsArray]; + }, []); + } + + if (ts.isLiteralTypeNode(node) && ts.isLiteralExpression(node.literal)) { + return node.literal.text; + } + + if (ts.isImportSpecifier(node)) { + const source = node.getSourceFile(); + const importedModuleName = getModuleSpecifier(node); + + const declarationSource = getResolvedModuleSourceFile(source, program, importedModuleName); + const declarationNode = getIdentifierDeclarationFromSource(node.name, declarationSource); + return getConstraints(declarationNode, program); + } + + throw Error(`Unsupported constraint of kind ${node.kind} [${ts.SyntaxKind[node.kind]}]`); +} + export function getDescriptor(node: ts.Node, program: ts.Program): Descriptor | DescriptorValue { if (ts.isMethodSignature(node) || ts.isPropertySignature(node)) { if (node.type) { @@ -79,14 +119,29 @@ export function getDescriptor(node: ts.Node, program: ts.Program): Descriptor | } if (ts.isTypeLiteralNode(node) || ts.isInterfaceDeclaration(node)) { return node.members.reduce((acc, m) => { - acc[m.name?.getText() || ''] = getDescriptor(m, program); - return acc; - }, {} as any); + const key = m.name?.getText(); + if (key) { + return { ...acc, [key]: getDescriptor(m, program) }; + } else { + return { ...acc, ...getDescriptor(m, program) }; + } + }, {}); } // If it's defined as signature { [key: string]: OtherInterface } - if (ts.isIndexSignatureDeclaration(node) && node.type) { - return { '@@INDEX@@': getDescriptor(node.type, program) }; + if ((ts.isIndexSignatureDeclaration(node) || ts.isMappedTypeNode(node)) && node.type) { + const descriptor = getDescriptor(node.type, program); + + // If we know the constraints of `string` ({ [key in 'prop1' | 'prop2']: value }) + const constraint = (node as ts.MappedTypeNode).typeParameter?.constraint; + if (constraint) { + const constraints = getConstraints(constraint, program); + const constraintsArray = Array.isArray(constraints) ? constraints : [constraints]; + if (typeof constraintsArray[0] === 'string') { + return constraintsArray.reduce((acc, c) => ({ ...acc, [c]: descriptor }), {}); + } + } + return { '@@INDEX@@': descriptor }; } if (ts.SyntaxKind.FirstNode === node.kind) { @@ -114,6 +169,26 @@ export function getDescriptor(node: ts.Node, program: ts.Program): Descriptor | if (symbolName === 'Date') { return { kind: TelemetryKinds.Date, type: 'Date' }; } + // Support `Record` + if (symbolName === 'Record') { + const descriptor = getDescriptor(node.typeArguments![1], program); + if (node.typeArguments![0].kind === ts.SyntaxKind.StringKeyword) { + return { '@@INDEX@@': descriptor }; + } + const constraints = getConstraints(node.typeArguments![0], program); + const constraintsArray = Array.isArray(constraints) ? constraints : [constraints]; + if (typeof constraintsArray[0] === 'string') { + return constraintsArray.reduce((acc, c) => ({ ...acc, [c]: descriptor }), {}); + } + } + + // Support `Pick` + if (symbolName === 'Pick') { + const parentDescriptor = getDescriptor(node.typeArguments![0], program); + const pickPropNames = getConstraints(node.typeArguments![1], program); + return pick(parentDescriptor, pickPropNames); + } + const declaration = (symbol?.getDeclarations() || [])[0]; if (declaration) { return getDescriptor(declaration, program); @@ -131,7 +206,7 @@ export function getDescriptor(node: ts.Node, program: ts.Program): Descriptor | } if (ts.isArrayTypeNode(node)) { - return getDescriptor(node.elementType, program); + return { items: getDescriptor(node.elementType, program) }; } if (ts.isLiteralTypeNode(node)) { @@ -157,6 +232,19 @@ export function getDescriptor(node: ts.Node, program: ts.Program): Descriptor | return uniqueKinds[0]; } + // Support `type MyUsageType = SomethingElse` + if (ts.isTypeAliasDeclaration(node)) { + return getDescriptor(node.type, program); + } + + // Support `&` unions + if (ts.isIntersectionTypeNode(node)) { + return node.types.reduce( + (acc, unionNode) => ({ ...acc, ...getDescriptor(unionNode, program) }), + {} + ); + } + switch (node.kind) { case ts.SyntaxKind.NumberKeyword: case ts.SyntaxKind.BooleanKeyword: diff --git a/packages/kbn-telemetry-tools/src/tools/ts_parser.test.ts b/packages/kbn-telemetry-tools/src/tools/ts_parser.test.ts index b7ca33a7bcd74..64d7f1fc35f47 100644 --- a/packages/kbn-telemetry-tools/src/tools/ts_parser.test.ts +++ b/packages/kbn-telemetry-tools/src/tools/ts_parser.test.ts @@ -25,6 +25,7 @@ import { parsedNestedCollector } from './__fixture__/parsed_nested_collector'; import { parsedExternallyDefinedCollector } from './__fixture__/parsed_externally_defined_collector'; import { parsedImportedUsageInterface } from './__fixture__/parsed_imported_usage_interface'; import { parsedImportedSchemaCollector } from './__fixture__/parsed_imported_schema'; +import { parsedSchemaDefinedWithSpreadsCollector } from './__fixture__/parsed_schema_defined_with_spreads_collector'; export function loadFixtureProgram(fixtureName: string) { const fixturePath = path.resolve( @@ -32,7 +33,7 @@ export function loadFixtureProgram(fixtureName: string) { 'src', 'fixtures', 'telemetry_collectors', - `${fixtureName}.ts` + `${fixtureName}` ); const tsConfig = ts.findConfigFile('./', ts.sys.fileExists, 'tsconfig.json'); if (!tsConfig) { @@ -51,43 +52,56 @@ describe('parseUsageCollection', () => { it.todo('throws when a function is returned from fetch'); it.todo('throws when an object is not returned from fetch'); + it('throws when `makeUsageCollector` argument is a function call', () => { + const { program, sourceFile } = loadFixtureProgram( + 'externally_defined_usage_collector/index.ts' + ); + expect(() => [...parseUsageCollection(sourceFile, program)]).toThrowErrorMatchingSnapshot(); + }); + it('throws when mapping fields is not defined', () => { - const { program, sourceFile } = loadFixtureProgram('unmapped_collector'); + const { program, sourceFile } = loadFixtureProgram('unmapped_collector.ts'); expect(() => [...parseUsageCollection(sourceFile, program)]).toThrowErrorMatchingSnapshot(); }); it('parses root level defined collector', () => { - const { program, sourceFile } = loadFixtureProgram('working_collector'); + const { program, sourceFile } = loadFixtureProgram('working_collector.ts'); const result = [...parseUsageCollection(sourceFile, program)]; expect(result).toEqual([parsedWorkingCollector]); }); + it('parses collector with schema defined as union of spreads', () => { + const { program, sourceFile } = loadFixtureProgram('schema_defined_with_spreads_collector.ts'); + const result = [...parseUsageCollection(sourceFile, program)]; + expect(result).toEqual([parsedSchemaDefinedWithSpreadsCollector]); + }); + it('parses nested collectors', () => { - const { program, sourceFile } = loadFixtureProgram('nested_collector'); + const { program, sourceFile } = loadFixtureProgram('nested_collector.ts'); const result = [...parseUsageCollection(sourceFile, program)]; expect(result).toEqual([parsedNestedCollector]); }); it('parses imported schema property', () => { - const { program, sourceFile } = loadFixtureProgram('imported_schema'); + const { program, sourceFile } = loadFixtureProgram('imported_schema.ts'); const result = [...parseUsageCollection(sourceFile, program)]; expect(result).toEqual(parsedImportedSchemaCollector); }); it('parses externally defined collectors', () => { - const { program, sourceFile } = loadFixtureProgram('externally_defined_collector'); + const { program, sourceFile } = loadFixtureProgram('externally_defined_collector.ts'); const result = [...parseUsageCollection(sourceFile, program)]; expect(result).toEqual(parsedExternallyDefinedCollector); }); it('parses imported Usage interface', () => { - const { program, sourceFile } = loadFixtureProgram('imported_usage_interface'); + const { program, sourceFile } = loadFixtureProgram('imported_usage_interface.ts'); const result = [...parseUsageCollection(sourceFile, program)]; expect(result).toEqual(parsedImportedUsageInterface); }); it('skips files that do not define a collector', () => { - const { program, sourceFile } = loadFixtureProgram('file_with_no_collector'); + const { program, sourceFile } = loadFixtureProgram('file_with_no_collector.ts'); const result = [...parseUsageCollection(sourceFile, program)]; expect(result).toEqual([]); }); diff --git a/packages/kbn-telemetry-tools/src/tools/ts_parser.ts b/packages/kbn-telemetry-tools/src/tools/ts_parser.ts index 6af8450f5a2e8..3af6b8b29768d 100644 --- a/packages/kbn-telemetry-tools/src/tools/ts_parser.ts +++ b/packages/kbn-telemetry-tools/src/tools/ts_parser.ts @@ -178,13 +178,11 @@ export function sourceHasUsageCollector(sourceFile: ts.SourceFile) { } const identifiers = (sourceFile as any).identifiers; - if ( - (!identifiers.get('makeUsageCollector') && !identifiers.get('type')) || - !identifiers.get('fetch') - ) { - return false; + if (identifiers.get('makeUsageCollector')) { + return true; } + return false; return true; } diff --git a/packages/kbn-telemetry-tools/src/tools/utils.ts b/packages/kbn-telemetry-tools/src/tools/utils.ts index 3d6764117374c..90ba7f4d9168f 100644 --- a/packages/kbn-telemetry-tools/src/tools/utils.ts +++ b/packages/kbn-telemetry-tools/src/tools/utils.ts @@ -78,14 +78,14 @@ export function getIdentifierDeclarationFromSource(node: ts.Node, source: ts.Sou const identifierName = node.getText(); const identifierDefinition: ts.Node = (source as any).locals.get(identifierName); if (!identifierDefinition) { - throw new Error(`Unable to fine identifier in source ${identifierName}`); + throw new Error(`Unable to find identifier in source ${identifierName}`); } const declarations = (identifierDefinition as any).declarations as ts.Node[]; const latestDeclaration: ts.Node | false | undefined = Array.isArray(declarations) && declarations[declarations.length - 1]; if (!latestDeclaration) { - throw new Error(`Unable to fine declaration for identifier ${identifierName}`); + throw new Error(`Unable to find declaration for identifier ${identifierName}`); } return latestDeclaration; @@ -100,42 +100,57 @@ export function getIdentifierDeclaration(node: ts.Node) { return getIdentifierDeclarationFromSource(node, source); } -export function getVariableValue(node: ts.Node): string | Record { +export function getVariableValue(node: ts.Node, program: ts.Program): string | Record { if (ts.isStringLiteral(node) || ts.isNumericLiteral(node)) { return node.text; } if (ts.isObjectLiteralExpression(node)) { - return serializeObject(node); + return serializeObject(node, program); } if (ts.isIdentifier(node)) { const declaration = getIdentifierDeclaration(node); if (ts.isVariableDeclaration(declaration) && declaration.initializer) { - return getVariableValue(declaration.initializer); + return getVariableValue(declaration.initializer, program); + } else { + // Go fetch it in another file + return getIdentifierValue(node, node, program, { chaseImport: true }); } - // TODO: If this is another imported value from another file, we'll need to go fetch it like in getPropertyValue } - throw Error(`Unsuppored Node: cannot get value of node (${node.getText()}) of kind ${node.kind}`); + if (ts.isSpreadAssignment(node)) { + return getVariableValue(node.expression, program); + } + + throw Error( + `Unsupported Node: cannot get value of node (${node.getText()}) of kind ${node.kind} [${ + ts.SyntaxKind[node.kind] + }]` + ); } -export function serializeObject(node: ts.Node) { +export function serializeObject(node: ts.Node, program: ts.Program) { if (!ts.isObjectLiteralExpression(node)) { throw new Error(`Expecting Object literal Expression got ${node.getText()}`); } - const value: Record = {}; + let value: Record = {}; for (const property of node.properties) { const propertyName = property.name?.getText(); + const val = ts.isPropertyAssignment(property) + ? getVariableValue(property.initializer, program) + : getVariableValue(property, program); + if (typeof propertyName === 'undefined') { - throw new Error(`Unable to get property name ${property.getText()}`); - } - const cleanPropertyName = propertyName.replace(/["']/g, ''); - if (ts.isPropertyAssignment(property)) { - value[cleanPropertyName] = getVariableValue(property.initializer); + if (typeof val === 'object') { + value = { ...value, ...val }; + } else { + throw new Error(`Unable to get property name ${property.getText()}`); + } } else { - value[cleanPropertyName] = getVariableValue(property); + const cleanPropertyName = propertyName.replace(/["']/g, ''); + value[cleanPropertyName] = val; } } @@ -155,45 +170,53 @@ export function getResolvedModuleSourceFile( return resolvedModuleSourceFile; } -export function getPropertyValue( +export function getIdentifierValue( node: ts.Node, + initializer: ts.Identifier, program: ts.Program, config: Optional<{ chaseImport: boolean }> = {} ) { const { chaseImport = false } = config; + const identifierName = initializer.getText(); + const declaration = getIdentifierDeclaration(initializer); + if (ts.isImportSpecifier(declaration)) { + if (!chaseImport) { + throw new Error( + `Value of node ${identifierName} is imported from another file. Chasing imports is not allowed.` + ); + } - if (ts.isPropertyAssignment(node)) { - const { initializer } = node; + const importedModuleName = getModuleSpecifier(declaration); - if (ts.isIdentifier(initializer)) { - const identifierName = initializer.getText(); - const declaration = getIdentifierDeclaration(initializer); - if (ts.isImportSpecifier(declaration)) { - if (!chaseImport) { - throw new Error( - `Value of node ${identifierName} is imported from another file. Chasing imports is not allowed.` - ); - } + const source = node.getSourceFile(); + const declarationSource = getResolvedModuleSourceFile(source, program, importedModuleName); + const declarationNode = getIdentifierDeclarationFromSource(initializer, declarationSource); + if (!ts.isVariableDeclaration(declarationNode)) { + throw new Error(`Expected ${identifierName} to be variable declaration.`); + } + if (!declarationNode.initializer) { + throw new Error(`Expected ${identifierName} to be initialized.`); + } + const serializedObject = serializeObject(declarationNode.initializer, program); + return serializedObject; + } - const importedModuleName = getModuleSpecifier(declaration); + return getVariableValue(declaration, program); +} - const source = node.getSourceFile(); - const declarationSource = getResolvedModuleSourceFile(source, program, importedModuleName); - const declarationNode = getIdentifierDeclarationFromSource(initializer, declarationSource); - if (!ts.isVariableDeclaration(declarationNode)) { - throw new Error(`Expected ${identifierName} to be variable declaration.`); - } - if (!declarationNode.initializer) { - throw new Error(`Expected ${identifierName} to be initialized.`); - } - const serializedObject = serializeObject(declarationNode.initializer); - return serializedObject; - } +export function getPropertyValue( + node: ts.Node, + program: ts.Program, + config: Optional<{ chaseImport: boolean }> = {} +) { + if (ts.isPropertyAssignment(node)) { + const { initializer } = node; - return getVariableValue(declaration); + if (ts.isIdentifier(initializer)) { + return getIdentifierValue(node, initializer, program, config); } - return getVariableValue(initializer); + return getVariableValue(initializer, program); } } @@ -249,7 +272,7 @@ export function difference(actual: any, expected: any) { function (result, value, key) { if (key && /@@INDEX@@/.test(`${key}`)) { // The type definition is an Index Signature, fuzzy searching for similar keys - const regexp = new RegExp(`${key}`.replace(/@@INDEX@@/g, '(.+)?')); + const regexp = new RegExp(`^${key}`.replace(/@@INDEX@@/g, '(.+)?')); const keysInBase = Object.keys(base) .map((k) => { const match = k.match(regexp); diff --git a/packages/kbn-test/package.json b/packages/kbn-test/package.json index 8a4ff55dcf68f..8422c34c9ed08 100644 --- a/packages/kbn-test/package.json +++ b/packages/kbn-test/package.json @@ -11,6 +11,7 @@ }, "devDependencies": { "@babel/cli": "^7.10.5", + "@jest/types": "^26.5.2", "@kbn/babel-preset": "1.0.0", "@kbn/dev-utils": "1.0.0", "@kbn/utils": "1.0.0", @@ -22,19 +23,22 @@ "diff": "^4.0.1" }, "dependencies": { + "@jest/reporters": "^26.5.2", "chalk": "^4.1.0", "dedent": "^0.7.0", "del": "^5.1.0", + "execa": "^4.0.2", "exit-hook": "^2.2.0", - "getopts": "^2.2.4", + "getopts": "^2.2.5", "glob": "^7.1.2", + "globby": "^8.0.1", "joi": "^13.5.2", - "lodash": "^4.17.15", + "lodash": "^4.17.20", + "mustache": "^2.3.2", "parse-link-header": "^1.0.1", "rxjs": "^6.5.5", - "strip-ansi": "^5.2.0", + "strip-ansi": "^6.0.0", "tar-fs": "^2.1.0", - "tmp": "^0.1.0", "xml2js": "^0.4.22", "zlib": "^1.0.5" } diff --git a/packages/kbn-test/src/functional_tests/lib/babel_register_for_test_plugins.js b/packages/kbn-test/src/functional_tests/lib/babel_register_for_test_plugins.js new file mode 100644 index 0000000000000..44ff579411bd9 --- /dev/null +++ b/packages/kbn-test/src/functional_tests/lib/babel_register_for_test_plugins.js @@ -0,0 +1,39 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +const Path = require('path'); + +const { REPO_ROOT } = require('@kbn/dev-utils'); + +// modifies all future calls to require() to automatically +// compile the required source with babel +require('@babel/register')({ + ignore: [/[\/\\](node_modules|target|dist)[\/\\]/], + only: [ + Path.resolve(REPO_ROOT, 'test'), + Path.resolve(REPO_ROOT, 'x-pack/test'), + Path.resolve(REPO_ROOT, 'examples'), + Path.resolve(REPO_ROOT, 'x-pack/examples'), + // TODO: should should probably remove this link back to the source + Path.resolve(REPO_ROOT, 'x-pack/plugins/task_manager/server/config.ts'), + ], + babelrc: false, + presets: [require.resolve('@kbn/babel-preset/node_preset')], + extensions: ['.js', '.ts', '.tsx'], +}); 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 fb9f8f7a52408..e7ec99467ecfd 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 @@ -17,9 +17,26 @@ * under the License. */ -import { resolve } from 'path'; +import { resolve, relative } from 'path'; import { KIBANA_ROOT, KIBANA_EXEC, KIBANA_EXEC_PATH } from './paths'; +function extendNodeOptions(installDir) { + if (!installDir) { + return {}; + } + + const testOnlyRegisterPath = relative( + installDir, + require.resolve('./babel_register_for_test_plugins') + ); + + return { + NODE_OPTIONS: `--require=${testOnlyRegisterPath}${ + process.env.NODE_OPTIONS ? ` ${process.env.NODE_OPTIONS}` : '' + }`, + }; +} + export async function runKibanaServer({ procs, config, options }) { const { installDir } = options; @@ -29,6 +46,7 @@ export async function runKibanaServer({ procs, config, options }) { env: { FORCE_COLOR: 1, ...process.env, + ...extendNodeOptions(installDir), }, cwd: installDir || KIBANA_ROOT, wait: /http server running/, diff --git a/packages/kbn-test/src/index.ts b/packages/kbn-test/src/index.ts index 50ef521a2d811..a57b92fbdde25 100644 --- a/packages/kbn-test/src/index.ts +++ b/packages/kbn-test/src/index.ts @@ -55,8 +55,8 @@ export { export { runFailedTestsReporterCli } from './failed_tests_reporter'; -export { makeJunitReportPath } from './junit_report_path'; - export { CI_PARALLEL_PROCESS_PREFIX } from './ci_parallel_process_prefix'; export * from './functional_test_runner'; + +export * from './jest'; diff --git a/packages/kbn-test/src/jest/index.ts b/packages/kbn-test/src/jest/index.ts new file mode 100644 index 0000000000000..c6d680863d9c4 --- /dev/null +++ b/packages/kbn-test/src/jest/index.ts @@ -0,0 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export * from './junit_reporter'; + +export * from './report_path'; diff --git a/packages/kbn-test/src/jest/integration_tests/__fixtures__/jest.config.js b/packages/kbn-test/src/jest/integration_tests/__fixtures__/jest.config.js new file mode 100644 index 0000000000000..50016c883d378 --- /dev/null +++ b/packages/kbn-test/src/jest/integration_tests/__fixtures__/jest.config.js @@ -0,0 +1,37 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +const { resolve } = require('path'); +const { REPO_ROOT } = require('@kbn/utils'); + +module.exports = { + reporters: [ + 'default', + [ + `${REPO_ROOT}/packages/kbn-test/target/jest/junit_reporter`, + { + reportName: 'JUnit Reporter Integration Test', + rootDirectory: resolve( + REPO_ROOT, + 'packages/kbn-test/src/jest/integration_tests/__fixtures__' + ), + }, + ], + ], +}; diff --git a/src/dev/jest/integration_tests/__fixtures__/test.js b/packages/kbn-test/src/jest/integration_tests/__fixtures__/test.js similarity index 89% rename from src/dev/jest/integration_tests/__fixtures__/test.js rename to packages/kbn-test/src/jest/integration_tests/__fixtures__/test.js index fe0c65fd45b74..161012fb3a91c 100644 --- a/src/dev/jest/integration_tests/__fixtures__/test.js +++ b/packages/kbn-test/src/jest/integration_tests/__fixtures__/test.js @@ -17,6 +17,8 @@ * under the License. */ -it('fails', () => { - throw new Error('failure'); +describe('JUnit Reporter', () => { + it('fails', () => { + throw new Error('failure'); + }); }); diff --git a/packages/kbn-test/src/jest/integration_tests/junit_reporter.test.ts b/packages/kbn-test/src/jest/integration_tests/junit_reporter.test.ts new file mode 100644 index 0000000000000..1390c44d84a07 --- /dev/null +++ b/packages/kbn-test/src/jest/integration_tests/junit_reporter.test.ts @@ -0,0 +1,93 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { resolve } from 'path'; +import { promisify } from 'util'; +import { readFileSync } from 'fs'; + +import del from 'del'; +import execa from 'execa'; +import xml2js from 'xml2js'; +import { makeJunitReportPath } from '@kbn/test'; +import { REPO_ROOT } from '@kbn/utils'; + +const MINUTE = 1000 * 60; +const FIXTURE_DIR = resolve(__dirname, '__fixtures__'); +const TARGET_DIR = resolve(FIXTURE_DIR, 'target'); +const XML_PATH = makeJunitReportPath(FIXTURE_DIR, 'JUnit Reporter Integration Test'); + +afterAll(async () => { + await del(TARGET_DIR); +}); + +const parseXml = promisify(xml2js.parseString); +it( + 'produces a valid junit report for failures', + async () => { + const result = await execa( + './node_modules/.bin/jest', + ['--config', 'packages/kbn-test/src/jest/integration_tests/__fixtures__/jest.config.js'], + { + cwd: REPO_ROOT, + env: { + CI: 'true', + }, + reject: false, + } + ); + + expect(result.exitCode).toBe(1); + await expect(parseXml(readFileSync(XML_PATH, 'utf8'))).resolves.toEqual({ + testsuites: { + $: { + failures: '1', + name: 'jest', + skipped: '0', + tests: '1', + time: expect.anything(), + timestamp: expect.anything(), + }, + testsuite: [ + { + $: { + failures: '1', + file: resolve(FIXTURE_DIR, './test.js'), + name: 'test.js', + skipped: '0', + tests: '1', + time: expect.anything(), + timestamp: expect.anything(), + }, + testcase: [ + { + $: { + classname: 'JUnit Reporter Integration Test.·', + name: 'JUnit Reporter fails', + time: expect.anything(), + }, + failure: [expect.stringMatching(/Error: failure\s+at /m)], + }, + ], + }, + ], + }, + }); + }, + 3 * MINUTE +); diff --git a/packages/kbn-test/src/jest/junit_reporter.ts b/packages/kbn-test/src/jest/junit_reporter.ts new file mode 100644 index 0000000000000..8deb6751bc268 --- /dev/null +++ b/packages/kbn-test/src/jest/junit_reporter.ts @@ -0,0 +1,122 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { resolve, dirname, relative } from 'path'; +import { writeFileSync, mkdirSync } from 'fs'; + +import xmlBuilder from 'xmlbuilder'; + +import type { Config } from '@jest/types'; +import { AggregatedResult, Test, BaseReporter } from '@jest/reporters'; + +import { escapeCdata } from '../mocha/xml'; +import { makeJunitReportPath } from './report_path'; + +interface ReporterOptions { + reportName?: string; + rootDirectory?: string; +} + +/** + * Jest reporter that produces JUnit report when running on CI + * @class JestJUnitReporter + */ + +// eslint-disable-next-line import/no-default-export +export default class JestJUnitReporter extends BaseReporter { + private _reportName: string; + private _rootDirectory: string; + + constructor(globalConfig: Config.GlobalConfig, { rootDirectory, reportName }: ReporterOptions) { + super(); + this._reportName = reportName || 'Jest Tests'; + this._rootDirectory = rootDirectory ? resolve(rootDirectory) : resolve(__dirname, '../..'); + } + + /** + * Called by jest when all tests complete + * @param {Object} contexts + * @param {JestResults} results see https://facebook.github.io/jest/docs/en/configuration.html#testresultsprocessor-string + * @return {undefined} + */ + onRunComplete(contexts: Set, results: AggregatedResult): void { + if (!process.env.CI || process.env.DISABLE_JUNIT_REPORTER || !results.testResults.length) { + return; + } + + const reportName = this._reportName; + const rootDirectory = this._rootDirectory; + const root = xmlBuilder.create( + 'testsuites', + { encoding: 'utf-8' }, + {}, + { keepNullAttributes: false } + ); + + const msToIso = (ms: number | null | undefined) => + ms ? new Date(ms).toISOString().slice(0, -5) : undefined; + const msToSec = (ms: number | null | undefined) => (ms ? (ms / 1000).toFixed(3) : undefined); + + root.att({ + name: 'jest', + timestamp: msToIso(results.startTime), + time: msToSec(Date.now() - results.startTime), + tests: results.numTotalTests, + failures: results.numFailedTests, + skipped: results.numPendingTests, + }); + + // top level test results are the files/suites + results.testResults.forEach((suite) => { + const suiteEl = root.ele('testsuite', { + name: relative(rootDirectory, suite.testFilePath), + timestamp: msToIso(suite.perfStats.start), + time: msToSec(suite.perfStats.end - suite.perfStats.start), + tests: suite.testResults.length, + failures: suite.numFailingTests, + skipped: suite.numPendingTests, + file: suite.testFilePath, + }); + + // nested in there are the tests in that file + const relativePath = dirname(relative(rootDirectory, suite.testFilePath)); + const classname = `${reportName}.${relativePath.replace(/\./g, '·')}`; + suite.testResults.forEach((test) => { + const testEl = suiteEl.ele('testcase', { + classname, + name: [...test.ancestorTitles, test.title].join(' '), + time: msToSec(test.duration), + }); + + test.failureMessages.forEach((message) => { + testEl.ele('failure').dat(escapeCdata(message)); + }); + + if (test.status === 'pending') { + testEl.ele('skipped'); + } + }); + }); + + const reportPath = makeJunitReportPath(rootDirectory, reportName); + const reportXML = root.end(); + mkdirSync(dirname(reportPath), { recursive: true }); + writeFileSync(reportPath, reportXML, 'utf8'); + } +} diff --git a/packages/kbn-test/src/jest/report_path.ts b/packages/kbn-test/src/jest/report_path.ts new file mode 100644 index 0000000000000..fe122c349c193 --- /dev/null +++ b/packages/kbn-test/src/jest/report_path.ts @@ -0,0 +1,30 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { resolve } from 'path'; +import { CI_PARALLEL_PROCESS_PREFIX } from '../ci_parallel_process_prefix'; + +export function makeJunitReportPath(rootDirectory: string, reportName: string) { + return resolve( + rootDirectory, + 'target/junit', + process.env.JOB || '.', + `TEST-${CI_PARALLEL_PROCESS_PREFIX}${reportName}.xml` + ); +} diff --git a/packages/kbn-test/src/junit_report_path.ts b/packages/kbn-test/src/junit_report_path.ts deleted file mode 100644 index 90405d7a89c02..0000000000000 --- a/packages/kbn-test/src/junit_report_path.ts +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { resolve } from 'path'; -import { CI_PARALLEL_PROCESS_PREFIX } from './ci_parallel_process_prefix'; - -export function makeJunitReportPath(rootDirectory: string, reportName: string) { - return resolve( - rootDirectory, - 'target/junit', - process.env.JOB || '.', - `TEST-${CI_PARALLEL_PROCESS_PREFIX}${reportName}.xml` - ); -} diff --git a/packages/kbn-ui-framework/package.json b/packages/kbn-ui-framework/package.json index 363f97522a901..21d25311420ca 100644 --- a/packages/kbn-ui-framework/package.json +++ b/packages/kbn-ui-framework/package.json @@ -17,7 +17,7 @@ "dependencies": { "classnames": "2.2.6", "focus-trap-react": "^3.1.1", - "lodash": "^4.17.15", + "lodash": "^4.17.20", "prop-types": "^15.7.2", "react": "^16.12.0", "react-ace": "^5.9.0", @@ -30,15 +30,15 @@ "enzyme-adapter-react-16": "^1.9.1" }, "devDependencies": { - "@babel/core": "^7.11.1", - "@elastic/eui": "0.0.55", + "@babel/core": "^7.11.6", + "@elastic/eui": "29.3.0", "@kbn/babel-preset": "1.0.0", "@kbn/optimizer": "1.0.0", "babel-loader": "^8.0.6", "brace": "0.11.1", "chalk": "^4.1.0", - "chokidar": "3.2.1", - "core-js": "^3.6.4", + "chokidar": "^3.4.2", + "core-js": "^3.6.5", "css-loader": "^3.4.2", "expose-loader": "^0.7.5", "file-loader": "^4.2.0", @@ -58,11 +58,11 @@ "postcss-loader": "^3.0.0", "raw-loader": "^3.1.0", "react-dom": "^16.12.0", - "react-redux": "^5.1.2", - "react-router": "^3.2.0", + "react-redux": "^7.2.0", + "react-router": "^5.2.0", "react-router-redux": "^4.0.8", - "redux": "3.7.2", - "redux-thunk": "2.2.0", + "redux": "^4.0.5", + "redux-thunk": "^2.3.0", "regenerator-runtime": "^0.13.3", "sass-loader": "^8.0.2", "sinon": "^7.4.2", diff --git a/packages/kbn-ui-shared-deps/entry.js b/packages/kbn-ui-shared-deps/entry.js index 365b84b83bd5f..d74b45f973eb1 100644 --- a/packages/kbn-ui-shared-deps/entry.js +++ b/packages/kbn-ui-shared-deps/entry.js @@ -35,7 +35,6 @@ export const MonacoBarePluginApi = require('@kbn/monaco').BarePluginApi; export const React = require('react'); export const ReactDom = require('react-dom'); export const ReactDomServer = require('react-dom/server'); -export const ReactIntl = require('react-intl'); export const ReactRouter = require('react-router'); // eslint-disable-line export const ReactRouterDom = require('react-router-dom'); export const StyledComponents = require('styled-components'); @@ -51,6 +50,11 @@ export const ElasticEui = require('@elastic/eui'); export const ElasticEuiLibServices = require('@elastic/eui/lib/services'); export const ElasticEuiLibServicesFormat = require('@elastic/eui/lib/services/format'); export const ElasticEuiChartsTheme = require('@elastic/eui/dist/eui_charts_theme'); +export const Lodash = require('lodash'); +export const LodashFp = require('lodash/fp'); + +// runtime deps which don't need to be copied across all bundles +export const TsLib = require('tslib'); import * as Theme from './theme.ts'; export { Theme }; diff --git a/packages/kbn-ui-shared-deps/index.js b/packages/kbn-ui-shared-deps/index.js index 84ca3435e02bc..8f931fae4f337 100644 --- a/packages/kbn-ui-shared-deps/index.js +++ b/packages/kbn-ui-shared-deps/index.js @@ -39,7 +39,6 @@ exports.externals = { react: '__kbnSharedDeps__.React', 'react-dom': '__kbnSharedDeps__.ReactDom', 'react-dom/server': '__kbnSharedDeps__.ReactDomServer', - 'react-intl': '__kbnSharedDeps__.ReactIntl', 'react-router': '__kbnSharedDeps__.ReactRouter', 'react-router-dom': '__kbnSharedDeps__.ReactRouterDom', 'styled-components': '__kbnSharedDeps__.StyledComponents', @@ -62,5 +61,12 @@ exports.externals = { '@elastic/eui/dist/eui_charts_theme': '__kbnSharedDeps__.ElasticEuiChartsTheme', '@elastic/eui/dist/eui_theme_light.json': '__kbnSharedDeps__.Theme.euiLightVars', '@elastic/eui/dist/eui_theme_dark.json': '__kbnSharedDeps__.Theme.euiDarkVars', + lodash: '__kbnSharedDeps__.Lodash', + 'lodash/fp': '__kbnSharedDeps__.LodashFp', + + /** + * runtime deps which don't need to be copied across all bundles + */ + tslib: '__kbnSharedDeps__.TsLib', }; exports.publicPathLoader = require.resolve('./public_path_loader'); diff --git a/packages/kbn-ui-shared-deps/package.json b/packages/kbn-ui-shared-deps/package.json index 8095e05e8b855..0a154c537fec1 100644 --- a/packages/kbn-ui-shared-deps/package.json +++ b/packages/kbn-ui-shared-deps/package.json @@ -9,23 +9,23 @@ "kbn:watch": "node scripts/build --dev --watch" }, "dependencies": { - "@elastic/charts": "21.1.2", - "@elastic/eui": "28.4.0", + "@elastic/charts": "23.2.1", + "@elastic/eui": "29.3.0", "@elastic/numeral": "^2.5.0", "@kbn/i18n": "1.0.0", "@kbn/monaco": "1.0.0", "abortcontroller-polyfill": "^1.4.0", "angular": "^1.8.0", "compression-webpack-plugin": "^4.0.0", - "core-js": "^3.6.4", + "core-js": "^3.6.5", "custom-event-polyfill": "^0.3.0", "jquery": "^3.5.0", + "lodash": "^4.17.20", "mini-css-extract-plugin": "0.8.0", "moment": "^2.24.0", "moment-timezone": "^0.5.27", "react": "^16.12.0", "react-dom": "^16.12.0", - "react-intl": "^2.8.0", "react-is": "^16.8.0", "react-router": "^5.2.0", "react-router-dom": "^5.2.0", @@ -33,11 +33,13 @@ "rxjs": "^6.5.5", "styled-components": "^5.1.0", "symbol-observable": "^1.2.0", + "tslib": "^2.0.0", "whatwg-fetch": "^3.0.0" }, "devDependencies": { "@kbn/babel-preset": "1.0.0", "@kbn/dev-utils": "1.0.0", + "babel-plugin-transform-react-remove-prop-types": "^0.4.24", "css-loader": "^3.4.2", "del": "^5.1.0", "loader-utils": "^1.2.3", diff --git a/packages/kbn-ui-shared-deps/scripts/build.js b/packages/kbn-ui-shared-deps/scripts/build.js index af4e3481e624d..86251536b8876 100644 --- a/packages/kbn-ui-shared-deps/scripts/build.js +++ b/packages/kbn-ui-shared-deps/scripts/build.js @@ -18,18 +18,21 @@ */ const Path = require('path'); +const Fs = require('fs'); -const { run, createFailError } = require('@kbn/dev-utils'); +const { run, createFailError, CiStatsReporter } = 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(Path.resolve(__dirname, '../target')); + await del(DIST_DIR); const compiler = webpack( getWebpackConfig({ @@ -38,10 +41,38 @@ run( ); /** @param {webpack.Stats} stats */ - const onCompilationComplete = (stats) => { + const onCompilationComplete = async (stats) => { const took = Math.round((stats.endTime - stats.startTime) / 1000); if (!stats.hasErrors() && !stats.hasWarnings()) { + if (!flags.dev) { + const reporter = CiStatsReporter.fromEnv(log); + + const metrics = [ + { + group: '@kbn/ui-shared-deps asset size', + id: 'kbn-ui-shared-deps.js', + value: Fs.statSync(Path.resolve(DIST_DIR, 'kbn-ui-shared-deps.js')).size, + }, + { + group: '@kbn/ui-shared-deps asset size', + id: 'kbn-ui-shared-deps.@elastic.js', + value: Fs.statSync(Path.resolve(DIST_DIR, 'kbn-ui-shared-deps.@elastic.js')).size, + }, + { + group: '@kbn/ui-shared-deps asset size', + id: 'css', + value: + Fs.statSync(Path.resolve(DIST_DIR, 'kbn-ui-shared-deps.css')).size + + Fs.statSync(Path.resolve(DIST_DIR, 'kbn-ui-shared-deps.v7.light.css')).size, + }, + ]; + + log.debug('metrics:', metrics); + + await reporter.metrics(metrics); + } + log.success(`webpack completed in about ${took} seconds`); return; } @@ -56,11 +87,9 @@ run( if (flags.watch) { compiler.hooks.done.tap('report on stats', (stats) => { - try { - onCompilationComplete(stats); - } catch (error) { + onCompilationComplete(stats).catch((error) => { log.error(error.message); - } + }); }); compiler.hooks.watchRun.tap('report on start', () => { @@ -83,7 +112,7 @@ run( return; } - onCompilationComplete( + await onCompilationComplete( await new Promise((resolve, reject) => { compiler.run((error, stats) => { if (error) { diff --git a/packages/kbn-ui-shared-deps/webpack.config.js b/packages/kbn-ui-shared-deps/webpack.config.js index b7d4e929ac93f..986ddba209270 100644 --- a/packages/kbn-ui-shared-deps/webpack.config.js +++ b/packages/kbn-ui-shared-deps/webpack.config.js @@ -77,6 +77,25 @@ exports.getWebpackConfig = ({ dev = false } = {}) => ({ }, ], }, + { + test: !dev ? /[\\\/]@elastic[\\\/]eui[\\\/].*\.js$/ : () => false, + use: [ + { + loader: 'babel-loader', + options: { + plugins: [ + [ + require.resolve('babel-plugin-transform-react-remove-prop-types'), + { + mode: 'remove', + removeImport: true, + }, + ], + ], + }, + }, + ], + }, ], }, diff --git a/packages/kbn-utils/src/repo_root.ts b/packages/kbn-utils/src/repo_root.ts index b33b28d8d6e2f..ed3516a7304f9 100644 --- a/packages/kbn-utils/src/repo_root.ts +++ b/packages/kbn-utils/src/repo_root.ts @@ -22,38 +22,50 @@ import Fs from 'fs'; import loadJsonFile from 'load-json-file'; -const isKibanaDir = (dir: string) => { +const readKibanaPkgJson = (dir: string) => { try { const path = Path.resolve(dir, 'package.json'); const json = loadJsonFile.sync(path); if (json && typeof json === 'object' && 'name' in json && json.name === 'kibana') { - return true; + return json; } } catch (error) { if (error && error.code === 'ENOENT') { - return false; + return; } throw error; } }; -// search for the kibana directory, since this file is moved around it might -// not be where we think but should always be a relatively close parent -// of this directory -const startDir = Fs.realpathSync(__dirname); -const { root: rootDir } = Path.parse(startDir); -let cursor = startDir; -while (true) { - if (isKibanaDir(cursor)) { - break; - } +const findKibanaPackageJson = () => { + // search for the kibana directory, since this file is moved around it might + // not be where we think but should always be a relatively close parent + // of this directory + const startDir = Fs.realpathSync(__dirname); + const { root: rootDir } = Path.parse(startDir); + let cursor = startDir; + while (true) { + const kibanaPkgJson = readKibanaPkgJson(cursor); + if (kibanaPkgJson) { + return { + kibanaDir: cursor, + kibanaPkgJson: kibanaPkgJson as { + name: string; + branch: string; + }, + }; + } - const parent = Path.dirname(cursor); - if (parent === rootDir) { - throw new Error(`unable to find kibana directory from ${startDir}`); + const parent = Path.dirname(cursor); + if (parent === rootDir) { + throw new Error(`unable to find kibana directory from ${startDir}`); + } + cursor = parent; } - cursor = parent; -} +}; + +const { kibanaDir, kibanaPkgJson } = findKibanaPackageJson(); -export const REPO_ROOT = cursor; +export const REPO_ROOT = kibanaDir; +export const UPSTREAM_BRANCH = kibanaPkgJson.branch; diff --git a/plugins/.empty b/plugins/.empty new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/renovate.json5 b/renovate.json5 index 57d0fcb9f8ce2..17391c2f83827 100644 --- a/renovate.json5 +++ b/renovate.json5 @@ -27,31 +27,36 @@ ], }, separateMajorMinor: false, - masterIssue: false, + masterIssue: true, rangeStrategy: 'bump', + semanticCommits: false, + vulnerabilityAlerts: { + enabled: false, + }, npm: { lockFileMaintenance: { enabled: false, }, packageRules: [ - { - groupSlug: '@elastic/charts', - packageNames: ['@elastic/charts'], - reviewers: ['markov00'], - }, { packagePatterns: [ '.*', ], enabled: false, }, + { + groupName: '@elastic/charts', + packageNames: ['@elastic/charts'], + reviewers: ['markov00'], + enabled: true, + }, + { + groupName: 'vega related modules', + packageNames: ['vega', 'vega-lite', 'vega-schema-url-parser', 'vega-tooltip'], + reviewers: ['team:kibana-app'], + labels: ['Feature:Lens', 'Team:KibanaApp'], + enabled: true, + }, ], }, - prConcurrentLimit: 0, - vulnerabilityAlerts: { - enabled: false, - }, - rebaseStalePrs: false, - rebaseConflictedPrs: false, - semanticCommits: false, } diff --git a/rfcs/images/background_sessions_client.png b/rfcs/images/background_sessions_client.png new file mode 100644 index 0000000000000..46cb90c93aa32 Binary files /dev/null and b/rfcs/images/background_sessions_client.png differ diff --git a/rfcs/images/background_sessions_server.png b/rfcs/images/background_sessions_server.png new file mode 100644 index 0000000000000..593db3156f879 Binary files /dev/null and b/rfcs/images/background_sessions_server.png differ diff --git a/rfcs/text/0013_background_sessions.md b/rfcs/text/0013_background_sessions.md new file mode 100644 index 0000000000000..056149e770448 --- /dev/null +++ b/rfcs/text/0013_background_sessions.md @@ -0,0 +1,489 @@ +- Start Date: (fill me in with today's date, YYYY-MM-DD) +- RFC PR: (leave this empty) +- Kibana Issue: (leave this empty) + +- Architecture diagram: https://app.lucidchart.com/documents/edit/cf35b512-616a-4734-bc72-43dde70dbd44/0_0 +- Mockups: https://www.figma.com/proto/FD2M7MUpLScJKOyYjfbmev/ES-%2F-Query-Management-v4?node-id=440%3A1&viewport=984%2C-99%2C0.09413627535104752&scaling=scale-down +- Old issue: https://github.com/elastic/kibana/issues/53335 +- Background search roadmap: https://github.com/elastic/kibana/issues/61738 +- POC: https://github.com/elastic/kibana/pull/64641 + +# Summary + +Background Sessions will enable Kibana applications and solutions to start a group of related search requests (such as those coming from a single load of a dashboard or SIEM timeline), navigate away or close the browser, then retrieve the results when they have completed. + +# Basic example + +At its core, background sessions are enabled via several new APIs, that: +- Start a session, associating multiple search requests with a single entity +- Store the session (and continue search requests in the background) +- Restore the background session + +```ts +const searchService = dataPluginStart.search; + +if (appState.sessionId) { + // If we are restoring a session, set the session ID in the search service + searchService.session.restore(sessionId); +} else { + // Otherwise, start a new background session to associate our search requests + appState.sessionId = searchService.session.start(); +} + +// Search, passing in the generated session ID. +// If this is a new session, the `search_interceptor` will associate and keep track of the async search ID with the session ID. +// If this is a restored session, the server will immediately return saved results. +// In the case where there is no saved result for a given request, or if the results have expired, `search` will throw an error with a meaningful error code. +const request = buildKibanaRequest(...); +request.sessionId = searchService.session.get(); +const response$ = await searchService.search(request); + +// Calling `session.store()`, creates a saved object for this session, allowing the user to navigate away. +// The session object will be saved with all async search IDs that were executed so far. +// Any follow up searches executed with this sessionId will be saved into this object as well. +const backgroundSession = await searchService.session.store(); +``` + +# Motivation + +Kibana is great at providing fast results from large sets of "hot" data. However, there is an increasing number of use cases where users want to analyze large amounts of "colder" data (such as year-over-year reports, historical or audit data, batch queries, etc.). + +For these cases, users run into two limitations: + 1. Kibana has a default timeout of 30s per search. This is controlled by the `elasticsearch.requestTimeout` setting (originally intended to protect clusters from unintentional overload by a single query). + 2. Kibana cancels queries upon navigating away from an application, once again, as means of protecting clusters and reducing unnecessary load. + +In 7.7, with the introduction of the `_async_search` API in Elasticsearch, we provided Kibana users a way to bypass the timeout, but users still need to remain on-screen for the entire duration of the search requests. + +The primary motivation of this RFC is to enable users to do the following without needing to keep Kibana open, or while moving onto other work inside Kibana: + +- Run long search requests (beyond 30 seconds) +- View their status (complete/incomplete) +- Cancel incomplete search requests +- Retrieve completed search request results + +# Detailed design + +Because a single view (such as a dashboard with multiple visualizations) can initiate multiple search requests, we need a way to associate the search requests together in a single entity. + +We call this entity a `session`, and when a user decides that they want to continue running the search requests while moving onto other work, we will create a saved object corresponding with that specific `session`, persisting the *sessionId* along with a mapping of each *request's hash* to the *async ID* returned by Elasticsearch. + +## High Level Flow Charts + +### Client side search + +This diagram matches any case where `data.search` is called from the front end: + +![image](../images/background_sessions_client.png) + +### Server side search + +This case happens if the server is the one to invoke the `data.search` endpoint, for example with TSVB. + +![image](../images/background_sessions_server.png) + +## Data and Saved Objects + +### Background Session Status + +```ts +export enum BackgroundSessionStatus { + Running, // The session has at least one running search ID associated with it. + Done, // All search IDs associated with this session have completed. + Error, // At least one search ID associated with this session had an error. + Expired, // The session has expired. Associated search ID data was cleared from ES. +} +``` + +### Saved Object Structure + +The saved object created for a background session will be scoped to a single space, and will be a `hidden` saved object +(so that it doesn't show in the management listings). We will provide a separate interface for users to manage their own +background sessions (which will use the `list`, `expire`, and `extend` methods described below, which will be restricted +per-user). + +```ts +interface BackgroundSessionAttributes extends SavedObjectAttributes { + sessionId: string; + userId: string; // Something unique to the user who generated this session, like username/realm-name/realm-type + status: BackgroundSessionStatus; + name: string; + creation: Date; + expiration: Date; + idMapping: { [key: string]: string }; + url: string; // A URL relative to the Kibana root to retrieve the results of a completed background session (and/or to return to an incomplete view) + metadata: { [key: string]: any } // Any data the specific application requires to restore a background session view +} +``` + +The URL that is provided will need to be generated by the specific application implementing background sessions. We +recommend using the URL generator to ensure that URLs are backwards-compatible since background sessions may exist as +long as a user continues to extend the expiration. + +## Frontend Services + +Most sessions will probably not be saved. Therefore, to avoid creating unnecessary saved objects, the browser will keep track of requests and their respective search IDs, until the user chooses to store the session. Once a session is stored, any additional searches will be immediately saved on the server side. + +### New Session Service + +We will expose a new frontend `session` service on the `data` plugin `search` service. + +The service will expose the following APIs: + +```ts +interface ISessionService { + /** + * Returns the current session ID + */ + getActiveSessionId: () => string; + + /** + * Sets the current session + * @param sessionId: The ID of the session to set + * @param isRestored: Whether or not the session is being restored + */ + setActiveSessionId: (sessionId: string, isRestored: boolean) => void; + + /** + * Start a new session, by generating a new session ID (calls `setActiveSessionId` internally) + */ + start: () => string; + + /** + * Store a session, alongside with any tracked searchIds. + * @param sessionId Session ID to store. Probably retrieved from `sessionService.get()`. + * @param name A display name for the session. + * @param url TODO: is the URL provided here? How? + * @returns The stored `BackgroundSessionAttributes` object + * @throws Throws an error in OSS. + */ + store: (sessionId: string, name: string, url: string) => Promise + + /** + * @returns Is the current session stored (i.e. is there a saved object corresponding with this sessionId). + */ + isStored: () => boolean; + + /** + * @returns Is the current session a restored session + */ + isRestored: () => boolean; + + /** + * Mark a session and and all associated searchIds as expired. + * Cancels active requests, if there are any. + * @param sessionId Session ID to store. Probably retrieved from `sessionService.get()`. + * @returns success status + * @throws Throws an error in OSS. + */ + expire: (sessionId: string) => Promise + + /** + * Extend a session and all associated searchIds. + * @param sessionId Session ID to extend. Probably retrieved from `sessionService.get()`. + * @param extendBy Time to extend by, can be a relative or absolute string. + * @returns success status + * @throws Throws an error in OSS. + */ + extend: (sessionId: string, extendBy: string)=> Promise + + /** + * @param sessionId the ID of the session to retrieve the saved object. + * @returns a filtered list of BackgroundSessionAttributes objects. + * @throws Throws an error in OSS. + */ + get: (sessionId: string) => Promise + + /** + * @param options The options to query for specific background session saved objects. + * @returns a filtered list of BackgroundSessionAttributes objects. + * @throws Throws an error in OSS. + */ + list: (options: SavedObjectsFindOptions) => Promise + + /** + * Clears out any session info as well as the current session. Called internally whenever the user navigates + * between applications. + * @internal + */ + clear: () => void; + + /** + * Track a search ID of a sessionId, if it exists. Called internally by the search service. + * @param sessionId + * @param request + * @param searchId + * @internal + */ + trackSearchId: ( + sessionId: string, + request: IKibanaSearchRequest, + searchId: string, + ) => Promise +} +``` + +## Backend Services and Routes + +The server side's feature implementation builds on how Elasticsearch's `async_search` endpoint works. When making an +initial new request to Elasticsearch, it returns a search ID that can be later used to retrieve the results. + +The server will then store that `request`, `sessionId`, and `searchId` in a mapping in memory, and periodically query +for a saved object corresponding with that session. If the saved object is found, it will update the saved object to +include this `request`/`searchId` combination, and remove it from memory. If, after a period of time (5 minutes?) the +saved object has not been found, we will stop polling for that `sessionId` and remove the `request`/`searchId` from +memory. + +When the server receives a search request that has a `sessionId` and is marked as a `restore` request, the server will +attempt to find the correct id within the saved object, and use it to retrieve the results previously saved. + +### New Session Service + +```ts +interface ISessionService { + /** + * Adds a search ID to a Background Session, if it exists. + * Also extends the expiration of the search ID to match the session's expiration. + * @param request + * @param sessionId + * @param searchId + * @returns true if id was added, false if Background Session doesn't exist or if there was an error while updating. + * @throws an error if `searchId` already exists in the mapping for this `sessionId` + */ + trackSearchId: ( + request: KibanaRequest, + sessionId: string, + searchId: string, + ) => Promise + + /** + * Get a Background Session object. + * @param request + * @param sessionId + * @returns the Background Session object if exists, or undefined. + */ + get: async ( + request: KibanaRequest, + sessionId: string + ) => Promise + + /** + * Get a searchId from a Background Session object. + * @param request + * @param sessionId + * @returns the searchID if exists on the Background Session, or undefined. + */ + getSearchId: async ( + request: KibanaRequest, + sessionId: string + ) => Promise + + /** + * Store a session. + * @param request + * @param sessionId Session ID to store. Probably retrieved from `sessionService.get()`. + * @param searchIdMap A mapping of hashed requests mapped to the corresponding searchId. + * @param url TODO: is the URL provided here? How? + * @returns The stored `BackgroundSessionAttributes` object + * @throws Throws an error in OSS. + * @internal (Consumers should use searchInterceptor.sendToBackground()) + */ + store: ( + request: KibanaRequest, + sessionId: string, + name: string, + url: string, + searchIdMapping?: Record + ) => Promise + + /** + * Mark a session as and all associated searchIds as expired. + * @param request + * @param sessionId + * @returns success status + * @throws Throws an error in OSS. + */ + expire: async ( + request: KibanaRequest, + sessionId: string + ) => Promise + + /** + * Extend a session and all associated searchIds. + * @param request + * @param sessionId + * @param extendBy Time to extend by, can be a relative or absolute string. + * @returns success status + * @throws Throws an error in OSS. + */ + extend: async ( + request: KibanaRequest, + sessionId: string, + extendBy: string, + ) => Promise + + /** + * Get a list of background session objects. + * @param request + * @param sessionId + * @returns success status + * @throws Throws an error in OSS. + */ + list: async ( + request: KibanaRequest, + ) => Promise + + /** + * Update the status of a given session + * @param request + * @param sessionId + * @param status + * @returns success status + * @throws Throws an error in OSS. + */ + updateStatus: async ( + request: KibanaRequest, + sessionId: string, + status: BackgroundSessionStatus + ) => Promise +} + +``` + +### Search Service Changes + +There are cases where search requests are issued by the server (Like TSVB). +We can simplify this flow by introducing a mechanism, similar to the frontend one, tracking the information in memory and polling for a saved object with a corresponding sessionId to store the ids into it. + +```ts +interface SearchService { + /** + * The search API will accept the option `trackId`, which will track the search ID, if available, on the server, until a corresponding saved object is created. + **/ + search: async ( + context: RequestHandlerContext, + request: IEnhancedEsSearchRequest, + options?: ISearchOptions + ) => ISearchResponse +} +``` + +### Server Routes + +Each route exposes the corresponding method from the Session Service (used only by the client-side service, not meant to be used directly by any consumers): + +`POST /internal/session/store` + +`POST /internal/session/extend` + +`POST /internal/session/expire` + +`GET /internal/session/list` + +### Search Strategy Integration + +If the `EnhancedEsSearchStrategy` receives a `restore` option, it will attempt reloading data using the Background Session saved object matching the provided `sessionId`. If there are any errors during that process, the strategy will return an error response and *not attempt to re-run the request. + +The strategy will track the asyncId on the server side, if `trackId` option is provided. + +### Monitoring Service + +The `data` plugin will register a task with the task manager, periodically monitoring the status of incomplete background sessions. + +It will query the list of all incomplete sessions, and check the status of each search that is executing. If the search requests are all complete, it will update the corresponding saved object to have a `status` of `complete`. If any of the searches return an error, it will update the saved object to an `error` state. If the search requests have expired, it will update the saved object to an `expired` state. Expired sessions will be purged once they are older than the time definedby the `EXPIRED_SESSION_TTL` advanced setting. + +Once there's a notification area in Kibana, we may use that mechanism to push completion \ error notifications to the client. + +## Miscellaneous + +#### Relative dates and restore URLs + +Restoring a sessionId depends on each request's `sha-256` hash matching exactly to the ones saved, requiring special attention to relative date ranges, as having these might yield ambiguous results. + +There are two potential scenarios: + - A relative date (for example `now-1d`) is being used in query DSL - In this case any future hash will match, but the returned data *won't match the displayed timeframe*. For example, a report might state that it shows data from yesterday, but actually show data from a week ago. + - A relative date is being translated by the application before being set to the query DSL - In this case a different date will be sent and the hash will never match, resulting in an error restoring the dashboard. + +Both scenarios require careful attention during the UI design and implementation. + +The former can be resolved by clearly displaying the creation time of the restored Background Session. We could also attempt translating relative dates to absolute one's, but this might be challenging as relative dates may appear deeply nested within the DSL. + +The latter case happens at the moment for the timepicker only: The relative date is being translated each time into an absolute one, before being sent to Elasticsearch. In order to avoid issues, we'll have to make sure that restore URLs are generated with an absolute date, to make sure they are restored correctly. + +#### Changing a restored session + +If you have restored a Background Session, making any type of change to it (time range, filters, etc.) will trigger new (potentially long) searches. There should be a clear indication in the UI that the data is no longer stored. A user then may choose to send it to background, resulting in a new Background Session being saved. + +#### Loading an errored \ expired \ canceled session + +When trying to restore a Background Session, if any of the requests hashes don't match the ones saved, or if any of the saved async search IDs are expired, a meaningful error code will be returned by the server **by those requests**. It is each application's responsibility to handle these errors appropriately. + +In such a scenario, the session will be partially restored. + +#### Extending Expiration + +Sessions are given an expiration date defined in an advanced setting (5 days by default). This expiration date is measured from the time the Background Session is saved, and it includes the time it takes to generate the results. + +A session's expiration date may be extended indefinitely. However, if a session was canceled or has already expired, it needs to be re-run. + +# Limitations + +In the first iteration, cases which require multiple search requests to be made serially will not be supported. The +following are examples of such scenarios: + +- When a visualization is configured with a terms agg with an "other" bucket +- When using blended layers or term joins in Maps + +Eventually, when expressions can be run on the server, they will run in the context of a specific `sessionId`, hence enabling those edge cases too. + +# Drawbacks + +One drawback of this approach is that we will be regularly polling Elasticsearch for saved objects, which will increase +load on the Elasticsearch server, in addition to the Kibana server (since all server-side processes share the same event +loop). We've opened https://github.com/elastic/kibana/issues/77293 to track this, and hopefully come up with benchmarks +so we feel comfortable moving forward with this approach. + +Two potential drawbacks stem from storing things in server memory. If a Kibana server is restarted, in-memory results +will be lost. (This can be an issue if a search request has started, and the user has sent to background, but the +background session saved object has not yet been updated with the search request ID.) In such cases, the user interface +will need to indicate errors for requests that were not stored in the saved object. + +There is also the consideration of the memory footprint of the Kibana server; however, since +we are only storing a hash of the request and search request ID, and are periodically cleaning it up (see Backend +Services and Routes), we do not anticipate the footprint to increase significantly. + +The results of search requests that have been sent to the background will be stored in Elasticsearch for several days, +even if they will only be retrieved once. This will be mitigated by allowing the user manually delete a background +session object after it has been accessed. + +# Alternatives + +What other designs have been considered? What is the impact of not doing this? + +# Adoption strategy + +(See "Basic example" above.) + +Any application or solution that uses the `data` plugin `search` services will be able to facilitate background sessions +fairly simply. The public side will need to create/clear sessions when appropriate, and ensure the `sessionId` is sent +with all search requests. It will also need to ensure that any necessary application data, as well as a `restoreUrl` is +sent when creating the saved object. + +The server side will just need to ensure that the `sessionId` is sent to the `search` service. If bypassing the `search` +service, it will need to also call `trackSearchId` when the first response is received, and `getSearchId` when restoring +the view. + +# How we teach this + +What names and terminology work best for these concepts and why? How is this +idea best presented? As a continuation of existing Kibana patterns? + +Would the acceptance of this proposal mean the Kibana documentation must be +re-organized or altered? Does it change how Kibana is taught to new developers +at any level? + +How should this feature be taught to existing Kibana developers? + +# Unresolved questions + +Optional, but suggested for first drafts. What parts of the design are still +TBD? diff --git a/rfcs/text/0013_saved_object_migrations.md b/rfcs/text/0013_saved_object_migrations.md new file mode 100644 index 0000000000000..c5069625cb8a6 --- /dev/null +++ b/rfcs/text/0013_saved_object_migrations.md @@ -0,0 +1,745 @@ +- Start Date: 2020-05-11 +- RFC PR: (leave this empty) +- Kibana Issue: (leave this empty) + +--- +- [1. Summary](#1-summary) +- [2. Motivation](#2-motivation) +- [3. Saved Object Migration Errors](#3-saved-object-migration-errors) +- [4. Design](#4-design) + - [4.0 Assumptions and tradeoffs](#40-assumptions-and-tradeoffs) + - [4.1 Discover and remedy potential failures before any downtime](#41-discover-and-remedy-potential-failures-before-any-downtime) + - [4.2 Automatically retry failed migrations until they succeed](#42-automatically-retry-failed-migrations-until-they-succeed) + - [4.2.1 Idempotent migrations performed without coordination](#421-idempotent-migrations-performed-without-coordination) + - [4.2.1.1 Restrictions](#4211-restrictions) + - [4.2.1.2 Migration algorithm: Cloned index per version](#4212-migration-algorithm-cloned-index-per-version) + - [4.2.1.3 Upgrade and rollback procedure](#4213-upgrade-and-rollback-procedure) + - [4.2.1.4 Handling documents that belong to a disabled plugin](#4214-handling-documents-that-belong-to-a-disabled-plugin) +- [5. Alternatives](#5-alternatives) + - [5.1 Rolling upgrades](#51-rolling-upgrades) + - [5.2 Single node migrations coordinated through a lease/lock](#52-single-node-migrations-coordinated-through-a-leaselock) + - [5.2.1 Migration algorithm](#521-migration-algorithm) + - [5.2.2 Document lock algorithm](#522-document-lock-algorithm) + - [5.2.3 Checking for "weak lease" expiry](#523-checking-for-weak-lease-expiry) + - [5.3 Minimize data loss with mixed Kibana versions during 7.x](#53-minimize-data-loss-with-mixed-kibana-versions-during-7x) + - [5.4 In-place migrations that re-use the same index (8.0)](#54-in-place-migrations-that-re-use-the-same-index-80) + - [5.4.1 Migration algorithm (8.0):](#541-migration-algorithm-80) + - [5.4.2 Minimizing data loss with unsupported upgrade configurations (8.0)](#542-minimizing-data-loss-with-unsupported-upgrade-configurations-80) + - [5.5 Tag objects as “invalid” if their transformation fails](#55-tag-objects-as-invalid-if-their-transformation-fails) +- [6. How we teach this](#6-how-we-teach-this) +- [7. Unresolved questions](#7-unresolved-questions) + +# 1. Summary + +Improve the Saved Object migration algorithm to ensure a smooth Kibana upgrade +procedure. + +# 2. Motivation + +Kibana version upgrades should have a minimal operational impact. To achieve +this, users should be able to rely on: + +1. A predictable downtime window. +2. A small downtime window. + 1. (future) provide a small downtime window on indices with 10k or even + a 100k documents. +3. The ability to discover and remedy potential failures before initiating the + downtime window. +4. Quick roll-back in case of failure. +5. Detailed documentation about the impact of downtime on the features they + are using (e.g. actions, task manager, fleet, reporting). +6. Mixed Kibana versions shouldn’t cause data loss. +7. (stretch goal) Maintain read-only functionality during the downtime window. + +The biggest hurdle to achieving the above is Kibana’s Saved Object migrations. +Migrations aren’t resilient and require manual intervention anytime an error +occurs (see [3. Saved Object Migration +Errors](#3-saved-object-migration-errors)). + +It is impossible to discover these failures before initiating downtime. Errors +often force users to roll-back to a previous version of Kibana or cause hours +of downtime. To retry the migration, users are asked to manually delete a +`.kibana_x` index. If done incorrectly this can lead to data loss, making it a +terrifying experience (restoring from a pre-upgrade snapshot is a safer +alternative but not mentioned in the docs or logs). + +Cloud users don’t have access to Kibana logs to be able to identify and remedy +the cause of the migration failure. Apart from blindly retrying migrations by +restoring a previous snapshot, cloud users are unable to remedy a failed +migration and have to escalate to support which can further delay resolution. + +Taken together, version upgrades are a major operational risk and discourage +users from adopting the latest features. + +# 3. Saved Object Migration Errors + +Any of the following classes of errors could result in a Saved Object +migration failure which requires manual intervention to resolve: + +1. A bug in a plugin’s registered document transformation function causes it + to throw an exception on _valid_ data. +2. _Invalid_ data stored in Elasticsearch causes a plugin’s registered + document transformation function to throw an exception . +3. Failures resulting from an unhealthy Elasticsearch cluster: + 1. Maximum shards open + 2. Too many scroll contexts + 3. `circuit_breaking_exception` (insufficient heap memory) + 4. `process_cluster_event_timeout_exception` for index-aliases, create-index, put-mappings + 5. Read-only indices due to low disk space (hitting the flood_stage watermark) + 6. Re-index failed: search rejected due to missing shards + 7. `TooManyRequests` while doing a `count` of documents requiring a migration + 8. Bulk write failed: primary shard is not active +4. The Kibana process is killed while migrations are in progress. + +# 4. Design +## 4.0 Assumptions and tradeoffs +The proposed design makes several important assumptions and tradeoffs. + +**Background:** + +The 7.x upgrade documentation lists taking an Elasticsearch snapshot as a +required step, but we instruct users to retry migrations and perform rollbacks +by deleting the failed `.kibana_n` index and pointing the `.kibana` alias to +`.kibana_n-1`: + - [Handling errors during saved object +migrations.](https://github.com/elastic/kibana/blob/75444a9f1879c5702f9f2b8ad4a70a3a0e75871d/docs/setup/upgrade/upgrade-migrations.asciidoc#handling-errors-during-saved-object-migrations) + - [Rolling back to a previous version of Kibana.](https://github.com/elastic/kibana/blob/75444a9f1879c5702f9f2b8ad4a70a3a0e75871d/docs/setup/upgrade/upgrade-migrations.asciidoc#rolling-back-to-a-previous-version-of-kib) + - Server logs from failed migrations. + +**Assumptions and tradeoffs:** +1. It is critical to maintain a backup index during 7.x to ensure that anyone + following the existing upgrade / rollback procedures don't end up in a + position where they no longer can recover their data. + 1. This excludes us from introducing in-place migrations to support huge + indices during 7.x. +2. The simplicity of idempotent, coordination-free migrations outweighs the + restrictions this will impose on the kinds of migrations we're able to + support in the future. See (4.2.1) +3. A saved object type (and it's associated migrations) will only ever be + owned by one plugin. If pluginA registers saved object type `plugin_a_type` + then pluginB must never register that same type, even if pluginA is + disabled. Although we cannot enforce it on third-party plugins, breaking + this assumption may lead to data loss. + +## 4.1 Discover and remedy potential failures before any downtime + +> Achieves goals: (2.3) +> Mitigates errors: (3.1), (3.2) + +1. Introduce a CLI option to perform a dry run migration to allow + administrators to locate and fix potential migration failures without + taking their existing Kibana node(s) offline. +2. To have the highest chance of surfacing potential failures such as low disk + space, dry run migrations should not be mere simulations. A dry run should + perform a real migration in a way that doesn’t impact the existing Kibana + cluster. +3. The CLI should generate a migration report to make it easy to create a + support request from a failed migration dry run. + 1. The report would be an NDJSON export of all failed objects. + 2. If support receives such a report, we could modify all the objects to + ensure the migration would pass and send this back to the client. + 3. The client can then import the updated objects using the standard Saved + Objects NDJSON import and run another dry run to verify all problems + have been fixed. +4. Make running dry run migrations a required step in the upgrade procedure + documentation. +5. (Optional) Add dry run migrations to the standard cloud upgrade procedure? + +## 4.2 Automatically retry failed migrations until they succeed + +> Achieves goals: (2.2), (2.6) +> Mitigates errors (3.3) and (3.4) + +External conditions such as failures from an unhealthy Elasticsearch cluster +(3.3) can cause the migration to fail. The Kibana cluster should be able to +recover automatically once these external conditions are resolved. There are +two broad approaches to solving this problem based on whether or not +migrations are idempotent: + +| Idempotent migrations |Description | +| --------------------- | --------------------------------------------------------- | +| Yes | Idempotent migrations performed without coordination | +| No | Single node migrations coordinated through a lease / lock | + +Idempotent migrations don't require coordination making the algorithm +significantly less complex and will never require manual intervention to +retry. We, therefore, prefer this solution, even though it introduces +restrictions on migrations (4.2.1.1). For other alternatives that were +considered see section [(5)](#5-alternatives). + +## 4.2.1 Idempotent migrations performed without coordination + +The migration system can be said to be idempotent if the same results are +produced whether the migration was run once or multiple times. This property +should hold even if new (up to date) writes occur in between migration runs +which introduces the following restrictions: + +### 4.2.1.1 Restrictions + +1. All document transforms need to be deterministic, that is a document + transform will always return the same result for the same set of inputs. +2. It should always be possible to construct the exact set of inputs required + for (1) at any point during the migration process (before, during, after). + +Although these restrictions require significant changes, it does not prevent +known upcoming migrations such as [sharing saved-objects in multiple spaces](https://github.com/elastic/kibana/issues/27004) or [splitting a saved +object into multiple child +documents](https://github.com/elastic/kibana/issues/26602). To ensure that +these migrations are idempotent, they will have to generate new saved object +id's deterministically with e.g. UUIDv5. + + +### 4.2.1.2 Migration algorithm: Cloned index per version +Note: +- The description below assumes the migration algorithm is released in 7.10.0. + So < 7.10.0 will use `.kibana` and >= 7.10.0 will use `.kibana_current`. +- We refer to the alias and index that outdated nodes use as the source alias + and source index. +- Every version performs a migration even if mappings or documents aren't outdated. + +1. Locate the source index by fetching aliases (including `.kibana` for + versions prior to v7.10.0) + + ``` + GET '/_alias/.kibana_current,.kibana_7.10.0,.kibana' + ``` + + The source index is: + 1. the index the `.kibana_current` alias points to, or if it doesn’t exist, + 2. the index the `.kibana` alias points to, or if it doesn't exist, + 3. the v6.x `.kibana` index + + If none of the aliases exists, this is a new Elasticsearch cluster and no + migrations are necessary. Create the `.kibana_7.10.0_001` index with the + following aliases: `.kibana_current` and `.kibana_7.10.0`. +2. If `.kibana_current` and `.kibana_7.10.0` both exists and are pointing to the same index this version's migration has already been completed. + 1. Because the same version can have plugins enabled at any point in time, + perform the mappings update in step (6) and migrate outdated documents + with step (7). + 2. Skip to step (9) to start serving traffic. +3. Fail the migration if: + 1. `.kibana_current` is pointing to an index that belongs to a later version of Kibana .e.g. `.kibana_7.12.0_001` + 2. (Only in 8.x) The source index contains documents that belong to an unknown Saved Object type (from a disabled plugin). Log an error explaining that the plugin that created these documents needs to be enabled again or that these objects should be deleted. See section (4.2.1.4). +4. Mark the source index as read-only and wait for all in-flight operations to drain (requires https://github.com/elastic/elasticsearch/pull/58094). This prevents any further writes from outdated nodes. Assuming this API is similar to the existing `//_close` API, we expect to receive `"acknowledged" : true` and `"shards_acknowledged" : true`. If all shards don’t acknowledge within the timeout, retry the operation until it succeeds. +5. Clone the source index into a new target index which has writes enabled. All nodes on the same version will use the same fixed index name e.g. `.kibana_7.10.0_001`. The `001` postfix isn't used by Kibana, but allows for re-indexing an index should this be required by an Elasticsearch upgrade. E.g. re-index `.kibana_7.10.0_001` into `.kibana_7.10.0_002` and point the `.kibana_7.10.0` alias to `.kibana_7.10.0_002`. + 1. `POST /.kibana_n/_clone/.kibana_7.10.0_001?wait_for_active_shards=all {"settings": {"index.blocks.write": false}}`. Ignore errors if the clone already exists. + 2. Wait for the cloning to complete `GET /_cluster/health/.kibana_7.10.0_001?wait_for_status=green&timeout=60s` If cloning doesn’t complete within the 60s timeout, log a warning for visibility and poll again. +6. Update the mappings of the target index + 1. Retrieve the existing mappings including the `migrationMappingPropertyHashes` metadata. + 2. Update the mappings with `PUT /.kibana_7.10.0_001/_mapping`. The API deeply merges any updates so this won't remove the mappings of any plugins that were enabled in a previous version but are now disabled. + 3. Ensure that fields are correctly indexed using the target index's latest mappings `POST /.kibana_7.10.0_001/_update_by_query?conflicts=proceed`. In the future we could optimize this query by only targeting documents: + 1. That belong to a known saved object type. + 2. Which don't have outdated migrationVersion numbers since these will be transformed anyway. + 3. That belong to a type whose mappings were changed by comparing the `migrationMappingPropertyHashes`. (Metadata, unlike the mappings isn't commutative, so there is a small chance that the metadata hashes do not accurately reflect the latest mappings, however, this will just result in an less efficient query). +7. Transform documents by reading batches of outdated documents from the target index then transforming and updating them with optimistic concurrency control. + 1. Ignore any version conflict errors. + 2. If a document transform throws an exception, add the document to a failure list and continue trying to transform all other documents. If any failures occured, log the complete list of documents that failed to transform. Fail the migration. +8. Mark the migration as complete by doing a single atomic operation (requires https://github.com/elastic/elasticsearch/pull/58100) that: + 1. Checks that `.kibana-current` alias is still pointing to the source index + 2. Points the `.kibana-7.10.0` and `.kibana_current` aliases to the target index. + 3. If this fails with a "required alias [.kibana_current] does not exist" error fetch `.kibana_current` again: + 1. If `.kibana_current` is _not_ pointing to our target index fail the migration. + 2. If `.kibana_current` is pointing to our target index the migration has succeeded and we can proceed to step (9). +9. Start serving traffic. + +Together with the limitations, this algorithm ensures that migrations are +idempotent. If two nodes are started simultaneously, both of them will start +transforming documents in that version's target index, but because migrations are idempotent, it doesn’t matter which node’s writes win. + +
+ In the future, this algorithm could enable (2.6) "read-only functionality during the downtime window" but this is outside of the scope of this RFC. + + Although the migration algorithm guarantees there's no data loss while providing read-only access to outdated nodes, this could cause plugins to behave in unexpected ways. If we wish to persue it in the future, enabling read-only functionality during the downtime window will be it's own project and must include an audit of all plugins' behaviours. +
+ +### 4.2.1.3 Upgrade and rollback procedure +When a newer Kibana starts an upgrade, it blocks all writes to the outdated index to prevent data loss. Since Kibana is not designed to gracefully handle a read-only index this could have unintended consequences such as a task executing multiple times but never being able to write that the task was completed successfully. To prevent unintended consequences, the following procedure should be followed when upgrading Kibana: + +1. Gracefully shutdown outdated nodes by sending a `SIGTERM` signal + 1. Node starts returning `503` from it's healthcheck endpoint to signal to + the load balancer that it's no longer accepting new traffic (requires https://github.com/elastic/kibana/issues/46984). + 2. Allows ungoing HTTP requests to complete with a configurable timeout + before forcefully terminating any open connections. + 3. Closes any keep-alive sockets by sending a `connection: close` header. + 4. Shutdown all plugins and Core services. +2. (recommended) Take a snapshot of all Kibana's Saved Objects indices. This simplifies doing a rollback to a simple snapshot restore, but is not required in order to do a rollback if a migration fails. +3. Start the upgraded Kibana nodes. All running Kibana nodes should be on the same version, have the same plugins enabled and use the same configuration. + +To rollback to a previous version of Kibana with a snapshot +1. Shutdown all Kibana nodes. +2. Restore the Saved Object indices and aliases from the snapshot +3. Start the rollback Kibana nodes. All running Kibana nodes should be on the same rollback version, have the same plugins enabled and use the same configuration. + +To rollback to a previous version of Kibana without a snapshot: +(Assumes the migration to 7.11.0 failed) +1. Shutdown all Kibana nodes. +2. Remove the index created by the failed Kibana migration by using the version-specific alias e.g. `DELETE /.kibana_7.11.0` +3. Identify the rollback index: + 1. If rolling back to a Kibana version < 7.10.0 use `.kibana` + 2. If rolling back to a Kibana version >= 7.10.0 use the version alias of the Kibana version you wish to rollback to e.g. `.kibana_7.10.0` +4. Point the `.kibana_current` alias to the rollback index. +5. Remove the write block from the rollback index. +6. Start the rollback Kibana nodes. All running Kibana nodes should be on the same rollback version, have the same plugins enabled and use the same configuration. + +### 4.2.1.4 Handling documents that belong to a disabled plugin +It is possible for a plugin to create documents in one version of Kibana, but then when upgrading Kibana to a newer version, that plugin is disabled. Because the plugin is disabled it cannot register it's Saved Objects type including the mappings or any migration transformation functions. These "orphan" documents could cause future problems: + - A major version introduces breaking mapping changes that cannot be applied to the data in these documents. + - Two majors later migrations will no longer be able to migrate this old schema and could fail unexpectadly when the plugin is suddenly enabled. + +As a concrete example of the above, consider a user taking the following steps: +1. Installs Kibana 7.6.0 with spaces=enabled. The spaces plugin creates a default space saved object. +2. User upgrades to 7.10.0 but uses the OSS download which has spaces=disabled. Although the 7.10.0 spaces plugin includes a migration for space documents, the OSS release cannot migrate the documents or update it's mappings. +3. User realizes they made a mistake and use Kibana 7.10.0 with x-pack and the spaces plugin enabled. At this point we have a completed migration for 7.10.0 but there's outdated spaces documents with migrationVersion=7.6.0 instead of 7.10.0. + +There are several approaches we could take to dealing with these orphan documents: + +1. Start up but refuse to query on types with outdated documents until a user manually triggers a re-migration + + Advantages: + - The impact is limited to a single plugin + + Disadvantages: + - It might be less obvious that a plugin is in a degraded state unless you read the logs (not possible on Cloud) or view the `/status` endpoint. + - If a user doesn't care that the plugin is degraded, orphan documents are carried forward indefinitely. + - Since Kibana has started receiving traffic, users can no longer + downgrade without losing data. They have to re-migrate, but if that + fails they're stuck. + - Introduces a breaking change in the upgrade behaviour + + To perform a re-migration: + - Remove the `.kibana_7.10.0` alias + - Take a snapshot OR set the configuration option `migrations.target_index_postfix: '002'` to create a new target index `.kibana_7.10.0_002` and keep the `.kibana_7.10.0_001` index to be able to perform a rollback. + - Start up Kibana + +2. Refuse to start Kibana until the plugin is enabled or it's data deleted + + Advantages: + - Admin’s are forced to deal with the problem as soon as they disable a plugin + + Disadvantages: + - Cannot temporarily disable a plugin to aid in debugging or to reduce the load a Kibana plugin places on an ES cluster. + - Introduces a breaking change + +3. Refuse to start a migration until the plugin is enabled or it's data deleted + + Advantages: + - We force users to enable a plugin or delete the documents which prevents these documents from creating future problems like a mapping update not being compatible because there are fields which are assumed to have been migrated. + - We keep the index “clean”. + + Disadvantages: + - Since users have to take down outdated nodes before they can start the upgrade, they have to enter the downtime window before they know about this problem. This prolongs the downtime window and in many cases might cause an operations team to have to reschedule their downtime window to give them time to investigate the documents that need to be deleted. Logging an error on every startup could warn users ahead of time to mitigate this. + - We don’t expose Kibana logs on Cloud so this will have to be escalated to support and could take 48hrs to resolve (users can safely rollback, but without visibility into the logs they might not know this). Exposing Kibana logs is on the cloud team’s roadmap. + - It might not be obvious just from the saved object type, which plugin created these objects. + - Introduces a breaking change in the upgrade behaviour + +4. Use a hash of enabled plugins as part of the target index name + Using a migration target index name like + `.kibana_7.10.0_${hash(enabled_plugins)}_001` we can migrate all documents + every time a plugin is enabled / disabled. + + Advantages: + - Outdated documents belonging to disabled plugins will be upgraded as soon + as the plugin is enabled again. + + Disadvantages: + - Disabling / enabling a plugin will cause downtime (breaking change). + - When a plugin is enabled, disabled and enabled again our target index + will be an existing outdated index which needs to be deleted and + re-cloned. Without a way to check if the index is outdated, we cannot + deterministically perform the delete and re-clone operation without + coordination. + +5. Transform outdated documents (step 7) on every startup + Advantages: + - Outdated documents belonging to disabled plugins will be upgraded as soon + as the plugin is enabled again. + + Disadvantages: + - Orphan documents are retained indefinitely so there's still a potential + for future problems. + - Slightly slower startup time since we have to query for outdated + documents every time. + +We prefer option (3) since it provides flexibility for disabling plugins in +the same version while also protecting users' data in all cases during an +upgrade migration. However, because this is a breaking change we will +implement (5) during 7.x and only implement (3) during 8.x. + +# 5. Alternatives +## 5.1 Rolling upgrades +We considered implementing rolling upgrades to provide zero downtime +migrations. However, this would introduce significant complexity for plugins: +they will need to maintain up and down migration transformations and ensure +that queries match both current and outdated documents across all +versions. Although we can afford the once-off complexity of implementing +rolling upgrades, the complexity burden of maintaining plugins that support +rolling-upgrades will slow down all development in Kibana. Since a predictable +downtime window is sufficient for our users, we decided against trying to +achieve zero downtime with rolling upgrades. See "Rolling upgrades" in +https://github.com/elastic/kibana/issues/52202 for more information. + +## 5.2 Single node migrations coordinated through a lease/lock +This alternative is a proposed algorithm for coordinating migrations so that +these only happen on a single node and therefore don't have the restrictions +found in [(4.2.1.1)](#4311-restrictions). We decided against this algorithm +primarily because it is a lot more complex, but also because it could still +require manual intervention to retry from certain unlikely edge cases. + +
+ It's impossible to guarantee that a single node performs the + migration and automatically retry failed migrations. + +Coordination should ensure that only one Kibana node performs the migration at +a given time which can be achived with a distributed lock built on top of +Elasticsearch. For the Kibana cluster to be able to retry a failed migration, +requires a specialized lock which expires after a given amount of inactivity. +We will refer to such expiring locks as a "lease". + +If a Kibana process stalls, it is possible that the process' lease has expired +but the process doesn't yet recognize this and continues the migration. To +prevent this from causing data loss each lease should be accompanied by a +"guard" that prevents all writes after the lease has expired. See +[how to do distributed +locking](https://martin.kleppmann.com/2016/02/08/how-to-do-distributed-locking.html) +for an in-depth discussion. + +Elasticsearch doesn't provide any building blocks for constructing such a guard. +
+ +However, we can implement a lock (that never expires) with strong +data-consistency guarantees. Because there’s no expiration, a failure between +obtaining the lock and releasing it will require manual intervention. Instead +of trying to accomplish the entire migration after obtaining a lock, we can +only perform the last step of the migration process, moving the aliases, with +a lock. A permanent failure in only this last step is not impossible, but very +unlikely. + +### 5.2.1 Migration algorithm +1. Obtain a document lock (see [5.2.2 Document lock + algorithm](#522-document-lock-algorithm)). Convert the lock into a "weak + lease" by expiring locks for nodes which aren't active (see [4.2.2.4 + Checking for lease expiry](#4324-checking-for-lease-expiry)). This "weak + lease" doesn't require strict guarantees since it's only used to prevent + multiple Kibana nodes from performing a migration in parallel to reduce the + load on Elasticsearch. +2. Migrate data into a new process specific index (we could use the process + UUID that’s used in the lease document like + `.kibana_3ef25ff1-090a-4335-83a0-307a47712b4e`). +3. Obtain a document lock (see [5.2.2 Document lock + algorithm](#522-document-lock-algorithm)). +4. Finish the migration by pointing `.kibana` → + `.kibana_3ef25ff1-090a-4335-83a0-307a47712b4e`. This automatically releases + the document lock (and any leases) because the new index will contain an + empty `kibana_cluster_state`. + +If a process crashes or is stopped after (3) but before (4) the lock will have +to be manually removed by deleting the `kibana_cluster_state` document from +`.kibana` or restoring from a snapshot. + +### 5.2.2 Document lock algorithm +To improve on the existing Saved Objects migrations lock, a locking algorithm +needs to satisfy the following requirements: +- Must guarantee that only a single node can obtain the lock. Since we can + only provide strong data-consistency guarantees on the document level in + Elasticsearch our locking mechanism needs to be based on a document. +- Manually removing the lock + - shouldn't have any risk of accidentally causing data loss. + - can be done with a single command that's always the same (shouldn’t + require trying to find `n` for removing the correct `.kibana_n` index). +- Must be easy to retrieve the lock/cluster state to aid in debugging or to + provide visibility. + +Algorithm: +1. Node reads `kibana_cluster_state` lease document from `.kibana` +2. It sends a heartbeat every `heartbeat_interval` seconds by sending an + update operation that adds it’s UUID to the `nodes` array and sets the + `lastSeen` value to the current local node time. If the update fails due to + a version conflict the update operation is retried after a random delay by + fetching the document again and attempting the update operation once more. +3. To obtain a lease, a node: + 1. Fetches the `kibana_cluster_state` document + 2. If all the nodes’ `hasLock === false` it sets it’s own `hasLock` to + true and attempts to write the document. If the update fails + (presumably because of another node’s heartbeat update) it restarts the + process to obtain a lease from step (3). + 3. If another nodes’ `hasLock === true` the node failed to acquire a + lock and waits until the active lock has expired before attempting to + obtain a lock again. +4. Once a node is done with its lock, it releases it by fetching and then + updating `hasLock = false`. The fetch + update operations are retried until + this node’s `hasLock === false`. + +Each machine writes a `UUID` to a file, so a single machine may have multiple +processes with the same Kibana `UUID`, so we should rather generate a new UUID +just for the lifetime of this process. + +`KibanaClusterState` document format: +```js + nodes: { + "852bd94e-5121-47f3-a321-e09d9db8d16e": { + version: "7.6.0", + lastSeen: [ 1114793, 555149266 ], // hrtime() big int timestamp + hasLease: true, + hasLock: false, + }, + "8d975c5b-cbf6-4418-9afb-7aa3ea34ac90": { + version: "7.6.0", + lastSeen: [ 1114862, 841295591 ], + hasLease: false, + hasLock: false, + }, + "3ef25ff1-090a-4335-83a0-307a47712b4e": { + version: "7.6.0", + lastSeen: [ 1114877, 611368546 ], + hasLease: false, + hasLock: false, + }, + }, + oplog: [ + {op: 'ACQUIRE_LOCK', node: '852bd94e...', timestamp: '2020-04-20T11:58:56.176Z'} + ] +} +``` + +### 5.2.3 Checking for "weak lease" expiry +The simplest way to check for lease expiry is to inspect the `lastSeen` value. +If `lastSeen + expiry_timeout > now` the lock is considered expired. If there +are clock drift or daylight savings time adjustments, there’s a risk that a +node loses it’s lease before `expiry_timeout` has occurred. Since losing a +lock prematurely will not lead to data loss it’s not critical that the +expiry time is observed under all conditions. + +A slightly safer approach is to use a monotonically increasing clock +(`process.hrtime()`) and relative time to determine expiry. Using a +monotonically increasing clock guarantees that the clock will always increase +even if the system time changes due to daylight savings time, NTP clock syncs, +or manually setting the time. To check for expiry, other nodes poll the +cluster state document. Once they see that the `lastSeen` value has increased, +they capture the current hr time `current_hr_time` and starts waiting until +`process.hrtime() - current_hr_time > expiry_timeout` if at that point +`lastSeen` hasn’t been updated the lease is considered to have expired. This +means other nodes can take up to `2*expiry_timeout` to recognize an expired +lease, but a lease will never expire prematurely. + +Any node that detects an expired lease can release that lease by setting the +expired node’s `hasLease = false`. It can then attempt to acquire its lease. + +## 5.3 Minimize data loss with mixed Kibana versions during 7.x +When multiple versions of Kibana are running at the same time, writes from the +outdated node can end up either in the outdated Kibana index, the newly +migrated index, or both. New documents added (and some updates) into the old +index while a migration is in-progress will be lost. Writes that end up in the +new index will be in an outdated format. This could cause queries on the data +to only return a subset of the results which leads to incorrect results or +silent data loss. + +Minimizing data loss from mixed 7.x versions, introduces two additional steps +to rollback to a previous version without a snapshot: +1. (existing) Point the `.kibana` alias to the previous Kibana index `.kibana_n-1` +2. (existing) Delete `.kibana_n` +3. (new) Enable writes on `.kibana_n-1` +4. (new) Delete the dummy "version lock" document from `.kibana_n-1` + +Since our documentation and server logs have implicitly encouraged users to +rollback without using snapshots, many users might have to rely on these +additional migration steps to perform a rollback. Since even the existing +steps are error prone, introducing more steps will likely introduce more +problems than what it solves. + +1. All future versions of Kibana 7.x will use the `.kibana_saved_objects` + alias to locate the current index. If `.kibana_saved_objects` doesn't + exist, newer versions will fallback to reading `.kibana`. +2. All future versions of Kibana will locate the index that + `.kibana_saved_objects` points to and then read and write directly from + the _index_ instead of the alias. +3. Before starting a migration: + 1. Write a new dummy "version lock" document to the `.kibana` index with a + `migrationVersion` set to the current version of Kibana. If an outdated + node is started up after a migration was started it will detect that + newer documents are present in the index and refuse to start up. + 2. Set the outdated index to read-only. Since `.kibana` is never advanced, + it will be pointing to a read-only index which prevent writes from + 6.8+ releases which are already online. + +## 5.4 In-place migrations that re-use the same index (8.0) +> We considered an algorithm that re-uses the same index for migrations and an approach to minimize data-loss if our upgrade procedures aren't followed. This is no longer our preferred approach because of several downsides: +> - It requires taking snapshots to prevent data loss so we can only release this in 8.x +> - Minimizing data loss with unsupported upgrade configurations adds significant complexity and still doesn't guarantee that data isn't lost. + +### 5.4.1 Migration algorithm (8.0): +1. Exit Kibana with a fatal error if a newer node has started a migration by + checking for: + 1. Documents with a newer `migrationVersion` numbers. +2. If the mappings are out of date, update the mappings to the combination of + the index's current mappings and the expected mappings. +3. If there are outdated documents, migrate these in batches: + 1. Read a batch of outdated documents from the index. + 2. Transform documents by applying the migration transformation functions. + 3. Update the document batch in the same index using optimistic concurrency + control. If a batch fails due to an update version mismatch continue + migrating the other batches. + 4. If a batch fails due other reasons repeat the entire migration process. +4. If any of the batches in step (3.3) failed, repeat the entire migration + process. This ensures that in-progress bulk update operations from an + outdated node won't lead to unmigrated documents still being present after + the migration. +5. Once all documents are up to date, the migration is complete and Kibana can + start serving traffic. + +Advantages: +- Not duplicating all documents into a new index will speed up migrations and + reduce the downtime window. This will be especially important for the future + requirement to support > 10k or > 100k documents. +- We can check the health of an existing index before starting the migration, + but we cannot detect what kind of failures might occur while creating a new + index. Whereas retrying migrations will eventually recover from the errors + in (3.3), re-using an index allows us to detect these problems before trying + and avoid errors like (3.3.1) altogether. +- Single index to backup instead of “index pattern” that matches any + `.kibana_n`. +- Simplifies Kibana system index Elasticsearch plugin since it needs to work + on one index per "tenant". +- By leveraging optimistic concurrency control we can further minimize data + loss for unsupported upgrade configurations in the future. + +Drawbacks: +- Cannot make breaking mapping changes (even though it was possible, we have not + introduced a breaking mapping change during 7.x). +- Rollback is only possible by restoring a snapshot which requires educating + users to ensure that they don't rely on `.kibana_n` indices as backups. + (Apart from the need to educate users, snapshot restores provide many + benefits). +- It narrows the second restriction under (4.2.1) even further: migrations + cannot rely on any state that could change as part of a migration because we + can no longer use the previous index as a snapshot of unmigrated state. +- We can’t automatically perform a rollback from a half-way done migration. +- It’s impossible to provide read-only functionality for outdated nodes which + means we can't achieve goal (2.7). + +### 5.4.2 Minimizing data loss with unsupported upgrade configurations (8.0) +> This alternative can reduce some data loss when our upgrade procedure isn't +> followed with the algorithm in (5.4.1). + +Even if (4.5.2) is the only supported upgrade procedure, we should try to +prevent data loss when these instructions aren't followed. + +To prevent data loss we need to prevent any writes from older nodes. We use +a version-specific alias for this purpose. Each time a migration is started, +all other aliases are removed. However, aliases are stored inside +Elasticsearch's ClusterState and this state could remain inconsistent between +nodes for an unbounded amount of time. In addition, bulk operations that were +accepted before the alias was removed will continue to run even after removing +the alias. + +As a result, Kibana cannot guarantee that there would be no data loss but +instead, aims to minimize it as much as possible by adding the bold sections +to the migration algorithm from (5.4.1) + +1. **Disable `action.auto_create_index` for the Kibana system indices.** +2. Exit Kibana with a fatal error if a newer node has started a migration by + checking for: + 1. **Version-specific aliases on the `.kibana` index with a newer version.** + 2. Documents with newer `migrationVersion` numbers. +3. **Remove all other aliases and create a new version-specific alias for + reading and writing to the `.kibana` index .e.g `.kibana_8.0.1`. During and + after the migration, all saved object reads and writes use this alias + instead of reading or writing directly to the index. By using the atomic + `POST /_aliases` API we minimize the chance that an outdated node creating + new outdated documents can cause data loss.** +4. **Wait for the default bulk operation timeout of 30s. This ensures that any + bulk operations accepted before the removal of the alias have either + completed or returned a timeout error to it's initiator.** +5. If the mappings are out of date, update the mappings **through the alias** + to the combination of the index's current mappings and the expected + mappings. **If this operation fails due to an index missing exception (most + likely because another node removed our version-specific alias) repeat the + entire migration process.** +6. If there are outdated documents, migrate these in batches: + 1. Read a batch of outdated documents from `.kibana_n`. + 2. Transform documents by applying the migration functions. + 3. Update the document batch in the same index using optimistic concurrency + control. If a batch fails due to an update version mismatch continue + migrating the other batches. + 4. If a batch fails due other reasons repeat the entire migration process. +7. If any of the batches in step (6.3) failed, repeat the entire migration + process. This ensures that in-progress bulk update operations from an + outdated node won't lead to unmigrated documents still being present after + the migration. +8. Once all documents are up to date, the migration is complete and Kibana can + start serving traffic. + +Steps (2) and (3) from the migration algorithm in minimize the chances of the +following scenarios occuring but cannot guarantee it. It is therefore useful +to enumarate some scenarios and their worst case impact: +1. An outdated node issued a bulk create to it's version-specific alias. + Because a user doesn't wait for all traffic to drain a newer node starts + it's migration before the bulk create was complete. Since this bulk create + was accepted before the newer node deleted the previous version-specific + aliases, it is possible that the index now contains some outdated documents + that the new node is unaware of and doesn't migrate. Although these outdated + documents can lead to inconsistent query results and data loss, step (4) + ensures that an error will be returned to the node that created these + objects. +2. A 8.1.0 node and a 8.2.0 node starts migrating a 8.0.0 index in parallel. + Even though the 8.2.0 node will remove the 8.1.0 version-specific aliases, + the 8.1.0 node could have sent an bulk update operation that got accepted + before its alias was removed. When the 8.2.0 node tries to migrate these + 8.1.0 documents it gets a version conflict but cannot be sure if this was + because another node of the same version migrated this document (which can + safely be ignored) or interference from a different Kibana version. The + 8.1.0 node will hit the error in step (6.3) and restart the migration but + then ultimately fail at step (2). The 8.2.0 node will repeat the entire + migration process from step (7) thus ensuring that all documents are up to + date. +3. A race condition with another Kibana node on the same version, but with + different enabled plugins caused this node's required mappings to be + overwritten. If this causes a mapper parsing exception in step (6.3) we can + restart the migration. Because updating the mappings is additive and saved + object types are unique to a plugin, restarting the migration will allow + the node to update the mappings to be compatible with node's plugins. Both + nodes will be able to successfully complete the migration of their plugins' + registered saved object types. However, if the migration doesn't trigger a + mapper parsing exception the incompatible mappings would go undetected + which can cause future problems like write failures or inconsistent query + results. + +## 5.5 Tag objects as “invalid” if their transformation fails +> This alternative prevents a failed migration when there's a migration transform function bug or a document with invalid data. Although it seems preferable to not fail the entire migration because of a single saved object type's migration transform bug or a single invalid document this has several pitfalls: +> 1. When an object fails to migrate the data for that saved object type becomes inconsistent. This could load to a critical feature being unavailable to a user leaving them with no choice but to downgrade. +> 2. Because Kibana starts accepting traffic after encountering invalid objects a rollback will lead to data loss leaving users with no clean way to recover. +> As a result we prefer to let an upgrade fail and making it easy for users to rollback until they can resolve the root cause. + +> Achieves goals: (2.2) +> Mitigates Errors (3.1), (3.2) + +1. Tag objects as “invalid” if they cause an exception when being transformed, + but don’t fail the entire migration. +2. Log an error message informing administrators that there are invalid + objects which require inspection. For each invalid object, provide an error + stack trace to aid in debugging. +3. Administrators should be able to generate a migration report (similar to + the one dry run migrations create) which is an NDJSON export of all objects + tagged as “invalid”. + 1. Expose this as an HTTP API first + 2. (later) Notify administrators and allow them to export invalid objects + from the Kibana UI. +4. When an invalid object is read, the Saved Objects repository will throw an + invalid object exception which should include a link to the documentation + to help administrators resolve migration bugs. +5. Educate Kibana developers to no longer simply write back an unmigrated + document if an exception occurred. A migration function should either + successfully transform the object or throw. + +# 6. How we teach this +1. Update documentation and server logs to start educating users to depend on + snapshots for Kibana rollbacks. +2. Update developer documentation and educate developers with best practices + for writing migration functions. + +# 7. Unresolved questions +1. When cloning an index we can only ever add new fields to the mappings. When + a saved object type or specific field is removed, the mappings will remain + until we re-index. Is it sufficient to only re-index every major? How do we + track the field count as it grows over every upgrade? +2. More generally, how do we deal with the growing field count approaching the + default limit of 1000? diff --git a/scripts/build_plugin_list_docs.js b/scripts/build_plugin_list_docs.js index 54821a1b10ee8..6f184ca7b14c6 100644 --- a/scripts/build_plugin_list_docs.js +++ b/scripts/build_plugin_list_docs.js @@ -17,5 +17,5 @@ * under the License. */ -require('../src/setup_node_env/prebuilt_dev_only_entry'); +require('../src/setup_node_env/no_transpilation'); require('@kbn/dev-utils').runPluginListCli(); diff --git a/scripts/es.js b/scripts/es.js index 93f1d69350bac..53b01d8cb4414 100644 --- a/scripts/es.js +++ b/scripts/es.js @@ -17,7 +17,7 @@ * under the License. */ -require('../src/setup_node_env'); +require('../src/setup_node_env/no_transpilation'); var resolve = require('path').resolve; var pkg = require('../package.json'); diff --git a/scripts/functional_tests.js b/scripts/functional_tests.js index 4facbe1ffbb07..2b338b1c054aa 100644 --- a/scripts/functional_tests.js +++ b/scripts/functional_tests.js @@ -23,6 +23,7 @@ const alwaysImportedTests = [ require.resolve('../test/plugin_functional/config.ts'), require.resolve('../test/ui_capabilities/newsfeed_err/config.ts'), require.resolve('../test/new_visualize_flow/config.js'), + require.resolve('../test/security_functional/config.ts'), ]; // eslint-disable-next-line no-restricted-syntax const onlyNotInCoverageTests = [ diff --git a/scripts/generate_plugin.js b/scripts/generate_plugin.js index f695eabb30f21..af3d31048ecfc 100644 --- a/scripts/generate_plugin.js +++ b/scripts/generate_plugin.js @@ -17,5 +17,5 @@ * under the License. */ -require('../src/setup_node_env/prebuilt_dev_only_entry'); +require('../src/setup_node_env/no_transpilation'); require('@kbn/plugin-generator').runCli(); diff --git a/scripts/generate_team_assignments.js b/scripts/generate_team_assignments.js new file mode 100644 index 0000000000000..9dcb9bb90e0fd --- /dev/null +++ b/scripts/generate_team_assignments.js @@ -0,0 +1,21 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +require('../src/setup_node_env'); +require('../src/dev/code_coverage/ingest_coverage/team_assignment').generateTeamAssignments(); diff --git a/scripts/kibana.js b/scripts/kibana.js index f5a63e6c07dd6..2767e555f2736 100644 --- a/scripts/kibana.js +++ b/scripts/kibana.js @@ -17,6 +17,4 @@ * under the License. */ -require('../src/apm')(process.env.ELASTIC_APM_PROXY_SERVICE_NAME || 'kibana-proxy'); -require('../src/setup_node_env'); -require('../src/cli/cli'); +require('../src/cli/dev'); diff --git a/scripts/kibana_keystore.js b/scripts/kibana_keystore.js index 3efd3500e1f8e..3f970a6517225 100644 --- a/scripts/kibana_keystore.js +++ b/scripts/kibana_keystore.js @@ -17,5 +17,4 @@ * under the License. */ -require('../src/setup_node_env'); -require('../src/cli_keystore'); +require('../src/cli_keystore/dev'); diff --git a/scripts/kibana_plugin.js b/scripts/kibana_plugin.js index 2478e515297ef..5196bdbb853f5 100644 --- a/scripts/kibana_plugin.js +++ b/scripts/kibana_plugin.js @@ -17,5 +17,4 @@ * under the License. */ -require('../src/setup_node_env'); -require('../src/cli_plugin/cli'); +require('../src/cli_plugin/dev'); diff --git a/scripts/load_team_assignment.js b/scripts/load_team_assignment.js deleted file mode 100644 index b8f5edc833634..0000000000000 --- a/scripts/load_team_assignment.js +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -require('../src/setup_node_env'); -require('../src/dev/code_coverage/ingest_coverage/team_assignment').uploadTeamAssignmentJson(); diff --git a/scripts/plugin_helpers.js b/scripts/plugin_helpers.js index a07ba7a9185f8..f28bf8fcfff90 100644 --- a/scripts/plugin_helpers.js +++ b/scripts/plugin_helpers.js @@ -17,5 +17,5 @@ * under the License. */ -require('../src/setup_node_env/prebuilt_dev_only_entry'); +require('../src/setup_node_env/no_transpilation'); require('@kbn/plugin-helpers').runCli(); diff --git a/scripts/precommit_hook.js b/scripts/precommit_hook.js index 7b9647cb7a911..7749fab6d371f 100644 --- a/scripts/precommit_hook.js +++ b/scripts/precommit_hook.js @@ -17,5 +17,5 @@ * under the License. */ -require('../src/setup_node_env/babel_register'); +require('@kbn/optimizer').registerNodeAutoTranspilation(); require('../src/dev/run_precommit_hook'); diff --git a/scripts/register_git_hook.js b/scripts/register_git_hook.js index af3f54619bcec..50dfeaf46109f 100644 --- a/scripts/register_git_hook.js +++ b/scripts/register_git_hook.js @@ -17,5 +17,5 @@ * under the License. */ -require('../src/setup_node_env/prebuilt_dev_only_entry'); +require('../src/setup_node_env/no_transpilation'); require('@kbn/dev-utils/target/precommit_hook/cli'); diff --git a/scripts/release_notes.js b/scripts/release_notes.js index f46ee5823d70d..ee9275194ae94 100644 --- a/scripts/release_notes.js +++ b/scripts/release_notes.js @@ -17,5 +17,5 @@ * under the License. */ -require('../src/setup_node_env/prebuilt_dev_only_entry'); +require('../src/setup_node_env/no_transpilation'); require('@kbn/release-notes').runReleaseNotesCli(); diff --git a/scripts/telemetry_check.js b/scripts/telemetry_check.js index 06b3ed46bdba6..22a22b401cb15 100644 --- a/scripts/telemetry_check.js +++ b/scripts/telemetry_check.js @@ -17,5 +17,5 @@ * under the License. */ -require('../src/setup_node_env/prebuilt_dev_only_entry'); +require('../src/setup_node_env/no_transpilation'); require('@kbn/telemetry-tools').runTelemetryCheck(); diff --git a/scripts/telemetry_extract.js b/scripts/telemetry_extract.js index 051bee26537b9..e2fbb64c26719 100644 --- a/scripts/telemetry_extract.js +++ b/scripts/telemetry_extract.js @@ -17,5 +17,5 @@ * under the License. */ -require('../src/setup_node_env/prebuilt_dev_only_entry'); +require('../src/setup_node_env/no_transpilation'); require('@kbn/telemetry-tools').runTelemetryExtract(); diff --git a/src/apm.js b/src/apm.js index effa6c77d7614..bde37fa006c61 100644 --- a/src/apm.js +++ b/src/apm.js @@ -18,67 +18,11 @@ */ const { join } = require('path'); -const { readFileSync } = require('fs'); -const { execSync } = require('child_process'); -const { merge } = require('lodash'); -const { name, version, build } = require('../package.json'); +const { name, build } = require('../package.json'); +const { loadConfiguration } = require('@kbn/apm-config-loader'); const ROOT_DIR = join(__dirname, '..'); - -function gitRev() { - try { - return execSync('git rev-parse --short HEAD', { - encoding: 'utf-8', - stdio: ['ignore', 'pipe', 'ignore'], - }).trim(); - } catch (e) { - return null; - } -} - -function devConfig() { - try { - const apmDevConfigPath = join(ROOT_DIR, 'config', 'apm.dev.js'); - return require(apmDevConfigPath); // eslint-disable-line import/no-dynamic-require - } catch (e) { - return {}; - } -} - -const apmConfig = merge( - { - active: false, - serverUrl: 'https://f1542b814f674090afd914960583265f.apm.us-central1.gcp.cloud.es.io:443', - // The secretToken below is intended to be hardcoded in this file even though - // it makes it public. This is not a security/privacy issue. Normally we'd - // instead disable the need for a secretToken in the APM Server config where - // the data is transmitted to, but due to how it's being hosted, it's easier, - // for now, to simply leave it in. - secretToken: 'R0Gjg46pE9K9wGestd', - globalLabels: {}, - breakdownMetrics: true, - centralConfig: false, - logUncaughtExceptions: true, - }, - devConfig() -); - -try { - const filename = join(ROOT_DIR, 'data', 'uuid'); - apmConfig.globalLabels.kibana_uuid = readFileSync(filename, 'utf-8'); -} catch (e) {} // eslint-disable-line no-empty - -const rev = gitRev(); -if (rev !== null) apmConfig.globalLabels.git_rev = rev; - -function getConfig(serviceName) { - return { - ...apmConfig, - ...{ - serviceName: `${serviceName}-${version.replace(/\./g, '_')}`, - }, - }; -} +let apmConfig; /** * Flag to disable APM RUM support on all kibana builds by default @@ -86,12 +30,38 @@ function getConfig(serviceName) { const isKibanaDistributable = Boolean(build && build.distributable === true); module.exports = function (serviceName = name) { - if (process.env.kbnWorkerType === 'optmzr') return; + if (process.env.kbnWorkerType === 'optmzr') { + return; + } - const conf = getConfig(serviceName); + apmConfig = loadConfiguration(process.argv, ROOT_DIR, isKibanaDistributable); + const conf = apmConfig.getConfig(serviceName); + const apm = require('elastic-apm-node'); - require('elastic-apm-node').start(conf); + // Filter out all user PII + apm.addFilter((payload) => { + try { + if (payload.context && payload.context.user && typeof payload.context.user === 'object') { + Object.keys(payload.context.user).forEach((key) => { + payload.context.user[key] = '[REDACTED]'; + }); + } + } finally { + return payload; + } + }); + + apm.start(conf); }; -module.exports.getConfig = getConfig; -module.exports.isKibanaDistributable = isKibanaDistributable; +module.exports.getConfig = (serviceName) => { + // integration test runner starts a kibana server that import the module without initializing APM. + // so we need to check initialization of the config. + // note that we can't just load the configuration during this module's import + // because jest IT are ran with `--config path-to-jest-config.js` which conflicts with the CLI's `config` arg + // causing the config loader to try to load the jest js config as yaml and throws. + if (apmConfig) { + return apmConfig.getConfig(serviceName); + } + return {}; +}; diff --git a/src/cli/cluster/cluster_manager.ts b/src/cli/cluster/cluster_manager.ts index 78472bb3f517d..931650a67687c 100644 --- a/src/cli/cluster/cluster_manager.ts +++ b/src/cli/cluster/cluster_manager.ts @@ -19,6 +19,7 @@ import { resolve } from 'path'; import { format as formatUrl } from 'url'; +import Fs from 'fs'; import opn from 'opn'; import { REPO_ROOT } from '@kbn/utils'; @@ -109,6 +110,7 @@ export class ClusterManager { type: 'server', log: this.log, argv: serverArgv, + apmServiceName: 'kibana', })), ]; @@ -227,22 +229,26 @@ export class ClusterManager { fromRoot('src/legacy/server'), fromRoot('src/legacy/ui'), fromRoot('src/legacy/utils'), - fromRoot('x-pack/legacy/common'), - fromRoot('x-pack/legacy/plugins'), - fromRoot('x-pack/legacy/server'), fromRoot('config'), ...extraPaths, ].map((path) => resolve(path)) ) ); + for (const watchPath of watchPaths) { + if (!Fs.existsSync(fromRoot(watchPath))) { + throw new Error( + `A watch directory [${watchPath}] does not exist, which will cause chokidar to fail. Either make sure the directory exists or remove it as a watch source in the ClusterManger` + ); + } + } + const ignorePaths = [ /[\\\/](\..*|node_modules|bower_components|target|public|__[a-z0-9_]+__|coverage)([\\\/]|$)/, /\.test\.(js|tsx?)$/, /\.md$/, /debug\.log$/, ...pluginInternalDirsIgnore, - fromRoot('src/legacy/server/sass/__tmp__'), fromRoot('x-pack/plugins/reporting/chromium'), fromRoot('x-pack/plugins/security_solution/cypress'), fromRoot('x-pack/plugins/apm/e2e'), @@ -253,7 +259,6 @@ export class ClusterManager { fromRoot('x-pack/plugins/lists/server/scripts'), fromRoot('x-pack/plugins/security_solution/scripts'), fromRoot('x-pack/plugins/security_solution/server/lib/detection_engine/scripts'), - 'plugins/java_languageserver', ]; this.watcher = chokidar.watch(watchPaths, { diff --git a/src/cli/cluster/worker.ts b/src/cli/cluster/worker.ts index c8a8a067d30bf..d28065765070b 100644 --- a/src/cli/cluster/worker.ts +++ b/src/cli/cluster/worker.ts @@ -24,7 +24,7 @@ import { EventEmitter } from 'events'; import { BinderFor } from './binder_for'; import { fromRoot } from '../../core/server/utils'; -const cliPath = fromRoot('src/cli'); +const cliPath = fromRoot('src/cli/dev'); const baseArgs = _.difference(process.argv.slice(2), ['--no-watch']); const baseArgv = [process.execPath, cliPath].concat(baseArgs); @@ -49,6 +49,7 @@ interface WorkerOptions { title?: string; watch?: boolean; baseArgv?: string[]; + apmServiceName?: string; } export class Worker extends EventEmitter { @@ -89,6 +90,7 @@ export class Worker extends EventEmitter { NODE_OPTIONS: process.env.NODE_OPTIONS || '', kbnWorkerType: this.type, kbnWorkerArgv: JSON.stringify([...(opts.baseArgv || baseArgv), ...(opts.argv || [])]), + ELASTIC_APM_SERVICE_NAME: opts.apmServiceName || '', }; } diff --git a/src/cli/dev.js b/src/cli/dev.js new file mode 100644 index 0000000000000..a284c82dfeb6e --- /dev/null +++ b/src/cli/dev.js @@ -0,0 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +require('../apm')(process.env.ELASTIC_APM_SERVICE_NAME || 'kibana-proxy'); +require('../setup_node_env'); +require('./cli'); diff --git a/src/cli/dist.js b/src/cli/dist.js new file mode 100644 index 0000000000000..05f0a68aa495c --- /dev/null +++ b/src/cli/dist.js @@ -0,0 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +require('../apm')(); +require('../setup_node_env/dist'); +require('./cli'); diff --git a/src/cli/index.js b/src/cli/index.js deleted file mode 100644 index 45f88eaf82a5b..0000000000000 --- a/src/cli/index.js +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -require('../apm')(); -require('../setup_node_env'); -require('./cli'); diff --git a/src/cli/serve/integration_tests/invalid_config.test.ts b/src/cli/serve/integration_tests/invalid_config.test.ts index fd6fa1bf192fc..a72142faa22fe 100644 --- a/src/cli/serve/integration_tests/invalid_config.test.ts +++ b/src/cli/serve/integration_tests/invalid_config.test.ts @@ -18,10 +18,10 @@ */ import { spawnSync } from 'child_process'; -import { resolve } from 'path'; -const ROOT_DIR = resolve(__dirname, '../../../../'); -const INVALID_CONFIG_PATH = resolve(__dirname, '__fixtures__/invalid_config.yml'); +import { REPO_ROOT } from '@kbn/dev-utils'; + +const INVALID_CONFIG_PATH = require.resolve('./__fixtures__/invalid_config.yml'); interface LogEntry { message: string; @@ -35,11 +35,11 @@ describe('cli invalid config support', function () { function () { // Unused keys only throw once LegacyService starts, so disable migrations so that Core // will finish the start lifecycle without a running Elasticsearch instance. - const { error, status, stdout } = spawnSync( + const { error, status, stdout, stderr } = spawnSync( process.execPath, - ['src/cli', '--config', INVALID_CONFIG_PATH, '--migrations.skip=true'], + ['scripts/kibana', '--config', INVALID_CONFIG_PATH, '--migrations.skip=true'], { - cwd: ROOT_DIR, + cwd: REPO_ROOT, } ); @@ -57,13 +57,21 @@ describe('cli invalid config support', function () { })); expect(error).toBe(undefined); - expect(status).toBe(64); + + if (!fatalLogLine) { + throw new Error( + `cli did not log the expected fatal error message:\n\nstdout: \n${stdout}\n\nstderr:\n${stderr}` + ); + } + expect(fatalLogLine.message).toContain( 'Error: Unknown configuration key(s): "unknown.key", "other.unknown.key", "other.third", "some.flat.key", ' + '"some.array". Check for spelling errors and ensure that expected plugins are installed.' ); expect(fatalLogLine.tags).toEqual(['fatal', 'root']); expect(fatalLogLine.type).toEqual('log'); + + expect(status).toBe(64); }, 20 * 1000 ); diff --git a/src/cli/serve/serve.js b/src/cli/serve/serve.js index d8bd39b9dcdf4..a1715cf3dba2c 100644 --- a/src/cli/serve/serve.js +++ b/src/cli/serve/serve.js @@ -48,11 +48,6 @@ const CAN_CLUSTER = canRequire(CLUSTER_MANAGER_PATH); const REPL_PATH = resolve(__dirname, '../repl'); const CAN_REPL = canRequire(REPL_PATH); -// xpack is installed in both dev and the distributable, it's optional if -// install is a link to the source, not an actual install -const XPACK_DIR = resolve(__dirname, '../../../x-pack'); -const XPACK_INSTALLED = canRequire(XPACK_DIR); - const pathCollector = function () { const paths = []; return function (path) { @@ -137,16 +132,7 @@ function applyConfigOverrides(rawConfig, opts, extraCliOptions) { if (opts.logFile) set('logging.dest', opts.logFile); set('plugins.scanDirs', _.compact([].concat(get('plugins.scanDirs'), opts.pluginDir))); - set( - 'plugins.paths', - _.compact( - [].concat( - get('plugins.paths'), - opts.pluginPath, - XPACK_INSTALLED && !opts.oss ? [XPACK_DIR] : [] - ) - ) - ); + set('plugins.paths', _.compact([].concat(get('plugins.paths'), opts.pluginPath))); merge(extraCliOptions); merge(readKeystore()); diff --git a/src/cli_keystore/index.js b/src/cli_keystore/dev.js similarity index 100% rename from src/cli_keystore/index.js rename to src/cli_keystore/dev.js diff --git a/src/cli_keystore/dist.js b/src/cli_keystore/dist.js new file mode 100644 index 0000000000000..60abe225372aa --- /dev/null +++ b/src/cli_keystore/dist.js @@ -0,0 +1,21 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +require('../setup_node_env/dist'); +require('./cli_keystore'); diff --git a/src/cli_plugin/index.js b/src/cli_plugin/dev.js similarity index 100% rename from src/cli_plugin/index.js rename to src/cli_plugin/dev.js diff --git a/src/cli_plugin/dist.js b/src/cli_plugin/dist.js new file mode 100644 index 0000000000000..cc931f60db1e4 --- /dev/null +++ b/src/cli_plugin/dist.js @@ -0,0 +1,21 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +require('../setup_node_env/dist'); +require('./cli'); diff --git a/src/core/public/apm_system.ts b/src/core/public/apm_system.ts new file mode 100644 index 0000000000000..5e4953b96dc5b --- /dev/null +++ b/src/core/public/apm_system.ts @@ -0,0 +1,76 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +/** + * This is the entry point used to boot the frontend when serving a application + * that lives in the Kibana Platform. + * + * Any changes to this file should be kept in sync with + * src/legacy/ui/ui_bundles/app_entry_template.js + */ +import type { InternalApplicationStart } from './application'; + +interface ApmConfig { + // AgentConfigOptions is not exported from @elastic/apm-rum + active?: boolean; + globalLabels?: Record; +} + +interface StartDeps { + application: InternalApplicationStart; +} + +export class ApmSystem { + private readonly enabled: boolean; + /** + * `apmConfig` would be populated with relevant APM RUM agent + * configuration if server is started with elastic.apm.* config. + */ + constructor(private readonly apmConfig?: ApmConfig) { + this.enabled = apmConfig != null && !!apmConfig.active; + } + + async setup() { + if (!this.enabled) return; + const { init, apm } = await import('@elastic/apm-rum'); + const { globalLabels, ...apmConfig } = this.apmConfig!; + if (globalLabels) { + apm.addLabels(globalLabels); + } + + init(apmConfig); + } + + async start(start?: StartDeps) { + if (!this.enabled || !start) return; + /** + * Register listeners for navigation changes and capture them as + * route-change transactions after Kibana app is bootstrapped + */ + start.application.currentAppId$.subscribe((appId) => { + const apmInstance = (window as any).elasticApm; + if (appId && apmInstance && typeof apmInstance.startTransaction === 'function') { + apmInstance.startTransaction(`/app/${appId}`, 'route-change', { + managed: true, + canReuse: true, + }); + } + }); + } +} diff --git a/src/core/public/application/integration_tests/router.test.tsx b/src/core/public/application/integration_tests/router.test.tsx index e3f992990f9f9..d982136422268 100644 --- a/src/core/public/application/integration_tests/router.test.tsx +++ b/src/core/public/application/integration_tests/router.test.tsx @@ -107,7 +107,7 @@ describe('AppRouter', () => { expect(app1.mounter.mount).toHaveBeenCalled(); expect(dom?.html()).toMatchInlineSnapshot(` - "
+ "
basename: /app/app1 html: App 1
" @@ -119,7 +119,7 @@ describe('AppRouter', () => { expect(app1Unmount).toHaveBeenCalled(); expect(app2.mounter.mount).toHaveBeenCalled(); expect(dom?.html()).toMatchInlineSnapshot(` - "
+ "
basename: /app/app2 html:
App 2
" @@ -133,7 +133,7 @@ describe('AppRouter', () => { expect(standardApp.mounter.mount).toHaveBeenCalled(); expect(dom?.html()).toMatchInlineSnapshot(` - "
+ "
basename: /app/app1 html: App 1
" @@ -145,7 +145,7 @@ describe('AppRouter', () => { expect(standardAppUnmount).toHaveBeenCalled(); expect(chromelessApp.mounter.mount).toHaveBeenCalled(); expect(dom?.html()).toMatchInlineSnapshot(` - "
+ "
basename: /chromeless-a/path html:
Chromeless A
" @@ -157,7 +157,7 @@ describe('AppRouter', () => { expect(chromelessAppUnmount).toHaveBeenCalled(); expect(standardApp.mounter.mount).toHaveBeenCalledTimes(2); expect(dom?.html()).toMatchInlineSnapshot(` - "
+ "
basename: /app/app1 html: App 1
" @@ -171,7 +171,7 @@ describe('AppRouter', () => { expect(chromelessAppA.mounter.mount).toHaveBeenCalled(); expect(dom?.html()).toMatchInlineSnapshot(` - "
+ "
basename: /chromeless-a/path html:
Chromeless A
" @@ -183,7 +183,7 @@ describe('AppRouter', () => { expect(chromelessAppAUnmount).toHaveBeenCalled(); expect(chromelessAppB.mounter.mount).toHaveBeenCalled(); expect(dom?.html()).toMatchInlineSnapshot(` - "
+ "
basename: /chromeless-b/path html:
Chromeless B
" @@ -195,7 +195,7 @@ describe('AppRouter', () => { expect(chromelessAppBUnmount).toHaveBeenCalled(); expect(chromelessAppA.mounter.mount).toHaveBeenCalledTimes(2); expect(dom?.html()).toMatchInlineSnapshot(` - "
+ "
basename: /chromeless-a/path html:
Chromeless A
" diff --git a/src/core/public/application/types.ts b/src/core/public/application/types.ts index df83b6e932aad..02d2d3a52a01a 100644 --- a/src/core/public/application/types.ts +++ b/src/core/public/application/types.ts @@ -710,11 +710,17 @@ export interface ApplicationStart { navigateToApp(appId: string, options?: NavigateToAppOptions): Promise; /** - * Navigate to given url, which can either be an absolute url or a relative path, in a SPA friendly way when possible. + * Navigate to given URL in a SPA friendly way when possible (when the URL will redirect to a valid application + * within the current basePath). * - * If all these criteria are true for the given url: + * The method resolves pathnames the same way browsers do when resolving a `` value. The provided `url` can be: + * - an absolute URL + * - an absolute path + * - a path relative to the current URL (window.location.href) + * + * If all these criteria are true for the given URL: * - (only for absolute URLs) The origin of the URL matches the origin of the browser's current location - * - The pathname of the URL starts with the current basePath (eg. /mybasepath/s/my-space) + * - The resolved pathname of the provided URL/path starts with the current basePath (eg. /mybasepath/s/my-space) * - The pathname segment after the basePath matches any known application route (eg. /app// or any application's `appRoute` configuration) * * Then a SPA navigation will be performed using `navigateToApp` using the corresponding application and path. @@ -727,23 +733,27 @@ export interface ApplicationStart { * // will call `application.navigateToApp('discover', { path: '/some-path?foo=bar'})` * application.navigateToUrl('https://kibana:8080/base-path/s/my-space/app/discover/some-path?foo=bar') * application.navigateToUrl('/base-path/s/my-space/app/discover/some-path?foo=bar') + * application.navigateToUrl('./discover/some-path?foo=bar') * * // will perform a full page reload using `window.location.assign` * application.navigateToUrl('https://elsewhere:8080/base-path/s/my-space/app/discover/some-path') // origin does not match * application.navigateToUrl('/app/discover/some-path') // does not include the current basePath * application.navigateToUrl('/base-path/s/my-space/app/unknown-app/some-path') // unknown application + * application.navigateToUrl('../discover') // resolve to `/base-path/s/my-space/discover` which is not a path of a known app. + * application.navigateToUrl('../../other-space/discover') // resolve to `/base-path/s/other-space/discover` which is not within the current basePath. * ``` * - * @param url - an absolute url, or a relative path, to navigate to. + * @param url - an absolute URL, an absolute path or a relative path, to navigate to. */ navigateToUrl(url: string): Promise; /** - * Returns an URL to a given app, including the global base path. - * By default, the URL is relative (/basePath/app/my-app). - * Use the `absolute` option to generate an absolute url (http://host:port/basePath/app/my-app) + * Returns the absolute path (or URL) to a given app, including the global base path. + * + * By default, it returns the absolute path of the application (e.g `/basePath/app/my-app`). + * Use the `absolute` option to generate an absolute url instead (e.g `http://host:port/basePath/app/my-app`) * - * Note that when generating absolute urls, the origin (protocol, host and port) are determined from the browser's location. + * Note that when generating absolute urls, the origin (protocol, host and port) are determined from the browser's current location. * * @param appId * @param options.path - optional path inside application to deep link to diff --git a/src/core/public/application/ui/app_container.tsx b/src/core/public/application/ui/app_container.tsx index 089d1cf3f3ced..9821db5ba2666 100644 --- a/src/core/public/application/ui/app_container.tsx +++ b/src/core/public/application/ui/app_container.tsx @@ -25,7 +25,7 @@ import React, { useState, MutableRefObject, } from 'react'; -import { EuiLoadingSpinner } from '@elastic/eui'; +import { EuiLoadingElastic } from '@elastic/eui'; import type { MountPoint } from '../../types'; import { AppLeaveHandler, AppStatus, AppUnmount, Mounter } from '../types'; @@ -120,7 +120,7 @@ export const AppContainer: FunctionComponent = ({ {appNotFound && } {showSpinner && (
- +
)}
diff --git a/src/core/public/application/utils.test.ts b/src/core/public/application/utils.test.ts deleted file mode 100644 index ee1d82a7a872e..0000000000000 --- a/src/core/public/application/utils.test.ts +++ /dev/null @@ -1,440 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { of } from 'rxjs'; -import { App, AppNavLinkStatus, AppStatus } from './types'; -import { BasePath } from '../http/base_path'; -import { appendAppPath, getAppInfo, parseAppUrl, relativeToAbsolute, removeSlashes } from './utils'; - -describe('removeSlashes', () => { - it('only removes duplicates by default', () => { - expect(removeSlashes('/some//url//to//')).toEqual('/some/url/to/'); - expect(removeSlashes('some/////other//url')).toEqual('some/other/url'); - }); - - it('remove trailing slash when `trailing` is true', () => { - expect(removeSlashes('/some//url//to//', { trailing: true })).toEqual('/some/url/to'); - }); - - it('remove leading slash when `leading` is true', () => { - expect(removeSlashes('/some//url//to//', { leading: true })).toEqual('some/url/to/'); - }); - - it('does not removes duplicates when `duplicates` is false', () => { - expect(removeSlashes('/some//url//to/', { leading: true, duplicates: false })).toEqual( - 'some//url//to/' - ); - expect(removeSlashes('/some//url//to/', { trailing: true, duplicates: false })).toEqual( - '/some//url//to' - ); - }); - - it('accept mixed options', () => { - expect( - removeSlashes('/some//url//to/', { leading: true, duplicates: false, trailing: true }) - ).toEqual('some//url//to'); - expect( - removeSlashes('/some//url//to/', { leading: true, duplicates: true, trailing: true }) - ).toEqual('some/url/to'); - }); -}); - -describe('appendAppPath', () => { - it('appends the appBasePath with given path', () => { - expect(appendAppPath('/app/my-app', '/some-path')).toEqual('/app/my-app/some-path'); - expect(appendAppPath('/app/my-app/', 'some-path')).toEqual('/app/my-app/some-path'); - expect(appendAppPath('/app/my-app', 'some-path')).toEqual('/app/my-app/some-path'); - expect(appendAppPath('/app/my-app', '')).toEqual('/app/my-app'); - }); - - it('preserves the trailing slash only if included in the hash or appPath', () => { - expect(appendAppPath('/app/my-app', '/some-path/')).toEqual('/app/my-app/some-path'); - expect(appendAppPath('/app/my-app', '/some-path#/')).toEqual('/app/my-app/some-path#/'); - expect(appendAppPath('/app/my-app#/', '')).toEqual('/app/my-app#/'); - expect(appendAppPath('/app/my-app#', '/')).toEqual('/app/my-app#/'); - expect(appendAppPath('/app/my-app', '/some-path#/hash/')).toEqual( - '/app/my-app/some-path#/hash/' - ); - expect(appendAppPath('/app/my-app', '/some-path#/hash')).toEqual('/app/my-app/some-path#/hash'); - }); -}); - -describe('relativeToAbsolute', () => { - it('converts a relative path to an absolute url', () => { - const origin = window.location.origin; - expect(relativeToAbsolute('path')).toEqual(`${origin}/path`); - expect(relativeToAbsolute('/path#hash')).toEqual(`${origin}/path#hash`); - expect(relativeToAbsolute('/path?query=foo')).toEqual(`${origin}/path?query=foo`); - }); -}); - -describe('parseAppUrl', () => { - let apps: Map>; - let basePath: BasePath; - - const getOrigin = () => 'https://kibana.local:8080'; - - const createApp = (props: Partial): App => { - const app: App = { - id: 'some-id', - title: 'some-title', - mount: () => () => undefined, - ...props, - }; - apps.set(app.id, app); - return app; - }; - - beforeEach(() => { - apps = new Map(); - basePath = new BasePath('/base-path'); - - createApp({ - id: 'foo', - }); - createApp({ - id: 'bar', - appRoute: '/custom-bar', - }); - }); - - describe('with relative paths', () => { - it('parses the app id', () => { - expect(parseAppUrl('/base-path/app/foo', basePath, apps, getOrigin)).toEqual({ - app: 'foo', - path: undefined, - }); - expect(parseAppUrl('/base-path/custom-bar', basePath, apps, getOrigin)).toEqual({ - app: 'bar', - path: undefined, - }); - }); - it('parses the path', () => { - expect(parseAppUrl('/base-path/app/foo/some/path', basePath, apps, getOrigin)).toEqual({ - app: 'foo', - path: '/some/path', - }); - expect(parseAppUrl('/base-path/custom-bar/another/path/', basePath, apps, getOrigin)).toEqual( - { - app: 'bar', - path: '/another/path/', - } - ); - }); - it('includes query and hash in the path for default app route', () => { - expect(parseAppUrl('/base-path/app/foo#hash/bang', basePath, apps, getOrigin)).toEqual({ - app: 'foo', - path: '#hash/bang', - }); - expect(parseAppUrl('/base-path/app/foo?hello=dolly', basePath, apps, getOrigin)).toEqual({ - app: 'foo', - path: '?hello=dolly', - }); - expect(parseAppUrl('/base-path/app/foo/path?hello=dolly', basePath, apps, getOrigin)).toEqual( - { - app: 'foo', - path: '/path?hello=dolly', - } - ); - expect(parseAppUrl('/base-path/app/foo/path#hash/bang', basePath, apps, getOrigin)).toEqual({ - app: 'foo', - path: '/path#hash/bang', - }); - expect( - parseAppUrl('/base-path/app/foo/path#hash/bang?hello=dolly', basePath, apps, getOrigin) - ).toEqual({ - app: 'foo', - path: '/path#hash/bang?hello=dolly', - }); - }); - it('includes query and hash in the path for custom app route', () => { - expect(parseAppUrl('/base-path/custom-bar#hash/bang', basePath, apps, getOrigin)).toEqual({ - app: 'bar', - path: '#hash/bang', - }); - expect(parseAppUrl('/base-path/custom-bar?hello=dolly', basePath, apps, getOrigin)).toEqual({ - app: 'bar', - path: '?hello=dolly', - }); - expect( - parseAppUrl('/base-path/custom-bar/path?hello=dolly', basePath, apps, getOrigin) - ).toEqual({ - app: 'bar', - path: '/path?hello=dolly', - }); - expect( - parseAppUrl('/base-path/custom-bar/path#hash/bang', basePath, apps, getOrigin) - ).toEqual({ - app: 'bar', - path: '/path#hash/bang', - }); - expect( - parseAppUrl('/base-path/custom-bar/path#hash/bang?hello=dolly', basePath, apps, getOrigin) - ).toEqual({ - app: 'bar', - path: '/path#hash/bang?hello=dolly', - }); - }); - it('returns undefined when the app is not known', () => { - expect(parseAppUrl('/base-path/app/non-registered', basePath, apps, getOrigin)).toEqual( - undefined - ); - expect(parseAppUrl('/base-path/unknown-path', basePath, apps, getOrigin)).toEqual(undefined); - }); - }); - - describe('with absolute urls', () => { - it('parses the app id', () => { - expect( - parseAppUrl('https://kibana.local:8080/base-path/app/foo', basePath, apps, getOrigin) - ).toEqual({ - app: 'foo', - path: undefined, - }); - expect( - parseAppUrl('https://kibana.local:8080/base-path/custom-bar', basePath, apps, getOrigin) - ).toEqual({ - app: 'bar', - path: undefined, - }); - }); - it('parses the path', () => { - expect( - parseAppUrl( - 'https://kibana.local:8080/base-path/app/foo/some/path', - basePath, - apps, - getOrigin - ) - ).toEqual({ - app: 'foo', - path: '/some/path', - }); - expect( - parseAppUrl( - 'https://kibana.local:8080/base-path/custom-bar/another/path/', - basePath, - apps, - getOrigin - ) - ).toEqual({ - app: 'bar', - path: '/another/path/', - }); - }); - it('includes query and hash in the path for default app routes', () => { - expect( - parseAppUrl( - 'https://kibana.local:8080/base-path/app/foo#hash/bang', - basePath, - apps, - getOrigin - ) - ).toEqual({ - app: 'foo', - path: '#hash/bang', - }); - expect( - parseAppUrl( - 'https://kibana.local:8080/base-path/app/foo?hello=dolly', - basePath, - apps, - getOrigin - ) - ).toEqual({ - app: 'foo', - path: '?hello=dolly', - }); - expect( - parseAppUrl( - 'https://kibana.local:8080/base-path/app/foo/path?hello=dolly', - basePath, - apps, - getOrigin - ) - ).toEqual({ - app: 'foo', - path: '/path?hello=dolly', - }); - expect( - parseAppUrl( - 'https://kibana.local:8080/base-path/app/foo/path#hash/bang', - basePath, - apps, - getOrigin - ) - ).toEqual({ - app: 'foo', - path: '/path#hash/bang', - }); - expect( - parseAppUrl( - 'https://kibana.local:8080/base-path/app/foo/path#hash/bang?hello=dolly', - basePath, - apps, - getOrigin - ) - ).toEqual({ - app: 'foo', - path: '/path#hash/bang?hello=dolly', - }); - }); - it('includes query and hash in the path for custom app route', () => { - expect( - parseAppUrl( - 'https://kibana.local:8080/base-path/custom-bar#hash/bang', - basePath, - apps, - getOrigin - ) - ).toEqual({ - app: 'bar', - path: '#hash/bang', - }); - expect( - parseAppUrl( - 'https://kibana.local:8080/base-path/custom-bar?hello=dolly', - basePath, - apps, - getOrigin - ) - ).toEqual({ - app: 'bar', - path: '?hello=dolly', - }); - expect( - parseAppUrl( - 'https://kibana.local:8080/base-path/custom-bar/path?hello=dolly', - basePath, - apps, - getOrigin - ) - ).toEqual({ - app: 'bar', - path: '/path?hello=dolly', - }); - expect( - parseAppUrl( - 'https://kibana.local:8080/base-path/custom-bar/path#hash/bang', - basePath, - apps, - getOrigin - ) - ).toEqual({ - app: 'bar', - path: '/path#hash/bang', - }); - expect( - parseAppUrl( - 'https://kibana.local:8080/base-path/custom-bar/path#hash/bang?hello=dolly', - basePath, - apps, - getOrigin - ) - ).toEqual({ - app: 'bar', - path: '/path#hash/bang?hello=dolly', - }); - }); - it('returns undefined when the app is not known', () => { - expect( - parseAppUrl( - 'https://kibana.local:8080/base-path/app/non-registered', - basePath, - apps, - getOrigin - ) - ).toEqual(undefined); - expect( - parseAppUrl('https://kibana.local:8080/base-path/unknown-path', basePath, apps, getOrigin) - ).toEqual(undefined); - }); - it('returns undefined when origin does not match', () => { - expect( - parseAppUrl( - 'https://other-kibana.external:8080/base-path/app/foo', - basePath, - apps, - getOrigin - ) - ).toEqual(undefined); - expect( - parseAppUrl( - 'https://other-kibana.external:8080/base-path/custom-bar', - basePath, - apps, - getOrigin - ) - ).toEqual(undefined); - }); - }); -}); - -describe('getAppInfo', () => { - const createApp = (props: Partial = {}): App => ({ - mount: () => () => undefined, - updater$: of(() => undefined), - id: 'some-id', - title: 'some-title', - status: AppStatus.accessible, - navLinkStatus: AppNavLinkStatus.default, - appRoute: `/app/some-id`, - ...props, - }); - - it('converts an application and remove sensitive properties', () => { - const app = createApp(); - const info = getAppInfo(app); - - expect(info).toEqual({ - id: 'some-id', - title: 'some-title', - status: AppStatus.accessible, - navLinkStatus: AppNavLinkStatus.visible, - appRoute: `/app/some-id`, - }); - }); - - it('computes the navLinkStatus depending on the app status', () => { - expect( - getAppInfo( - createApp({ - navLinkStatus: AppNavLinkStatus.default, - status: AppStatus.inaccessible, - }) - ) - ).toEqual( - expect.objectContaining({ - navLinkStatus: AppNavLinkStatus.hidden, - }) - ); - expect( - getAppInfo( - createApp({ - navLinkStatus: AppNavLinkStatus.default, - status: AppStatus.accessible, - }) - ) - ).toEqual( - expect.objectContaining({ - navLinkStatus: AppNavLinkStatus.visible, - }) - ); - }); -}); diff --git a/src/core/public/application/utils.ts b/src/core/public/application/utils.ts deleted file mode 100644 index 85760526bf544..0000000000000 --- a/src/core/public/application/utils.ts +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { IBasePath } from '../http'; -import { App, AppNavLinkStatus, AppStatus, ParsedAppUrl, PublicAppInfo } from './types'; - -/** - * Utility to remove trailing, leading or duplicate slashes. - * By default will only remove duplicates. - */ -export const removeSlashes = ( - url: string, - { - trailing = false, - leading = false, - duplicates = true, - }: { trailing?: boolean; leading?: boolean; duplicates?: boolean } = {} -): string => { - if (duplicates) { - url = url.replace(/\/{2,}/g, '/'); - } - if (trailing) { - url = url.replace(/\/$/, ''); - } - if (leading) { - url = url.replace(/^\//, ''); - } - return url; -}; - -export const appendAppPath = (appBasePath: string, path: string = '') => { - // Only prepend slash if not a hash or query path - path = path === '' || path.startsWith('#') || path.startsWith('?') ? path : `/${path}`; - // Do not remove trailing slash when in hashbang or basePath - const removeTrailing = path.indexOf('#') === -1 && appBasePath.indexOf('#') === -1; - return removeSlashes(`${appBasePath}${path}`, { - trailing: removeTrailing, - duplicates: true, - leading: false, - }); -}; - -/** - * Converts a relative path to an absolute url. - * Implementation is based on a specified behavior of the browser to automatically convert - * a relative url to an absolute one when setting the `href` attribute of a `` html element. - * - * @example - * ```ts - * // current url: `https://kibana:8000/base-path/app/my-app` - * relativeToAbsolute('/base-path/app/another-app') => `https://kibana:8000/base-path/app/another-app` - * ``` - */ -export const relativeToAbsolute = (url: string): string => { - const a = document.createElement('a'); - a.setAttribute('href', url); - return a.href; -}; - -/** - * Parse given url and return the associated app id and path if any app matches. - * Input can either be: - * - a path containing the basePath, ie `/base-path/app/my-app/some-path` - * - an absolute url matching the `origin` of the kibana instance (as seen by the browser), - * i.e `https://kibana:8080/base-path/app/my-app/some-path` - */ -export const parseAppUrl = ( - url: string, - basePath: IBasePath, - apps: Map>, - getOrigin: () => string = () => window.location.origin -): ParsedAppUrl | undefined => { - url = removeBasePath(url, basePath, getOrigin()); - if (!url.startsWith('/')) { - return undefined; - } - - for (const app of apps.values()) { - const appPath = app.appRoute || `/app/${app.id}`; - - if (url.startsWith(appPath)) { - const path = url.substr(appPath.length); - return { - app: app.id, - path: path.length ? path : undefined, - }; - } - } -}; - -const removeBasePath = (url: string, basePath: IBasePath, origin: string): string => { - if (url.startsWith(origin)) { - url = url.substring(origin.length); - } - return basePath.remove(url); -}; - -export function getAppInfo(app: App): PublicAppInfo { - const navLinkStatus = - app.navLinkStatus === AppNavLinkStatus.default - ? app.status === AppStatus.inaccessible - ? AppNavLinkStatus.hidden - : AppNavLinkStatus.visible - : app.navLinkStatus!; - const { updater$, mount, ...infos } = app; - return { - ...infos, - status: app.status!, - navLinkStatus, - appRoute: app.appRoute!, - }; -} diff --git a/src/core/public/application/utils/append_app_path.test.ts b/src/core/public/application/utils/append_app_path.test.ts new file mode 100644 index 0000000000000..a153b5753bbe2 --- /dev/null +++ b/src/core/public/application/utils/append_app_path.test.ts @@ -0,0 +1,40 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { appendAppPath } from './append_app_path'; + +describe('appendAppPath', () => { + it('appends the appBasePath with given path', () => { + expect(appendAppPath('/app/my-app', '/some-path')).toEqual('/app/my-app/some-path'); + expect(appendAppPath('/app/my-app/', 'some-path')).toEqual('/app/my-app/some-path'); + expect(appendAppPath('/app/my-app', 'some-path')).toEqual('/app/my-app/some-path'); + expect(appendAppPath('/app/my-app', '')).toEqual('/app/my-app'); + }); + + it('preserves the trailing slash only if included in the hash or appPath', () => { + expect(appendAppPath('/app/my-app', '/some-path/')).toEqual('/app/my-app/some-path'); + expect(appendAppPath('/app/my-app', '/some-path#/')).toEqual('/app/my-app/some-path#/'); + expect(appendAppPath('/app/my-app#/', '')).toEqual('/app/my-app#/'); + expect(appendAppPath('/app/my-app#', '/')).toEqual('/app/my-app#/'); + expect(appendAppPath('/app/my-app', '/some-path#/hash/')).toEqual( + '/app/my-app/some-path#/hash/' + ); + expect(appendAppPath('/app/my-app', '/some-path#/hash')).toEqual('/app/my-app/some-path#/hash'); + }); +}); diff --git a/src/core/public/application/utils/append_app_path.ts b/src/core/public/application/utils/append_app_path.ts new file mode 100644 index 0000000000000..70cb4a44c648e --- /dev/null +++ b/src/core/public/application/utils/append_app_path.ts @@ -0,0 +1,32 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { removeSlashes } from './remove_slashes'; + +export const appendAppPath = (appBasePath: string, path: string = '') => { + // Only prepend slash if not a hash or query path + path = path === '' || path.startsWith('#') || path.startsWith('?') ? path : `/${path}`; + // Do not remove trailing slash when in hashbang or basePath + const removeTrailing = path.indexOf('#') === -1 && appBasePath.indexOf('#') === -1; + return removeSlashes(`${appBasePath}${path}`, { + trailing: removeTrailing, + duplicates: true, + leading: false, + }); +}; diff --git a/src/core/public/application/utils/get_app_info.test.ts b/src/core/public/application/utils/get_app_info.test.ts new file mode 100644 index 0000000000000..055f7d1a5ada9 --- /dev/null +++ b/src/core/public/application/utils/get_app_info.test.ts @@ -0,0 +1,75 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { of } from 'rxjs'; +import { App, AppNavLinkStatus, AppStatus } from '../types'; +import { getAppInfo } from './get_app_info'; + +describe('getAppInfo', () => { + const createApp = (props: Partial = {}): App => ({ + mount: () => () => undefined, + updater$: of(() => undefined), + id: 'some-id', + title: 'some-title', + status: AppStatus.accessible, + navLinkStatus: AppNavLinkStatus.default, + appRoute: `/app/some-id`, + ...props, + }); + + it('converts an application and remove sensitive properties', () => { + const app = createApp(); + const info = getAppInfo(app); + + expect(info).toEqual({ + id: 'some-id', + title: 'some-title', + status: AppStatus.accessible, + navLinkStatus: AppNavLinkStatus.visible, + appRoute: `/app/some-id`, + }); + }); + + it('computes the navLinkStatus depending on the app status', () => { + expect( + getAppInfo( + createApp({ + navLinkStatus: AppNavLinkStatus.default, + status: AppStatus.inaccessible, + }) + ) + ).toEqual( + expect.objectContaining({ + navLinkStatus: AppNavLinkStatus.hidden, + }) + ); + expect( + getAppInfo( + createApp({ + navLinkStatus: AppNavLinkStatus.default, + status: AppStatus.accessible, + }) + ) + ).toEqual( + expect.objectContaining({ + navLinkStatus: AppNavLinkStatus.visible, + }) + ); + }); +}); diff --git a/src/core/public/application/utils/get_app_info.ts b/src/core/public/application/utils/get_app_info.ts new file mode 100644 index 0000000000000..71cd8a3e14929 --- /dev/null +++ b/src/core/public/application/utils/get_app_info.ts @@ -0,0 +1,36 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { App, AppNavLinkStatus, AppStatus, PublicAppInfo } from '../types'; + +export function getAppInfo(app: App): PublicAppInfo { + const navLinkStatus = + app.navLinkStatus === AppNavLinkStatus.default + ? app.status === AppStatus.inaccessible + ? AppNavLinkStatus.hidden + : AppNavLinkStatus.visible + : app.navLinkStatus!; + const { updater$, mount, ...infos } = app; + return { + ...infos, + status: app.status!, + navLinkStatus, + appRoute: app.appRoute!, + }; +} diff --git a/src/core/public/application/utils/index.ts b/src/core/public/application/utils/index.ts new file mode 100644 index 0000000000000..3b8a34df8c50d --- /dev/null +++ b/src/core/public/application/utils/index.ts @@ -0,0 +1,24 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export { appendAppPath } from './append_app_path'; +export { getAppInfo } from './get_app_info'; +export { parseAppUrl } from './parse_app_url'; +export { relativeToAbsolute } from './relative_to_absolute'; +export { removeSlashes } from './remove_slashes'; diff --git a/src/core/public/application/utils/parse_app_url.test.ts b/src/core/public/application/utils/parse_app_url.test.ts new file mode 100644 index 0000000000000..bf7e0a88a0742 --- /dev/null +++ b/src/core/public/application/utils/parse_app_url.test.ts @@ -0,0 +1,407 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { App } from '../types'; +import { BasePath } from '../../http/base_path'; +import { parseAppUrl } from './parse_app_url'; + +describe('parseAppUrl', () => { + let apps: Map>; + let basePath: BasePath; + + const currentUrl = + 'https://kibana.local:8080/base-path/app/current/current-path?current-query=true'; + + const createApp = (props: Partial): App => { + const app: App = { + id: 'some-id', + title: 'some-title', + mount: () => () => undefined, + ...props, + }; + apps.set(app.id, app); + return app; + }; + + beforeEach(() => { + apps = new Map(); + basePath = new BasePath('/base-path'); + + createApp({ + id: 'foo', + }); + createApp({ + id: 'bar', + appRoute: '/custom-bar', + }); + }); + + describe('with absolute paths', () => { + it('parses the app id', () => { + expect(parseAppUrl('/base-path/app/foo', basePath, apps, currentUrl)).toEqual({ + app: 'foo', + path: undefined, + }); + expect(parseAppUrl('/base-path/custom-bar', basePath, apps, currentUrl)).toEqual({ + app: 'bar', + path: undefined, + }); + }); + it('parses the path', () => { + expect(parseAppUrl('/base-path/app/foo/some/path', basePath, apps, currentUrl)).toEqual({ + app: 'foo', + path: '/some/path', + }); + expect( + parseAppUrl('/base-path/custom-bar/another/path/', basePath, apps, currentUrl) + ).toEqual({ + app: 'bar', + path: '/another/path/', + }); + }); + it('includes query and hash in the path for default app route', () => { + expect(parseAppUrl('/base-path/app/foo#hash/bang', basePath, apps, currentUrl)).toEqual({ + app: 'foo', + path: '#hash/bang', + }); + expect(parseAppUrl('/base-path/app/foo?hello=dolly', basePath, apps, currentUrl)).toEqual({ + app: 'foo', + path: '?hello=dolly', + }); + expect( + parseAppUrl('/base-path/app/foo/path?hello=dolly', basePath, apps, currentUrl) + ).toEqual({ + app: 'foo', + path: '/path?hello=dolly', + }); + expect(parseAppUrl('/base-path/app/foo/path#hash/bang', basePath, apps, currentUrl)).toEqual({ + app: 'foo', + path: '/path#hash/bang', + }); + expect( + parseAppUrl('/base-path/app/foo/path#hash/bang?hello=dolly', basePath, apps, currentUrl) + ).toEqual({ + app: 'foo', + path: '/path#hash/bang?hello=dolly', + }); + }); + it('includes query and hash in the path for custom app route', () => { + expect(parseAppUrl('/base-path/custom-bar#hash/bang', basePath, apps, currentUrl)).toEqual({ + app: 'bar', + path: '#hash/bang', + }); + expect(parseAppUrl('/base-path/custom-bar?hello=dolly', basePath, apps, currentUrl)).toEqual({ + app: 'bar', + path: '?hello=dolly', + }); + expect( + parseAppUrl('/base-path/custom-bar/path?hello=dolly', basePath, apps, currentUrl) + ).toEqual({ + app: 'bar', + path: '/path?hello=dolly', + }); + expect( + parseAppUrl('/base-path/custom-bar/path#hash/bang', basePath, apps, currentUrl) + ).toEqual({ + app: 'bar', + path: '/path#hash/bang', + }); + expect( + parseAppUrl('/base-path/custom-bar/path#hash/bang?hello=dolly', basePath, apps, currentUrl) + ).toEqual({ + app: 'bar', + path: '/path#hash/bang?hello=dolly', + }); + }); + it('returns undefined when the app is not known', () => { + expect(parseAppUrl('/base-path/app/non-registered', basePath, apps, currentUrl)).toEqual( + undefined + ); + expect(parseAppUrl('/base-path/unknown-path', basePath, apps, currentUrl)).toEqual(undefined); + }); + it('returns undefined when the path does not start with the base path', () => { + expect(parseAppUrl('/app/foo', basePath, apps, currentUrl)).toBeUndefined(); + }); + }); + + describe('with relative paths', () => { + it('works with sibling relative urls', () => { + expect( + parseAppUrl('./foo', basePath, apps, 'https://kibana.local:8080/base-path/app/current') + ).toEqual({ + app: 'foo', + path: undefined, + }); + }); + it('works with parent relative urls', () => { + expect( + parseAppUrl( + '../custom-bar', + basePath, + apps, + 'https://kibana.local:8080/base-path/app/current' + ) + ).toEqual({ + app: 'bar', + path: undefined, + }); + }); + it('works with nested parents', () => { + expect( + parseAppUrl( + '../../custom-bar', + basePath, + apps, + 'https://kibana.local:8080/base-path/app/current/some-path' + ) + ).toEqual({ + app: 'bar', + path: undefined, + }); + }); + it('parses the path', () => { + expect( + parseAppUrl( + './foo/path?hello=dolly', + basePath, + apps, + 'https://kibana.local:8080/base-path/app/current' + ) + ).toEqual({ + app: 'foo', + path: '/path?hello=dolly', + }); + }); + it('parses the path with query and hash', () => { + expect( + parseAppUrl( + '../custom-bar/path#hash?hello=dolly', + basePath, + apps, + 'https://kibana.local:8080/base-path/app/current' + ) + ).toEqual({ + app: 'bar', + path: '/path#hash?hello=dolly', + }); + }); + + it('returns undefined if the relative path redirect outside of the basePath', () => { + expect( + parseAppUrl( + '../../custom-bar', + basePath, + apps, + 'https://kibana.local:8080/base-path/app/current' + ) + ).toBeUndefined(); + }); + }); + + describe('with absolute urls', () => { + it('parses the app id', () => { + expect( + parseAppUrl('https://kibana.local:8080/base-path/app/foo', basePath, apps, currentUrl) + ).toEqual({ + app: 'foo', + path: undefined, + }); + expect( + parseAppUrl('https://kibana.local:8080/base-path/custom-bar', basePath, apps, currentUrl) + ).toEqual({ + app: 'bar', + path: undefined, + }); + }); + it('parses the path', () => { + expect( + parseAppUrl( + 'https://kibana.local:8080/base-path/app/foo/some/path', + basePath, + apps, + currentUrl + ) + ).toEqual({ + app: 'foo', + path: '/some/path', + }); + expect( + parseAppUrl( + 'https://kibana.local:8080/base-path/custom-bar/another/path/', + basePath, + apps, + currentUrl + ) + ).toEqual({ + app: 'bar', + path: '/another/path/', + }); + }); + it('includes query and hash in the path for default app routes', () => { + expect( + parseAppUrl( + 'https://kibana.local:8080/base-path/app/foo#hash/bang', + basePath, + apps, + currentUrl + ) + ).toEqual({ + app: 'foo', + path: '#hash/bang', + }); + expect( + parseAppUrl( + 'https://kibana.local:8080/base-path/app/foo?hello=dolly', + basePath, + apps, + currentUrl + ) + ).toEqual({ + app: 'foo', + path: '?hello=dolly', + }); + expect( + parseAppUrl( + 'https://kibana.local:8080/base-path/app/foo/path?hello=dolly', + basePath, + apps, + currentUrl + ) + ).toEqual({ + app: 'foo', + path: '/path?hello=dolly', + }); + expect( + parseAppUrl( + 'https://kibana.local:8080/base-path/app/foo/path#hash/bang', + basePath, + apps, + currentUrl + ) + ).toEqual({ + app: 'foo', + path: '/path#hash/bang', + }); + expect( + parseAppUrl( + 'https://kibana.local:8080/base-path/app/foo/path#hash/bang?hello=dolly', + basePath, + apps, + currentUrl + ) + ).toEqual({ + app: 'foo', + path: '/path#hash/bang?hello=dolly', + }); + }); + it('includes query and hash in the path for custom app route', () => { + expect( + parseAppUrl( + 'https://kibana.local:8080/base-path/custom-bar#hash/bang', + basePath, + apps, + currentUrl + ) + ).toEqual({ + app: 'bar', + path: '#hash/bang', + }); + expect( + parseAppUrl( + 'https://kibana.local:8080/base-path/custom-bar?hello=dolly', + basePath, + apps, + currentUrl + ) + ).toEqual({ + app: 'bar', + path: '?hello=dolly', + }); + expect( + parseAppUrl( + 'https://kibana.local:8080/base-path/custom-bar/path?hello=dolly', + basePath, + apps, + currentUrl + ) + ).toEqual({ + app: 'bar', + path: '/path?hello=dolly', + }); + expect( + parseAppUrl( + 'https://kibana.local:8080/base-path/custom-bar/path#hash/bang', + basePath, + apps, + currentUrl + ) + ).toEqual({ + app: 'bar', + path: '/path#hash/bang', + }); + expect( + parseAppUrl( + 'https://kibana.local:8080/base-path/custom-bar/path#hash/bang?hello=dolly', + basePath, + apps, + currentUrl + ) + ).toEqual({ + app: 'bar', + path: '/path#hash/bang?hello=dolly', + }); + }); + it('returns undefined when the app is not known', () => { + expect( + parseAppUrl( + 'https://kibana.local:8080/base-path/app/non-registered', + basePath, + apps, + currentUrl + ) + ).toEqual(undefined); + expect( + parseAppUrl('https://kibana.local:8080/base-path/unknown-path', basePath, apps, currentUrl) + ).toEqual(undefined); + }); + it('returns undefined when origin does not match', () => { + expect( + parseAppUrl( + 'https://other-kibana.external:8080/base-path/app/foo', + basePath, + apps, + currentUrl + ) + ).toEqual(undefined); + expect( + parseAppUrl( + 'https://other-kibana.external:8080/base-path/custom-bar', + basePath, + apps, + currentUrl + ) + ).toEqual(undefined); + }); + it('returns undefined when the path does not contain the base path', () => { + expect(parseAppUrl('https://kibana.local:8080/app/foo', basePath, apps, currentUrl)).toEqual( + undefined + ); + }); + }); +}); diff --git a/src/core/public/application/utils/parse_app_url.ts b/src/core/public/application/utils/parse_app_url.ts new file mode 100644 index 0000000000000..d253129a63ae4 --- /dev/null +++ b/src/core/public/application/utils/parse_app_url.ts @@ -0,0 +1,83 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { getUrlOrigin } from '@kbn/std'; +import { resolve } from 'url'; +import { IBasePath } from '../../http'; +import { App, ParsedAppUrl } from '../types'; + +/** + * Parse given URL and return the associated app id and path if any app matches, or undefined if none do. + * Input can either be: + * + * - an absolute path containing the basePath, + * e.g `/base-path/app/my-app/some-path` + * + * - an absolute URL matching the `origin` of the Kibana instance (as seen by the browser), + * e.g `https://kibana:8080/base-path/app/my-app/some-path` + * + * - a path relative to the provided `currentUrl`. + * e.g with `currentUrl` being `https://kibana:8080/base-path/app/current-app/some-path` + * `../other-app/other-path` will be converted to `/base-path/app/other-app/other-path` + */ +export const parseAppUrl = ( + url: string, + basePath: IBasePath, + apps: Map>, + currentUrl: string = window.location.href +): ParsedAppUrl | undefined => { + const currentOrigin = getUrlOrigin(currentUrl); + if (!currentOrigin) { + throw new Error('when manually provided, currentUrl must be valid url with an origin'); + } + const currentPath = currentUrl.substring(currentOrigin.length); + + // remove the origin from the given url + if (url.startsWith(currentOrigin)) { + url = url.substring(currentOrigin.length); + } + + // if the path is relative (i.e `../../to/somewhere`), we convert it to absolute + if (!url.startsWith('/')) { + url = resolve(currentPath, url); + } + + // if using a basePath and the absolute path does not starts with it, it can't be a match + const basePathValue = basePath.get(); + if (basePathValue && !url.startsWith(basePathValue)) { + return undefined; + } + + url = basePath.remove(url); + if (!url.startsWith('/')) { + return undefined; + } + + for (const app of apps.values()) { + const appPath = app.appRoute || `/app/${app.id}`; + + if (url.startsWith(appPath)) { + const path = url.substr(appPath.length); + return { + app: app.id, + path: path.length ? path : undefined, + }; + } + } +}; diff --git a/src/core/public/application/utils/relative_to_absolute.test.ts b/src/core/public/application/utils/relative_to_absolute.test.ts new file mode 100644 index 0000000000000..56a33450ce902 --- /dev/null +++ b/src/core/public/application/utils/relative_to_absolute.test.ts @@ -0,0 +1,29 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { relativeToAbsolute } from './relative_to_absolute'; + +describe('relativeToAbsolute', () => { + it('converts a relative path to an absolute url', () => { + const origin = window.location.origin; + expect(relativeToAbsolute('path')).toEqual(`${origin}/path`); + expect(relativeToAbsolute('/path#hash')).toEqual(`${origin}/path#hash`); + expect(relativeToAbsolute('/path?query=foo')).toEqual(`${origin}/path?query=foo`); + }); +}); diff --git a/src/core/public/application/utils/relative_to_absolute.ts b/src/core/public/application/utils/relative_to_absolute.ts new file mode 100644 index 0000000000000..0f24f754f56cd --- /dev/null +++ b/src/core/public/application/utils/relative_to_absolute.ts @@ -0,0 +1,35 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +/** + * Converts a relative path to an absolute url. + * Implementation is based on a specified behavior of the browser to automatically convert + * a relative url to an absolute one when setting the `href` attribute of a `` html element. + * + * @example + * ```ts + * // current url: `https://kibana:8000/base-path/app/my-app` + * relativeToAbsolute('/base-path/app/another-app') => `https://kibana:8000/base-path/app/another-app` + * ``` + */ +export const relativeToAbsolute = (url: string): string => { + const a = document.createElement('a'); + a.setAttribute('href', url); + return a.href; +}; diff --git a/src/core/public/application/utils/remove_slashes.test.ts b/src/core/public/application/utils/remove_slashes.test.ts new file mode 100644 index 0000000000000..719e1ea08d109 --- /dev/null +++ b/src/core/public/application/utils/remove_slashes.test.ts @@ -0,0 +1,53 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { removeSlashes } from './remove_slashes'; + +describe('removeSlashes', () => { + it('only removes duplicates by default', () => { + expect(removeSlashes('/some//url//to//')).toEqual('/some/url/to/'); + expect(removeSlashes('some/////other//url')).toEqual('some/other/url'); + }); + + it('remove trailing slash when `trailing` is true', () => { + expect(removeSlashes('/some//url//to//', { trailing: true })).toEqual('/some/url/to'); + }); + + it('remove leading slash when `leading` is true', () => { + expect(removeSlashes('/some//url//to//', { leading: true })).toEqual('some/url/to/'); + }); + + it('does not removes duplicates when `duplicates` is false', () => { + expect(removeSlashes('/some//url//to/', { leading: true, duplicates: false })).toEqual( + 'some//url//to/' + ); + expect(removeSlashes('/some//url//to/', { trailing: true, duplicates: false })).toEqual( + '/some//url//to' + ); + }); + + it('accept mixed options', () => { + expect( + removeSlashes('/some//url//to/', { leading: true, duplicates: false, trailing: true }) + ).toEqual('some//url//to'); + expect( + removeSlashes('/some//url//to/', { leading: true, duplicates: true, trailing: true }) + ).toEqual('some/url/to'); + }); +}); diff --git a/src/core/public/application/utils/remove_slashes.ts b/src/core/public/application/utils/remove_slashes.ts new file mode 100644 index 0000000000000..641d7bc4164f4 --- /dev/null +++ b/src/core/public/application/utils/remove_slashes.ts @@ -0,0 +1,42 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +/** + * Utility to remove trailing, leading or duplicate slashes. + * By default will only remove duplicates. + */ +export const removeSlashes = ( + url: string, + { + trailing = false, + leading = false, + duplicates = true, + }: { trailing?: boolean; leading?: boolean; duplicates?: boolean } = {} +): string => { + if (duplicates) { + url = url.replace(/\/{2,}/g, '/'); + } + if (trailing) { + url = url.replace(/\/$/, ''); + } + if (leading) { + url = url.replace(/^\//, ''); + } + return url; +}; diff --git a/src/core/public/chrome/ui/__snapshots__/loading_indicator.test.tsx.snap b/src/core/public/chrome/ui/__snapshots__/loading_indicator.test.tsx.snap index 3007be1e5dfe0..e6bf7e898d8c4 100644 --- a/src/core/public/chrome/ui/__snapshots__/loading_indicator.test.tsx.snap +++ b/src/core/public/chrome/ui/__snapshots__/loading_indicator.test.tsx.snap @@ -1,23 +1,19 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`kbnLoadingIndicator is hidden by default 1`] = ` -
-
-
+/> `; exports[`kbnLoadingIndicator is visible when loadingCount is > 0 1`] = ` -
-
-
+/> `; diff --git a/src/core/public/chrome/ui/_loading_indicator.scss b/src/core/public/chrome/ui/_loading_indicator.scss index ad934717b4b76..ccf1ecc873fc5 100644 --- a/src/core/public/chrome/ui/_loading_indicator.scss +++ b/src/core/public/chrome/ui/_loading_indicator.scss @@ -1,55 +1,4 @@ -$kbnLoadingIndicatorBackgroundSize: $euiSizeXXL * 10; -$kbnLoadingIndicatorColor1: tint($euiColorAccent, 15%); -$kbnLoadingIndicatorColor2: tint($euiColorAccent, 60%); - -/** - * 1. Position this loader on top of the content. - * 2. Make sure indicator isn't wider than the screen. - */ -.kbnLoadingIndicator { - position: fixed; // 1 - top: 0; // 1 - left: 0; // 1 - right: 0; // 1 - z-index: $euiZLevel2; // 1 - overflow: hidden; // 2 - height: $euiSizeXS / 2; - - &.hidden { - visibility: hidden; - opacity: 0; - transition-delay: 0.25s; - } -} - -.kbnLoadingIndicator__bar { - top: 0; - left: 0; - right: 0; - bottom: 0; - position: absolute; - z-index: $euiZLevel2 + 1; - visibility: visible; - display: block; - animation: kbn-animate-loading-indicator 2s linear infinite; - background-color: $kbnLoadingIndicatorColor2; - background-image: linear-gradient( - to right, - $kbnLoadingIndicatorColor1 0%, - $kbnLoadingIndicatorColor1 50%, - $kbnLoadingIndicatorColor2 50%, - $kbnLoadingIndicatorColor2 100% - ); - background-repeat: repeat-x; - background-size: $kbnLoadingIndicatorBackgroundSize $kbnLoadingIndicatorBackgroundSize; - width: 200%; -} - -@keyframes kbn-animate-loading-indicator { - from { - transform: translateX(0); - } - to { - transform: translateX(-$kbnLoadingIndicatorBackgroundSize); - } +.kbnLoadingIndicator-hidden { + visibility: hidden; + animation-play-state: paused; } diff --git a/src/core/public/chrome/ui/header/__snapshots__/collapsible_nav.test.tsx.snap b/src/core/public/chrome/ui/header/__snapshots__/collapsible_nav.test.tsx.snap index dc5ed3c44f25a..47b8aaefaf86a 100644 --- a/src/core/public/chrome/ui/header/__snapshots__/collapsible_nav.test.tsx.snap +++ b/src/core/public/chrome/ui/header/__snapshots__/collapsible_nav.test.tsx.snap @@ -1876,12 +1876,9 @@ exports[`CollapsibleNav renders links grouped by category 1`] = ` ] } > - +
- +
- -
-
-
-
, - ], - }, - Object { - "borders": "none", - "items": Array [ - , ], }, Object { "borders": "none", "items": Array [ + + + , + ], + }, + Object { + "borders": "none", + "items": Array [ + + + ,
-
- - -
- + showAsBar={false} + > + + + + +
+
+
+
+ +
+ +
+ + +
@@ -3050,6 +3118,24 @@ exports[`Header renders 1`] = ` +
+ +
+
+
- -
- - +
; + return ; } const toggleCollapsibleNavRef = createRef(); @@ -97,7 +99,6 @@ export function Header({ return ( <> -
, + , ], borders: 'none', }, { ...(observables.navControlsCenter$ && { - items: [], + items: [ + + + , + ], }), borders: 'none', }, { items: [ + + + , - - diff --git a/src/core/public/chrome/ui/header/header_breadcrumbs.tsx b/src/core/public/chrome/ui/header/header_breadcrumbs.tsx index 174c46981db53..52412f8990c7a 100644 --- a/src/core/public/chrome/ui/header/header_breadcrumbs.tsx +++ b/src/core/public/chrome/ui/header/header_breadcrumbs.tsx @@ -20,7 +20,7 @@ import { EuiHeaderBreadcrumbs } from '@elastic/eui'; import classNames from 'classnames'; import React from 'react'; -import { useObservable } from 'react-use'; +import useObservable from 'react-use/lib/useObservable'; import { Observable } from 'rxjs'; import { ChromeBreadcrumb } from '../../chrome_service'; diff --git a/src/core/public/chrome/ui/header/header_logo.tsx b/src/core/public/chrome/ui/header/header_logo.tsx index dee93ecb1a804..83e0c52ab3f3a 100644 --- a/src/core/public/chrome/ui/header/header_logo.tsx +++ b/src/core/public/chrome/ui/header/header_logo.tsx @@ -20,7 +20,7 @@ import { EuiHeaderLogo } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import React from 'react'; -import { useObservable } from 'react-use'; +import useObservable from 'react-use/lib/useObservable'; import { Observable } from 'rxjs'; import Url from 'url'; import { ChromeNavLink } from '../..'; diff --git a/src/core/public/chrome/ui/header/header_nav_controls.tsx b/src/core/public/chrome/ui/header/header_nav_controls.tsx index 8d9d8097fd8e3..69b0e3bd8afe3 100644 --- a/src/core/public/chrome/ui/header/header_nav_controls.tsx +++ b/src/core/public/chrome/ui/header/header_nav_controls.tsx @@ -19,7 +19,7 @@ import { EuiHeaderSectionItem } from '@elastic/eui'; import React from 'react'; -import { useObservable } from 'react-use'; +import useObservable from 'react-use/lib/useObservable'; import { Observable } from 'rxjs'; import { ChromeNavControl } from '../../nav_controls'; import { HeaderExtension } from './header_extension'; diff --git a/src/core/public/chrome/ui/loading_indicator.tsx b/src/core/public/chrome/ui/loading_indicator.tsx index 0209612eae08c..ca3e95f722ec5 100644 --- a/src/core/public/chrome/ui/loading_indicator.tsx +++ b/src/core/public/chrome/ui/loading_indicator.tsx @@ -17,6 +17,8 @@ * under the License. */ +import { EuiLoadingSpinner, EuiProgress } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; import React from 'react'; import classNames from 'classnames'; import { Subscription } from 'rxjs'; @@ -25,9 +27,12 @@ import { HttpStart } from '../../http'; export interface LoadingIndicatorProps { loadingCount$: ReturnType; + showAsBar?: boolean; } export class LoadingIndicator extends React.Component { + public static defaultProps = { showAsBar: false }; + private loadingCountSubscription?: Subscription; state = { @@ -50,16 +55,35 @@ export class LoadingIndicator extends React.Component -
-
+ const ariaHidden = this.state.visible ? false : true; + + const ariaLabel = i18n.translate('core.ui.loadingIndicatorAriaLabel', { + defaultMessage: 'Loading content', + }); + + return !this.props.showAsBar ? ( + + ) : ( + ); } } diff --git a/src/core/public/doc_links/doc_links_service.ts b/src/core/public/doc_links/doc_links_service.ts index 47f58a3a9fcbf..629bf97c24887 100644 --- a/src/core/public/doc_links/doc_links_service.ts +++ b/src/core/public/doc_links/doc_links_service.ts @@ -119,6 +119,7 @@ export class DocLinksService { gettingStarted: `${ELASTIC_WEBSITE_URL}guide/en/security/${DOC_LINK_VERSION}/index.html`, }, query: { + eql: `${ELASTICSEARCH_DOCS}eql.html`, luceneQuerySyntax: `${ELASTICSEARCH_DOCS}query-dsl-query-string-query.html#query-string-syntax`, queryDsl: `${ELASTICSEARCH_DOCS}query-dsl.html`, kueryQuerySyntax: `${ELASTIC_WEBSITE_URL}guide/en/kibana/${DOC_LINK_VERSION}/kuery-query.html`, @@ -227,6 +228,7 @@ export interface DocLinksStart { readonly gettingStarted: string; }; readonly query: { + readonly eql: string; readonly luceneQuerySyntax: string; readonly queryDsl: string; readonly kueryQuerySyntax: string; diff --git a/src/core/public/http/base_path.ts b/src/core/public/http/base_path.ts index 5d9eb51023b78..78e9cf75ff806 100644 --- a/src/core/public/http/base_path.ts +++ b/src/core/public/http/base_path.ts @@ -16,24 +16,6 @@ * specific language governing permissions and limitations * under the License. */ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ import { modifyUrl } from '@kbn/std'; diff --git a/src/core/public/i18n/i18n_eui_mapping.tsx b/src/core/public/i18n/i18n_eui_mapping.tsx index 4c7cdd18d03f6..3bb8fa39d4ff8 100644 --- a/src/core/public/i18n/i18n_eui_mapping.tsx +++ b/src/core/public/i18n/i18n_eui_mapping.tsx @@ -25,550 +25,564 @@ interface EuiValues { [key: string]: any; } -export const euiContextMapping = { - 'euiBasicTable.selectAllRows': i18n.translate('core.euiBasicTable.selectAllRows', { - defaultMessage: 'Select all rows', - description: 'ARIA and displayed label on a checkbox to select all table rows', - }), - 'euiBasicTable.selectThisRow': i18n.translate('core.euiBasicTable.selectThisRow', { - defaultMessage: 'Select this row', - description: 'ARIA and displayed label on a checkbox to select a single table row', - }), - 'euiBasicTable.tableDescription': ({ itemCount }: EuiValues) => - i18n.translate('core.euiBasicTable.tableDescription', { - defaultMessage: 'Below is a table of {itemCount} items.', - values: { itemCount }, - description: 'Screen reader text to describe the size of a table', - }), - 'euiBottomBar.screenReaderAnnouncement': i18n.translate( - 'core.euiBottomBar.screenReaderAnnouncement', - { - defaultMessage: - 'There is a new menu opening with page level controls at the end of the document.', - description: - 'Screen reader announcement that functionality is available in the page document', - } - ), - 'euiBreadcrumbs.collapsedBadge.ariaLabel': i18n.translate( - 'core.euiBreadcrumbs.collapsedBadge.ariaLabel', - { - defaultMessage: 'Show all breadcrumbs', - description: 'Displayed when one or more breadcrumbs are hidden.', - } - ), - 'euiCardSelect.select': i18n.translate('core.euiCardSelect.select', { - defaultMessage: 'Select', - description: 'Displayed button text when a card option can be selected.', - }), - 'euiCardSelect.selected': i18n.translate('core.euiCardSelect.selected', { - defaultMessage: 'Selected', - description: 'Displayed button text when a card option is selected.', - }), - 'euiCardSelect.unavailable': i18n.translate('core.euiCardSelect.unavailable', { - defaultMessage: 'Unavailable', - description: 'Displayed button text when a card option is unavailable.', - }), - 'euiCodeBlock.copyButton': i18n.translate('core.euiCodeBlock.copyButton', { - defaultMessage: 'Copy', - description: 'ARIA label for a button that copies source code text to the clipboard', - }), - 'euiCodeEditor.startEditing': i18n.translate('core.euiCodeEditor.startEditing', { - defaultMessage: 'Press Enter to start editing.', - }), - 'euiCodeEditor.startInteracting': i18n.translate('core.euiCodeEditor.startInteracting', { - defaultMessage: 'Press Enter to start interacting with the code.', - }), - 'euiCodeEditor.stopEditing': i18n.translate('core.euiCodeEditor.stopEditing', { - defaultMessage: "When you're done, press Escape to stop editing.", - }), - 'euiCodeEditor.stopInteracting': i18n.translate('core.euiCodeEditor.stopInteracting', { - defaultMessage: "When you're done, press Escape to stop interacting with the code.", - }), - 'euiCollapsedItemActions.allActions': i18n.translate('core.euiCollapsedItemActions.allActions', { - defaultMessage: 'All actions', - description: 'ARIA label and tooltip content describing a button that expands an actions menu', - }), - 'euiColorPicker.screenReaderAnnouncement': i18n.translate( - 'core.euiColorPicker.screenReaderAnnouncement', - { - defaultMessage: - 'A popup with a range of selectable colors opened. Tab forward to cycle through colors choices or press escape to close this popup.', - description: - 'Message when the color picker popover is opened. Describes the interaction with the elements in the popover.', - } - ), - 'euiColorPicker.swatchAriaLabel': ({ swatch }: EuiValues) => - i18n.translate('core.euiColorPicker.swatchAriaLabel', { - defaultMessage: 'Select {swatch} as the color', - values: { swatch }, - description: - 'Screen reader text to describe the action and hex value of the selectable option', - }), - 'euiColorStopThumb.removeLabel': i18n.translate('core.euiColorStopThumb.removeLabel', { - defaultMessage: 'Remove this stop', - description: 'Label accompanying a button whose action will remove the color stop', - }), - 'euiColorStopThumb.screenReaderAnnouncement': i18n.translate( - 'core.euiColorStopThumb.screenReaderAnnouncement', - { - defaultMessage: - 'A popup with a color stop edit form opened. Tab forward to cycle through form controls or press escape to close this popup.', - description: - 'Message when the color picker popover has opened for an individual color stop thumb.', - } - ), - 'euiColorStops.screenReaderAnnouncement': ({ label, readOnly, disabled }: EuiValues) => - i18n.translate('core.euiColorStops.screenReaderAnnouncement', { - defaultMessage: - '{label}: {readOnly} {disabled} Color stop picker. Each stop consists of a number and corresponding color value. Use the Down and Up arrow keys to select individual stops. Press the Enter key to create a new stop.', - values: { label, readOnly, disabled }, - description: - 'Screen reader text to describe the composite behavior of the color stops component.', - }), - 'euiColumnSelector.hideAll': i18n.translate('core.euiColumnSelector.hideAll', { - defaultMessage: 'Hide all', - }), - 'euiColumnSelector.selectAll': i18n.translate('core.euiColumnSelector.selectAll', { - defaultMessage: 'Show all', - }), - 'euiColumnSorting.clearAll': i18n.translate('core.euiColumnSorting.clearAll', { - defaultMessage: 'Clear sorting', - }), - 'euiColumnSorting.emptySorting': i18n.translate('core.euiColumnSorting.emptySorting', { - defaultMessage: 'Currently no fields are sorted', - }), - 'euiColumnSorting.pickFields': i18n.translate('core.euiColumnSorting.pickFields', { - defaultMessage: 'Pick fields to sort by', - }), - 'euiColumnSorting.sortFieldAriaLabel': i18n.translate( - 'core.euiColumnSorting.sortFieldAriaLabel', - { - defaultMessage: 'Sort by:', - } - ), - 'euiColumnSortingDraggable.activeSortLabel': i18n.translate( - 'core.euiColumnSortingDraggable.activeSortLabel', - { - defaultMessage: 'is sorting this data grid', - } - ), - 'euiColumnSortingDraggable.defaultSortAsc': i18n.translate( - 'core.euiColumnSortingDraggable.defaultSortAsc', - { - defaultMessage: 'A-Z', - description: 'Ascending sort label', - } - ), - 'euiColumnSortingDraggable.defaultSortDesc': i18n.translate( - 'core.euiColumnSortingDraggable.defaultSortDesc', - { - defaultMessage: 'Z-A', - description: 'Descending sort label', - } - ), - 'euiColumnSortingDraggable.removeSortLabel': i18n.translate( - 'core.euiColumnSortingDraggable.removeSortLabel', - { - defaultMessage: 'Remove from data grid sort:', - } - ), - 'euiColumnSortingDraggable.toggleLegend': i18n.translate( - 'core.euiColumnSortingDraggable.toggleLegend', - { - defaultMessage: 'Select sorting method for field:', - } - ), - 'euiComboBoxOptionsList.allOptionsSelected': i18n.translate( - 'core.euiComboBoxOptionsList.allOptionsSelected', - { - defaultMessage: "You've selected all available options", - } - ), - 'euiComboBoxOptionsList.alreadyAdded': ({ label }: EuiValues) => ( - - ), - 'euiComboBoxOptionsList.createCustomOption': ({ key, searchValue }: EuiValues) => ( - - ), - 'euiComboBoxOptionsList.loadingOptions': i18n.translate( - 'core.euiComboBoxOptionsList.loadingOptions', - { +export const getEuiContextMapping = () => { + const euiContextMapping = { + 'euiBasicTable.selectAllRows': i18n.translate('core.euiBasicTable.selectAllRows', { + defaultMessage: 'Select all rows', + description: 'ARIA and displayed label on a checkbox to select all table rows', + }), + 'euiBasicTable.selectThisRow': i18n.translate('core.euiBasicTable.selectThisRow', { + defaultMessage: 'Select this row', + description: 'ARIA and displayed label on a checkbox to select a single table row', + }), + 'euiBasicTable.tableDescription': ({ itemCount }: EuiValues) => + i18n.translate('core.euiBasicTable.tableDescription', { + defaultMessage: 'Below is a table of {itemCount} items.', + values: { itemCount }, + description: 'Screen reader text to describe the size of a table', + }), + 'euiBottomBar.screenReaderAnnouncement': i18n.translate( + 'core.euiBottomBar.screenReaderAnnouncement', + { + defaultMessage: + 'There is a new menu opening with page level controls at the end of the document.', + description: + 'Screen reader announcement that functionality is available in the page document', + } + ), + 'euiBreadcrumbs.collapsedBadge.ariaLabel': i18n.translate( + 'core.euiBreadcrumbs.collapsedBadge.ariaLabel', + { + defaultMessage: 'Show all breadcrumbs', + description: 'Displayed when one or more breadcrumbs are hidden.', + } + ), + 'euiCardSelect.select': i18n.translate('core.euiCardSelect.select', { + defaultMessage: 'Select', + description: 'Displayed button text when a card option can be selected.', + }), + 'euiCardSelect.selected': i18n.translate('core.euiCardSelect.selected', { + defaultMessage: 'Selected', + description: 'Displayed button text when a card option is selected.', + }), + 'euiCardSelect.unavailable': i18n.translate('core.euiCardSelect.unavailable', { + defaultMessage: 'Unavailable', + description: 'Displayed button text when a card option is unavailable.', + }), + 'euiCodeBlock.copyButton': i18n.translate('core.euiCodeBlock.copyButton', { + defaultMessage: 'Copy', + description: 'ARIA label for a button that copies source code text to the clipboard', + }), + 'euiCodeEditor.startEditing': i18n.translate('core.euiCodeEditor.startEditing', { + defaultMessage: 'Press Enter to start editing.', + }), + 'euiCodeEditor.startInteracting': i18n.translate('core.euiCodeEditor.startInteracting', { + defaultMessage: 'Press Enter to start interacting with the code.', + }), + 'euiCodeEditor.stopEditing': i18n.translate('core.euiCodeEditor.stopEditing', { + defaultMessage: "When you're done, press Escape to stop editing.", + }), + 'euiCodeEditor.stopInteracting': i18n.translate('core.euiCodeEditor.stopInteracting', { + defaultMessage: "When you're done, press Escape to stop interacting with the code.", + }), + 'euiCollapsedItemActions.allActions': i18n.translate( + 'core.euiCollapsedItemActions.allActions', + { + defaultMessage: 'All actions', + description: + 'ARIA label and tooltip content describing a button that expands an actions menu', + } + ), + 'euiColorPicker.screenReaderAnnouncement': i18n.translate( + 'core.euiColorPicker.screenReaderAnnouncement', + { + defaultMessage: + 'A popup with a range of selectable colors opened. Tab forward to cycle through colors choices or press escape to close this popup.', + description: + 'Message when the color picker popover is opened. Describes the interaction with the elements in the popover.', + } + ), + 'euiColorPicker.swatchAriaLabel': ({ swatch }: EuiValues) => + i18n.translate('core.euiColorPicker.swatchAriaLabel', { + defaultMessage: 'Select {swatch} as the color', + values: { swatch }, + description: + 'Screen reader text to describe the action and hex value of the selectable option', + }), + 'euiColorStopThumb.removeLabel': i18n.translate('core.euiColorStopThumb.removeLabel', { + defaultMessage: 'Remove this stop', + description: 'Label accompanying a button whose action will remove the color stop', + }), + 'euiColorStopThumb.screenReaderAnnouncement': i18n.translate( + 'core.euiColorStopThumb.screenReaderAnnouncement', + { + defaultMessage: + 'A popup with a color stop edit form opened. Tab forward to cycle through form controls or press escape to close this popup.', + description: + 'Message when the color picker popover has opened for an individual color stop thumb.', + } + ), + 'euiColorStops.screenReaderAnnouncement': ({ label, readOnly, disabled }: EuiValues) => + i18n.translate('core.euiColorStops.screenReaderAnnouncement', { + defaultMessage: + '{label}: {readOnly} {disabled} Color stop picker. Each stop consists of a number and corresponding color value. Use the Down and Up arrow keys to select individual stops. Press the Enter key to create a new stop.', + values: { label, readOnly, disabled }, + description: + 'Screen reader text to describe the composite behavior of the color stops component.', + }), + 'euiColumnSelector.hideAll': i18n.translate('core.euiColumnSelector.hideAll', { + defaultMessage: 'Hide all', + }), + 'euiColumnSelector.selectAll': i18n.translate('core.euiColumnSelector.selectAll', { + defaultMessage: 'Show all', + }), + 'euiColumnSorting.clearAll': i18n.translate('core.euiColumnSorting.clearAll', { + defaultMessage: 'Clear sorting', + }), + 'euiColumnSorting.emptySorting': i18n.translate('core.euiColumnSorting.emptySorting', { + defaultMessage: 'Currently no fields are sorted', + }), + 'euiColumnSorting.pickFields': i18n.translate('core.euiColumnSorting.pickFields', { + defaultMessage: 'Pick fields to sort by', + }), + 'euiColumnSorting.sortFieldAriaLabel': i18n.translate( + 'core.euiColumnSorting.sortFieldAriaLabel', + { + defaultMessage: 'Sort by:', + } + ), + 'euiColumnSortingDraggable.activeSortLabel': i18n.translate( + 'core.euiColumnSortingDraggable.activeSortLabel', + { + defaultMessage: 'is sorting this data grid', + } + ), + 'euiColumnSortingDraggable.defaultSortAsc': i18n.translate( + 'core.euiColumnSortingDraggable.defaultSortAsc', + { + defaultMessage: 'A-Z', + description: 'Ascending sort label', + } + ), + 'euiColumnSortingDraggable.defaultSortDesc': i18n.translate( + 'core.euiColumnSortingDraggable.defaultSortDesc', + { + defaultMessage: 'Z-A', + description: 'Descending sort label', + } + ), + 'euiColumnSortingDraggable.removeSortLabel': i18n.translate( + 'core.euiColumnSortingDraggable.removeSortLabel', + { + defaultMessage: 'Remove from data grid sort:', + } + ), + 'euiColumnSortingDraggable.toggleLegend': i18n.translate( + 'core.euiColumnSortingDraggable.toggleLegend', + { + defaultMessage: 'Select sorting method for field:', + } + ), + 'euiComboBoxOptionsList.allOptionsSelected': i18n.translate( + 'core.euiComboBoxOptionsList.allOptionsSelected', + { + defaultMessage: "You've selected all available options", + } + ), + 'euiComboBoxOptionsList.alreadyAdded': ({ label }: EuiValues) => ( + + ), + 'euiComboBoxOptionsList.createCustomOption': ({ key, searchValue }: EuiValues) => ( + + ), + 'euiComboBoxOptionsList.loadingOptions': i18n.translate( + 'core.euiComboBoxOptionsList.loadingOptions', + { + defaultMessage: 'Loading options', + description: 'Placeholder message while data is asynchronously loaded', + } + ), + 'euiComboBoxOptionsList.noAvailableOptions': i18n.translate( + 'core.euiComboBoxOptionsList.noAvailableOptions', + { + defaultMessage: "There aren't any options available", + } + ), + 'euiComboBoxOptionsList.noMatchingOptions': ({ searchValue }: EuiValues) => ( + + ), + 'euiComboBoxPill.removeSelection': ({ children }: EuiValues) => + i18n.translate('core.euiComboBoxPill.removeSelection', { + defaultMessage: 'Remove {children} from selection in this group', + values: { children }, + description: 'ARIA label, `children` is the human-friendly value of an option', + }), + 'euiCommonlyUsedTimeRanges.legend': i18n.translate('core.euiCommonlyUsedTimeRanges.legend', { + defaultMessage: 'Commonly used', + }), + 'euiDataGrid.screenReaderNotice': i18n.translate('core.euiDataGrid.screenReaderNotice', { + defaultMessage: 'Cell contains interactive content.', + }), + 'euiDataGridCell.expandButtonTitle': i18n.translate('core.euiDataGridCell.expandButtonTitle', { + defaultMessage: 'Click or hit enter to interact with cell content', + }), + 'euiDataGridSchema.booleanSortTextAsc': i18n.translate( + 'core.euiDataGridSchema.booleanSortTextAsc', + { + defaultMessage: 'True-False', + description: 'Ascending boolean label', + } + ), + 'euiDataGridSchema.booleanSortTextDesc': i18n.translate( + 'core.euiDataGridSchema.booleanSortTextDesc', + { + defaultMessage: 'False-True', + description: 'Descending boolean label', + } + ), + 'euiDataGridSchema.currencySortTextAsc': i18n.translate( + 'core.euiDataGridSchema.currencySortTextAsc', + { + defaultMessage: 'Low-High', + description: 'Ascending currency label', + } + ), + 'euiDataGridSchema.currencySortTextDesc': i18n.translate( + 'core.euiDataGridSchema.currencySortTextDesc', + { + defaultMessage: 'High-Low', + description: 'Descending currency label', + } + ), + 'euiDataGridSchema.dateSortTextAsc': i18n.translate('core.euiDataGridSchema.dateSortTextAsc', { + defaultMessage: 'New-Old', + description: 'Ascending date label', + }), + 'euiDataGridSchema.dateSortTextDesc': i18n.translate( + 'core.euiDataGridSchema.dateSortTextDesc', + { + defaultMessage: 'Old-New', + description: 'Descending date label', + } + ), + 'euiDataGridSchema.numberSortTextAsc': i18n.translate( + 'core.euiDataGridSchema.numberSortTextAsc', + { + defaultMessage: 'Low-High', + description: 'Ascending number label', + } + ), + 'euiDataGridSchema.numberSortTextDesc': i18n.translate( + 'core.euiDataGridSchema.numberSortTextDesc', + { + defaultMessage: 'High-Low', + description: 'Descending number label', + } + ), + 'euiDataGridSchema.jsonSortTextAsc': i18n.translate('core.euiDataGridSchema.jsonSortTextAsc', { + defaultMessage: 'Small-Large', + description: 'Ascending size label', + }), + 'euiDataGridSchema.jsonSortTextDesc': i18n.translate( + 'core.euiDataGridSchema.jsonSortTextDesc', + { + defaultMessage: 'Large-Small', + description: 'Descending size label', + } + ), + 'euiFilterButton.filterBadge': ({ count, hasActiveFilters }: EuiValues) => + i18n.translate('core.euiFilterButton.filterBadge', { + defaultMessage: '${count} ${filterCountLabel} filters', + values: { count, filterCountLabel: hasActiveFilters ? 'active' : 'available' }, + }), + 'euiForm.addressFormErrors': i18n.translate('core.euiForm.addressFormErrors', { + defaultMessage: 'Please address the errors in your form.', + }), + 'euiFormControlLayoutClearButton.label': i18n.translate( + 'core.euiFormControlLayoutClearButton.label', + { + defaultMessage: 'Clear input', + description: 'ARIA label on a button that removes any entry in a form field', + } + ), + 'euiHeaderAlert.dismiss': i18n.translate('core.euiHeaderAlert.dismiss', { + defaultMessage: 'Dismiss', + description: 'ARIA label on a button that dismisses/removes a notification', + }), + 'euiHeaderLinks.appNavigation': i18n.translate('core.euiHeaderLinks.appNavigation', { + defaultMessage: 'App navigation', + description: 'ARIA label on a `nav` element', + }), + 'euiHeaderLinks.openNavigationMenu': i18n.translate('core.euiHeaderLinks.openNavigationMenu', { + defaultMessage: 'Open navigation menu', + }), + 'euiHue.label': i18n.translate('core.euiHue.label', { + defaultMessage: 'Select the HSV color mode "hue" value', + }), + 'euiImage.closeImage': ({ alt }: EuiValues) => + i18n.translate('core.euiImage.closeImage', { + defaultMessage: 'Close full screen {alt} image', + values: { alt }, + }), + 'euiImage.openImage': ({ alt }: EuiValues) => + i18n.translate('core.euiImage.openImage', { + defaultMessage: 'Open full screen {alt} image', + values: { alt }, + }), + 'euiLink.external.ariaLabel': i18n.translate('core.euiLink.external.ariaLabel', { + defaultMessage: 'External link', + }), + 'euiModal.closeModal': i18n.translate('core.euiModal.closeModal', { + defaultMessage: 'Closes this modal window', + }), + 'euiPagination.jumpToLastPage': ({ pageCount }: EuiValues) => + i18n.translate('core.euiPagination.jumpToLastPage', { + defaultMessage: 'Jump to the last page, number {pageCount}', + values: { pageCount }, + }), + 'euiPagination.nextPage': i18n.translate('core.euiPagination.nextPage', { + defaultMessage: 'Next page', + }), + 'euiPagination.pageOfTotal': ({ page, total }: EuiValues) => + i18n.translate('core.euiPagination.pageOfTotal', { + defaultMessage: 'Page {page} of {total}', + values: { page, total }, + }), + 'euiPagination.previousPage': i18n.translate('core.euiPagination.previousPage', { + defaultMessage: 'Previous page', + }), + 'euiPopover.screenReaderAnnouncement': i18n.translate( + 'core.euiPopover.screenReaderAnnouncement', + { + defaultMessage: 'You are in a dialog. To close this dialog, hit escape.', + } + ), + 'euiQuickSelect.applyButton': i18n.translate('core.euiQuickSelect.applyButton', { + defaultMessage: 'Apply', + }), + 'euiQuickSelect.fullDescription': ({ timeTense, timeValue, timeUnit }: EuiValues) => + i18n.translate('core.euiQuickSelect.fullDescription', { + defaultMessage: 'Currently set to {timeTense} {timeValue} {timeUnit}.', + values: { timeTense, timeValue, timeUnit }, + }), + 'euiQuickSelect.legendText': i18n.translate('core.euiQuickSelect.legendText', { + defaultMessage: 'Quick select a time range', + }), + 'euiQuickSelect.nextLabel': i18n.translate('core.euiQuickSelect.nextLabel', { + defaultMessage: 'Next time window', + }), + 'euiQuickSelect.previousLabel': i18n.translate('core.euiQuickSelect.previousLabel', { + defaultMessage: 'Previous time window', + }), + 'euiQuickSelect.quickSelectTitle': i18n.translate('core.euiQuickSelect.quickSelectTitle', { + defaultMessage: 'Quick select', + }), + 'euiQuickSelect.tenseLabel': i18n.translate('core.euiQuickSelect.tenseLabel', { + defaultMessage: 'Time tense', + }), + 'euiQuickSelect.unitLabel': i18n.translate('core.euiQuickSelect.unitLabel', { + defaultMessage: 'Time unit', + }), + 'euiQuickSelect.valueLabel': i18n.translate('core.euiQuickSelect.valueLabel', { + defaultMessage: 'Time value', + }), + 'euiRefreshInterval.fullDescription': ({ optionValue, optionText }: EuiValues) => + i18n.translate('core.euiRefreshInterval.fullDescription', { + defaultMessage: 'Currently set to {optionValue} {optionText}.', + values: { optionValue, optionText }, + }), + 'euiRefreshInterval.legend': i18n.translate('core.euiRefreshInterval.legend', { + defaultMessage: 'Refresh every', + }), + 'euiRefreshInterval.start': i18n.translate('core.euiRefreshInterval.start', { + defaultMessage: 'Start', + }), + 'euiRefreshInterval.stop': i18n.translate('core.euiRefreshInterval.stop', { + defaultMessage: 'Stop', + }), + 'euiRelativeTab.fullDescription': ({ unit }: EuiValues) => + i18n.translate('core.euiRelativeTab.fullDescription', { + defaultMessage: 'The unit is changeable. Currently set to {unit}.', + values: { unit }, + }), + 'euiRelativeTab.relativeDate': ({ position }: EuiValues) => + i18n.translate('core.euiRelativeTab.relativeDate', { + defaultMessage: '{position} date', + values: { position }, + }), + 'euiRelativeTab.roundingLabel': ({ unit }: EuiValues) => + i18n.translate('core.euiRelativeTab.roundingLabel', { + defaultMessage: 'Round to the {unit}', + values: { unit }, + }), + 'euiRelativeTab.unitInputLabel': i18n.translate('core.euiRelativeTab.unitInputLabel', { + defaultMessage: 'Relative time span', + }), + 'euiSaturation.roleDescription': i18n.translate('core.euiSaturation.roleDescription', { + defaultMessage: 'HSV color mode saturation and value selection', + }), + 'euiSaturation.screenReaderAnnouncement': i18n.translate( + 'core.euiSaturation.screenReaderAnnouncement', + { + defaultMessage: + 'Use the arrow keys to navigate the square color gradient. The coordinates resulting from each key press will be used to calculate HSV color mode "saturation" and "value" numbers, in the range of 0 to 1. Left and right decrease and increase (respectively) the "saturation" value. Up and down decrease and increase (respectively) the "value" value.', + } + ), + 'euiSelectable.loadingOptions': i18n.translate('core.euiSelectable.loadingOptions', { defaultMessage: 'Loading options', description: 'Placeholder message while data is asynchronously loaded', - } - ), - 'euiComboBoxOptionsList.noAvailableOptions': i18n.translate( - 'core.euiComboBoxOptionsList.noAvailableOptions', - { + }), + 'euiSelectable.noAvailableOptions': i18n.translate('core.euiSelectable.noAvailableOptions', { defaultMessage: "There aren't any options available", - } - ), - 'euiComboBoxOptionsList.noMatchingOptions': ({ searchValue }: EuiValues) => ( - - ), - 'euiComboBoxPill.removeSelection': ({ children }: EuiValues) => - i18n.translate('core.euiComboBoxPill.removeSelection', { - defaultMessage: 'Remove {children} from selection in this group', - values: { children }, - description: 'ARIA label, `children` is the human-friendly value of an option', - }), - 'euiCommonlyUsedTimeRanges.legend': i18n.translate('core.euiCommonlyUsedTimeRanges.legend', { - defaultMessage: 'Commonly used', - }), - 'euiDataGrid.screenReaderNotice': i18n.translate('core.euiDataGrid.screenReaderNotice', { - defaultMessage: 'Cell contains interactive content.', - }), - 'euiDataGridCell.expandButtonTitle': i18n.translate('core.euiDataGridCell.expandButtonTitle', { - defaultMessage: 'Click or hit enter to interact with cell content', - }), - 'euiDataGridSchema.booleanSortTextAsc': i18n.translate( - 'core.euiDataGridSchema.booleanSortTextAsc', - { - defaultMessage: 'True-False', - description: 'Ascending boolean label', - } - ), - 'euiDataGridSchema.booleanSortTextDesc': i18n.translate( - 'core.euiDataGridSchema.booleanSortTextDesc', - { - defaultMessage: 'False-True', - description: 'Descending boolean label', - } - ), - 'euiDataGridSchema.currencySortTextAsc': i18n.translate( - 'core.euiDataGridSchema.currencySortTextAsc', - { - defaultMessage: 'Low-High', - description: 'Ascending currency label', - } - ), - 'euiDataGridSchema.currencySortTextDesc': i18n.translate( - 'core.euiDataGridSchema.currencySortTextDesc', - { - defaultMessage: 'High-Low', - description: 'Descending currency label', - } - ), - 'euiDataGridSchema.dateSortTextAsc': i18n.translate('core.euiDataGridSchema.dateSortTextAsc', { - defaultMessage: 'New-Old', - description: 'Ascending date label', - }), - 'euiDataGridSchema.dateSortTextDesc': i18n.translate('core.euiDataGridSchema.dateSortTextDesc', { - defaultMessage: 'Old-New', - description: 'Descending date label', - }), - 'euiDataGridSchema.numberSortTextAsc': i18n.translate( - 'core.euiDataGridSchema.numberSortTextAsc', - { - defaultMessage: 'Low-High', - description: 'Ascending number label', - } - ), - 'euiDataGridSchema.numberSortTextDesc': i18n.translate( - 'core.euiDataGridSchema.numberSortTextDesc', - { - defaultMessage: 'High-Low', - description: 'Descending number label', - } - ), - 'euiDataGridSchema.jsonSortTextAsc': i18n.translate('core.euiDataGridSchema.jsonSortTextAsc', { - defaultMessage: 'Small-Large', - description: 'Ascending size label', - }), - 'euiDataGridSchema.jsonSortTextDesc': i18n.translate('core.euiDataGridSchema.jsonSortTextDesc', { - defaultMessage: 'Large-Small', - description: 'Descending size label', - }), - 'euiFilterButton.filterBadge': ({ count, hasActiveFilters }: EuiValues) => - i18n.translate('core.euiFilterButton.filterBadge', { - defaultMessage: '${count} ${filterCountLabel} filters', - values: { count, filterCountLabel: hasActiveFilters ? 'active' : 'available' }, - }), - 'euiForm.addressFormErrors': i18n.translate('core.euiForm.addressFormErrors', { - defaultMessage: 'Please address the errors in your form.', - }), - 'euiFormControlLayoutClearButton.label': i18n.translate( - 'core.euiFormControlLayoutClearButton.label', - { - defaultMessage: 'Clear input', - description: 'ARIA label on a button that removes any entry in a form field', - } - ), - 'euiHeaderAlert.dismiss': i18n.translate('core.euiHeaderAlert.dismiss', { - defaultMessage: 'Dismiss', - description: 'ARIA label on a button that dismisses/removes a notification', - }), - 'euiHeaderLinks.appNavigation': i18n.translate('core.euiHeaderLinks.appNavigation', { - defaultMessage: 'App navigation', - description: 'ARIA label on a `nav` element', - }), - 'euiHeaderLinks.openNavigationMenu': i18n.translate('core.euiHeaderLinks.openNavigationMenu', { - defaultMessage: 'Open navigation menu', - }), - 'euiHue.label': i18n.translate('core.euiHue.label', { - defaultMessage: 'Select the HSV color mode "hue" value', - }), - 'euiImage.closeImage': ({ alt }: EuiValues) => - i18n.translate('core.euiImage.closeImage', { - defaultMessage: 'Close full screen {alt} image', - values: { alt }, - }), - 'euiImage.openImage': ({ alt }: EuiValues) => - i18n.translate('core.euiImage.openImage', { - defaultMessage: 'Open full screen {alt} image', - values: { alt }, - }), - 'euiLink.external.ariaLabel': i18n.translate('core.euiLink.external.ariaLabel', { - defaultMessage: 'External link', - }), - 'euiModal.closeModal': i18n.translate('core.euiModal.closeModal', { - defaultMessage: 'Closes this modal window', - }), - 'euiPagination.jumpToLastPage': ({ pageCount }: EuiValues) => - i18n.translate('core.euiPagination.jumpToLastPage', { - defaultMessage: 'Jump to the last page, number {pageCount}', - values: { pageCount }, - }), - 'euiPagination.nextPage': i18n.translate('core.euiPagination.nextPage', { - defaultMessage: 'Next page', - }), - 'euiPagination.pageOfTotal': ({ page, total }: EuiValues) => - i18n.translate('core.euiPagination.pageOfTotal', { - defaultMessage: 'Page {page} of {total}', - values: { page, total }, - }), - 'euiPagination.previousPage': i18n.translate('core.euiPagination.previousPage', { - defaultMessage: 'Previous page', - }), - 'euiPopover.screenReaderAnnouncement': i18n.translate( - 'core.euiPopover.screenReaderAnnouncement', - { - defaultMessage: 'You are in a dialog. To close this dialog, hit escape.', - } - ), - 'euiQuickSelect.applyButton': i18n.translate('core.euiQuickSelect.applyButton', { - defaultMessage: 'Apply', - }), - 'euiQuickSelect.fullDescription': ({ timeTense, timeValue, timeUnit }: EuiValues) => - i18n.translate('core.euiQuickSelect.fullDescription', { - defaultMessage: 'Currently set to {timeTense} {timeValue} {timeUnit}.', - values: { timeTense, timeValue, timeUnit }, - }), - 'euiQuickSelect.legendText': i18n.translate('core.euiQuickSelect.legendText', { - defaultMessage: 'Quick select a time range', - }), - 'euiQuickSelect.nextLabel': i18n.translate('core.euiQuickSelect.nextLabel', { - defaultMessage: 'Next time window', - }), - 'euiQuickSelect.previousLabel': i18n.translate('core.euiQuickSelect.previousLabel', { - defaultMessage: 'Previous time window', - }), - 'euiQuickSelect.quickSelectTitle': i18n.translate('core.euiQuickSelect.quickSelectTitle', { - defaultMessage: 'Quick select', - }), - 'euiQuickSelect.tenseLabel': i18n.translate('core.euiQuickSelect.tenseLabel', { - defaultMessage: 'Time tense', - }), - 'euiQuickSelect.unitLabel': i18n.translate('core.euiQuickSelect.unitLabel', { - defaultMessage: 'Time unit', - }), - 'euiQuickSelect.valueLabel': i18n.translate('core.euiQuickSelect.valueLabel', { - defaultMessage: 'Time value', - }), - 'euiRefreshInterval.fullDescription': ({ optionValue, optionText }: EuiValues) => - i18n.translate('core.euiRefreshInterval.fullDescription', { - defaultMessage: 'Currently set to {optionValue} {optionText}.', - values: { optionValue, optionText }, - }), - 'euiRefreshInterval.legend': i18n.translate('core.euiRefreshInterval.legend', { - defaultMessage: 'Refresh every', - }), - 'euiRefreshInterval.start': i18n.translate('core.euiRefreshInterval.start', { - defaultMessage: 'Start', - }), - 'euiRefreshInterval.stop': i18n.translate('core.euiRefreshInterval.stop', { - defaultMessage: 'Stop', - }), - 'euiRelativeTab.fullDescription': ({ unit }: EuiValues) => - i18n.translate('core.euiRelativeTab.fullDescription', { - defaultMessage: 'The unit is changeable. Currently set to {unit}.', - values: { unit }, - }), - 'euiRelativeTab.relativeDate': ({ position }: EuiValues) => - i18n.translate('core.euiRelativeTab.relativeDate', { - defaultMessage: '{position} date', - values: { position }, - }), - 'euiRelativeTab.roundingLabel': ({ unit }: EuiValues) => - i18n.translate('core.euiRelativeTab.roundingLabel', { - defaultMessage: 'Round to the {unit}', - values: { unit }, - }), - 'euiRelativeTab.unitInputLabel': i18n.translate('core.euiRelativeTab.unitInputLabel', { - defaultMessage: 'Relative time span', - }), - 'euiSaturation.roleDescription': i18n.translate('core.euiSaturation.roleDescription', { - defaultMessage: 'HSV color mode saturation and value selection', - }), - 'euiSaturation.screenReaderAnnouncement': i18n.translate( - 'core.euiSaturation.screenReaderAnnouncement', - { - defaultMessage: - 'Use the arrow keys to navigate the square color gradient. The coordinates resulting from each key press will be used to calculate HSV color mode "saturation" and "value" numbers, in the range of 0 to 1. Left and right decrease and increase (respectively) the "saturation" value. Up and down decrease and increase (respectively) the "value" value.', - } - ), - 'euiSelectable.loadingOptions': i18n.translate('core.euiSelectable.loadingOptions', { - defaultMessage: 'Loading options', - description: 'Placeholder message while data is asynchronously loaded', - }), - 'euiSelectable.noAvailableOptions': i18n.translate('core.euiSelectable.noAvailableOptions', { - defaultMessage: "There aren't any options available", - }), - 'euiSelectable.noMatchingOptions': ({ searchValue }: EuiValues) => ( - - ), - 'euiStat.loadingText': i18n.translate('core.euiStat.loadingText', { - defaultMessage: 'Statistic is loading', - }), - 'euiStep.ariaLabel': ({ status }: EuiValues) => - i18n.translate('core.euiStep.ariaLabel', { - defaultMessage: '{stepStatus}', - values: { stepStatus: status === 'incomplete' ? 'Incomplete Step' : 'Step' }, - }), - 'euiStepHorizontal.buttonTitle': ({ step, title, disabled, isComplete }: EuiValues) => { - return i18n.translate('core.euiStepHorizontal.buttonTitle', { - defaultMessage: 'Step {step}: {title}{titleAppendix}', - values: { - step, - title, - titleAppendix: disabled ? ' is disabled' : isComplete ? ' is complete' : '', - }, - }); - }, - 'euiStepHorizontal.step': i18n.translate('core.euiStepHorizontal.step', { - defaultMessage: 'Step', - description: 'Screen reader text announcing information about a step in some process', - }), - 'euiStepNumber.hasErrors': i18n.translate('core.euiStepNumber.hasErrors', { - defaultMessage: 'has errors', - description: - 'Used as the title attribute on an image or svg icon to indicate a given process step has errors', - }), - 'euiStepNumber.hasWarnings': i18n.translate('core.euiStepNumber.hasWarnings', { - defaultMessage: 'has warnings', - description: - 'Used as the title attribute on an image or svg icon to indicate a given process step has warnings', - }), - 'euiStepNumber.isComplete': i18n.translate('core.euiStepNumber.isComplete', { - defaultMessage: 'complete', - description: - 'Used as the title attribute on an image or svg icon to indicate a given process step is complete', - }), - 'euiStyleSelector.buttonText': i18n.translate('core.euiStyleSelector.buttonText', { - defaultMessage: 'Density', - }), - 'euiSuperDatePicker.showDatesButtonLabel': i18n.translate( - 'core.euiSuperDatePicker.showDatesButtonLabel', - { - defaultMessage: 'Show dates', - description: 'Displayed in a button that shows date picker', - } - ), - 'euiSuperSelect.screenReaderAnnouncement': ({ optionsCount }: EuiValues) => - i18n.translate('core.euiSuperSelect.screenReaderAnnouncement', { - defaultMessage: - 'You are in a form selector of {optionsCount} items and must select a single option. Use the Up and Down keys to navigate or Escape to close.', - values: { optionsCount }, - }), - 'euiSuperSelectControl.selectAnOption': ({ selectedValue }: EuiValues) => - i18n.translate('core.euiSuperSelectControl.selectAnOption', { - defaultMessage: 'Select an option: {selectedValue}, is selected', - values: { selectedValue }, - }), - 'euiSuperUpdateButton.cannotUpdateTooltip': i18n.translate( - 'core.euiSuperUpdateButton.cannotUpdateTooltip', - { - defaultMessage: 'Cannot update', - description: "Displayed in a tooltip when updates can't happen", - } - ), - 'euiSuperUpdateButton.clickToApplyTooltip': i18n.translate( - 'core.euiSuperUpdateButton.clickToApplyTooltip', - { - defaultMessage: 'Click to apply', - description: "Displayed in a tooltip when there are changes that haven't been applied", - } - ), - 'euiSuperUpdateButton.refreshButtonLabel': i18n.translate( - 'core.euiSuperUpdateButton.refreshButtonLabel', - { - defaultMessage: 'Refresh', - description: 'Displayed in a button that refreshes based on date picked', - } - ), - 'euiSuperUpdateButton.updatingButtonLabel': i18n.translate( - 'core.euiSuperUpdateButton.updatingButtonLabel', - { - defaultMessage: 'Updating', - description: 'Displayed in a button that refreshes when updates are happening', - } - ), - 'euiSuperUpdateButton.updateButtonLabel': i18n.translate( - 'core.euiSuperUpdateButton.updateButtonLabel', - { - defaultMessage: 'Update', - description: 'Displayed in a button that updates based on date picked', - } - ), - 'euiTablePagination.rowsPerPage': i18n.translate('core.euiTablePagination.rowsPerPage', { - defaultMessage: 'Rows per page', - description: 'Displayed in a button that toggles a table pagination menu', - }), - 'euiTablePagination.rowsPerPageOption': ({ rowsPerPage }: EuiValues) => - i18n.translate('core.euiTablePagination.rowsPerPageOption', { - defaultMessage: '{rowsPerPage} rows', - description: 'Displayed in a button that toggles the number of visible rows', - values: { rowsPerPage }, - }), - 'euiTableSortMobile.sorting': i18n.translate('core.euiTableSortMobile.sorting', { - defaultMessage: 'Sorting', - description: 'Displayed in a button that toggles a table sorting menu', - }), - 'euiToast.dismissToast': i18n.translate('core.euiToast.dismissToast', { - defaultMessage: 'Dismiss toast', - }), - 'euiToast.newNotification': i18n.translate('core.euiToast.newNotification', { - defaultMessage: 'A new notification appears', - }), - 'euiToast.notification': i18n.translate('core.euiToast.notification', { - defaultMessage: 'Notification', - description: 'ARIA label on an element containing a notification', - }), - 'euiTreeView.ariaLabel': ({ nodeLabel, ariaLabel }: EuiValues) => - i18n.translate('core.euiTreeView.ariaLabel', { - defaultMessage: '{nodeLabel} child of {ariaLabel}', - values: { nodeLabel, ariaLabel }, - }), - 'euiTreeView.listNavigationInstructions': i18n.translate( - 'core.euiTreeView.listNavigationInstructions', - { - defaultMessage: 'You can quickly navigate this list using arrow keys.', - } - ), + }), + 'euiSelectable.noMatchingOptions': ({ searchValue }: EuiValues) => ( + + ), + 'euiStat.loadingText': i18n.translate('core.euiStat.loadingText', { + defaultMessage: 'Statistic is loading', + }), + 'euiStep.ariaLabel': ({ status }: EuiValues) => + i18n.translate('core.euiStep.ariaLabel', { + defaultMessage: '{stepStatus}', + values: { stepStatus: status === 'incomplete' ? 'Incomplete Step' : 'Step' }, + }), + 'euiStepHorizontal.buttonTitle': ({ step, title, disabled, isComplete }: EuiValues) => { + return i18n.translate('core.euiStepHorizontal.buttonTitle', { + defaultMessage: 'Step {step}: {title}{titleAppendix}', + values: { + step, + title, + titleAppendix: disabled ? ' is disabled' : isComplete ? ' is complete' : '', + }, + }); + }, + 'euiStepHorizontal.step': i18n.translate('core.euiStepHorizontal.step', { + defaultMessage: 'Step', + description: 'Screen reader text announcing information about a step in some process', + }), + 'euiStepNumber.hasErrors': i18n.translate('core.euiStepNumber.hasErrors', { + defaultMessage: 'has errors', + description: + 'Used as the title attribute on an image or svg icon to indicate a given process step has errors', + }), + 'euiStepNumber.hasWarnings': i18n.translate('core.euiStepNumber.hasWarnings', { + defaultMessage: 'has warnings', + description: + 'Used as the title attribute on an image or svg icon to indicate a given process step has warnings', + }), + 'euiStepNumber.isComplete': i18n.translate('core.euiStepNumber.isComplete', { + defaultMessage: 'complete', + description: + 'Used as the title attribute on an image or svg icon to indicate a given process step is complete', + }), + 'euiStyleSelector.buttonText': i18n.translate('core.euiStyleSelector.buttonText', { + defaultMessage: 'Density', + }), + 'euiSuperDatePicker.showDatesButtonLabel': i18n.translate( + 'core.euiSuperDatePicker.showDatesButtonLabel', + { + defaultMessage: 'Show dates', + description: 'Displayed in a button that shows date picker', + } + ), + 'euiSuperSelect.screenReaderAnnouncement': ({ optionsCount }: EuiValues) => + i18n.translate('core.euiSuperSelect.screenReaderAnnouncement', { + defaultMessage: + 'You are in a form selector of {optionsCount} items and must select a single option. Use the Up and Down keys to navigate or Escape to close.', + values: { optionsCount }, + }), + 'euiSuperSelectControl.selectAnOption': ({ selectedValue }: EuiValues) => + i18n.translate('core.euiSuperSelectControl.selectAnOption', { + defaultMessage: 'Select an option: {selectedValue}, is selected', + values: { selectedValue }, + }), + 'euiSuperUpdateButton.cannotUpdateTooltip': i18n.translate( + 'core.euiSuperUpdateButton.cannotUpdateTooltip', + { + defaultMessage: 'Cannot update', + description: "Displayed in a tooltip when updates can't happen", + } + ), + 'euiSuperUpdateButton.clickToApplyTooltip': i18n.translate( + 'core.euiSuperUpdateButton.clickToApplyTooltip', + { + defaultMessage: 'Click to apply', + description: "Displayed in a tooltip when there are changes that haven't been applied", + } + ), + 'euiSuperUpdateButton.refreshButtonLabel': i18n.translate( + 'core.euiSuperUpdateButton.refreshButtonLabel', + { + defaultMessage: 'Refresh', + description: 'Displayed in a button that refreshes based on date picked', + } + ), + 'euiSuperUpdateButton.updatingButtonLabel': i18n.translate( + 'core.euiSuperUpdateButton.updatingButtonLabel', + { + defaultMessage: 'Updating', + description: 'Displayed in a button that refreshes when updates are happening', + } + ), + 'euiSuperUpdateButton.updateButtonLabel': i18n.translate( + 'core.euiSuperUpdateButton.updateButtonLabel', + { + defaultMessage: 'Update', + description: 'Displayed in a button that updates based on date picked', + } + ), + 'euiTablePagination.rowsPerPage': i18n.translate('core.euiTablePagination.rowsPerPage', { + defaultMessage: 'Rows per page', + description: 'Displayed in a button that toggles a table pagination menu', + }), + 'euiTablePagination.rowsPerPageOption': ({ rowsPerPage }: EuiValues) => + i18n.translate('core.euiTablePagination.rowsPerPageOption', { + defaultMessage: '{rowsPerPage} rows', + description: 'Displayed in a button that toggles the number of visible rows', + values: { rowsPerPage }, + }), + 'euiTableSortMobile.sorting': i18n.translate('core.euiTableSortMobile.sorting', { + defaultMessage: 'Sorting', + description: 'Displayed in a button that toggles a table sorting menu', + }), + 'euiToast.dismissToast': i18n.translate('core.euiToast.dismissToast', { + defaultMessage: 'Dismiss toast', + }), + 'euiToast.newNotification': i18n.translate('core.euiToast.newNotification', { + defaultMessage: 'A new notification appears', + }), + 'euiToast.notification': i18n.translate('core.euiToast.notification', { + defaultMessage: 'Notification', + description: 'ARIA label on an element containing a notification', + }), + 'euiTreeView.ariaLabel': ({ nodeLabel, ariaLabel }: EuiValues) => + i18n.translate('core.euiTreeView.ariaLabel', { + defaultMessage: '{nodeLabel} child of {ariaLabel}', + values: { nodeLabel, ariaLabel }, + }), + 'euiTreeView.listNavigationInstructions': i18n.translate( + 'core.euiTreeView.listNavigationInstructions', + { + defaultMessage: 'You can quickly navigate this list using arrow keys.', + } + ), + }; + + return euiContextMapping; }; diff --git a/src/core/public/i18n/i18n_service.tsx b/src/core/public/i18n/i18n_service.tsx index 501d83e36b1b9..37af6127346c1 100644 --- a/src/core/public/i18n/i18n_service.tsx +++ b/src/core/public/i18n/i18n_service.tsx @@ -21,7 +21,7 @@ import React from 'react'; import { EuiContext } from '@elastic/eui'; import { I18nProvider } from '@kbn/i18n/react'; -import { euiContextMapping } from './i18n_eui_mapping'; +import { getEuiContextMapping } from './i18n_eui_mapping'; /** * Service that is responsible for i18n capabilities. @@ -37,6 +37,8 @@ export class I18nService { * @internal */ public getContext(): I18nStart { + const euiContextMapping = getEuiContextMapping(); + const mapping = { ...euiContextMapping, }; diff --git a/src/core/public/injected_metadata/injected_metadata_service.ts b/src/core/public/injected_metadata/injected_metadata_service.ts index 5b51bc823d166..bd8c9e91f15a2 100644 --- a/src/core/public/injected_metadata/injected_metadata_service.ts +++ b/src/core/public/injected_metadata/injected_metadata_service.ts @@ -58,19 +58,6 @@ export interface InjectedMetadataParams { uiPlugins: InjectedPluginMetadata[]; anonymousStatusPage: boolean; legacyMetadata: { - app: { - id: string; - title: string; - }; - bundleId: string; - version: string; - branch: string; - buildNum: number; - buildSha: string; - basePath: string; - serverName: string; - devMode: boolean; - category?: AppCategory; uiSettings: { defaults: Record; user?: Record; @@ -167,18 +154,6 @@ export interface InjectedMetadataSetup { getPlugins: () => InjectedPluginMetadata[]; getAnonymousStatusPage: () => boolean; getLegacyMetadata: () => { - app: { - id: string; - title: string; - }; - bundleId: string; - version: string; - branch: string; - buildNum: number; - buildSha: string; - basePath: string; - serverName: string; - devMode: boolean; uiSettings: { defaults: Record; user?: Record | undefined; diff --git a/src/core/public/kbn_bootstrap.test.mocks.ts b/src/core/public/kbn_bootstrap.test.mocks.ts new file mode 100644 index 0000000000000..30f292280a135 --- /dev/null +++ b/src/core/public/kbn_bootstrap.test.mocks.ts @@ -0,0 +1,50 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { applicationServiceMock } from './application/application_service.mock'; +import { fatalErrorsServiceMock } from './fatal_errors/fatal_errors_service.mock'; +export const fatalErrorMock = fatalErrorsServiceMock.createSetupContract(); +export const coreSystemMock = { + setup: jest.fn().mockResolvedValue({ + fatalErrors: fatalErrorMock, + }), + start: jest.fn().mockResolvedValue({ + application: applicationServiceMock.createInternalStartContract(), + }), +}; +jest.doMock('./core_system', () => ({ + CoreSystem: jest.fn().mockImplementation(() => coreSystemMock), +})); + +export const apmSystem = { + setup: jest.fn().mockResolvedValue(undefined), + start: jest.fn().mockResolvedValue(undefined), +}; +export const ApmSystemConstructor = jest.fn().mockImplementation(() => apmSystem); +jest.doMock('./apm_system', () => ({ + ApmSystem: ApmSystemConstructor, +})); + +export const i18nLoad = jest.fn().mockResolvedValue(undefined); +jest.doMock('@kbn/i18n', () => ({ + i18n: { + ...jest.requireActual('@kbn/i18n').i18n, + load: i18nLoad, + }, +})); diff --git a/src/core/public/kbn_bootstrap.test.ts b/src/core/public/kbn_bootstrap.test.ts new file mode 100644 index 0000000000000..9cd16dd6ab9df --- /dev/null +++ b/src/core/public/kbn_bootstrap.test.ts @@ -0,0 +1,54 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +import { apmSystem, fatalErrorMock, i18nLoad } from './kbn_bootstrap.test.mocks'; +import { __kbnBootstrap__ } from './'; + +describe('kbn_bootstrap', () => { + beforeAll(() => { + const metadata = { + i18n: { translationsUrl: 'http://localhost' }, + vars: { apmConfig: null }, + }; + // eslint-disable-next-line no-unsanitized/property + document.body.innerHTML = ` +`; + }); + + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('does not report a fatal error if apm load fails', async () => { + apmSystem.setup.mockRejectedValueOnce(new Error('reason')); + const consoleSpy = jest.spyOn(console, 'warn').mockImplementationOnce(() => undefined); + + await __kbnBootstrap__(); + + expect(fatalErrorMock.add).toHaveBeenCalledTimes(0); + expect(consoleSpy).toHaveBeenCalledTimes(1); + }); + + it('reports a fatal error if i18n load fails', async () => { + i18nLoad.mockRejectedValueOnce(new Error('reason')); + + await __kbnBootstrap__(); + + expect(fatalErrorMock.add).toHaveBeenCalledTimes(1); + }); +}); diff --git a/src/core/public/kbn_bootstrap.ts b/src/core/public/kbn_bootstrap.ts index a108b5aaa47ec..a083196004cf4 100644 --- a/src/core/public/kbn_bootstrap.ts +++ b/src/core/public/kbn_bootstrap.ts @@ -17,70 +17,38 @@ * under the License. */ -/** - * This is the entry point used to boot the frontend when serving a application - * that lives in the Kibana Platform. - * - * Any changes to this file should be kept in sync with - * src/legacy/ui/ui_bundles/app_entry_template.js - */ - import { i18n } from '@kbn/i18n'; import { CoreSystem } from './core_system'; +import { ApmSystem } from './apm_system'; /** @internal */ -export function __kbnBootstrap__() { +export async function __kbnBootstrap__() { const injectedMetadata = JSON.parse( document.querySelector('kbn-injected-metadata')!.getAttribute('data')! ); - /** - * `apmConfig` would be populated with relavant APM RUM agent - * configuration if server is started with `ELASTIC_APM_ACTIVE=true` - */ - const apmConfig = injectedMetadata.vars.apmConfig; - const APM_ENABLED = process.env.IS_KIBANA_DISTRIBUTABLE !== 'true' && apmConfig != null; - - if (APM_ENABLED) { - // eslint-disable-next-line @typescript-eslint/no-var-requires - const { init, apm } = require('@elastic/apm-rum'); - if (apmConfig.globalLabels) { - apm.addLabels(apmConfig.globalLabels); - } - init(apmConfig); + let i18nError: Error | undefined; + const apmSystem = new ApmSystem(injectedMetadata.vars.apmConfig); + + await Promise.all([ + // eslint-disable-next-line no-console + apmSystem.setup().catch(console.warn), + i18n.load(injectedMetadata.i18n.translationsUrl).catch((error) => { + i18nError = error; + }), + ]); + + const coreSystem = new CoreSystem({ + injectedMetadata, + rootDomElement: document.body, + browserSupportsCsp: !(window as any).__kbnCspNotEnforced__, + }); + + const setup = await coreSystem.setup(); + if (i18nError && setup) { + setup.fatalErrors.add(i18nError); } - i18n - .load(injectedMetadata.i18n.translationsUrl) - .catch((e) => e) - .then(async (i18nError) => { - const coreSystem = new CoreSystem({ - injectedMetadata, - rootDomElement: document.body, - browserSupportsCsp: !(window as any).__kbnCspNotEnforced__, - }); - - const setup = await coreSystem.setup(); - if (i18nError && setup) { - setup.fatalErrors.add(i18nError); - } - - const start = await coreSystem.start(); - - if (APM_ENABLED && start) { - /** - * Register listeners for navigation changes and capture them as - * route-change transactions after Kibana app is bootstrapped - */ - start.application.currentAppId$.subscribe((appId) => { - const apmInstance = (window as any).elasticApm; - if (appId && apmInstance && typeof apmInstance.startTransaction === 'function') { - apmInstance.startTransaction(`/app/${appId}`, 'route-change', { - managed: true, - canReuse: true, - }); - } - }); - } - }); + const start = await coreSystem.start(); + await apmSystem.start(start); } diff --git a/src/core/public/notifications/toasts/__snapshots__/global_toast_list.test.tsx.snap b/src/core/public/notifications/toasts/__snapshots__/global_toast_list.test.tsx.snap index 2b3bdb65708a3..0ed32a1dbccb2 100644 --- a/src/core/public/notifications/toasts/__snapshots__/global_toast_list.test.tsx.snap +++ b/src/core/public/notifications/toasts/__snapshots__/global_toast_list.test.tsx.snap @@ -2,6 +2,7 @@ exports[`renders matching snapshot 1`] = ` { public render() { return ( this.props.dismissToast(id)} diff --git a/src/core/public/overlays/banners/banners_list.test.tsx b/src/core/public/overlays/banners/banners_list.test.tsx index dbee20790fa94..3850a88699d90 100644 --- a/src/core/public/overlays/banners/banners_list.test.tsx +++ b/src/core/public/overlays/banners/banners_list.test.tsx @@ -43,7 +43,7 @@ describe('BannersList', () => { ]); expect(mount().html()).toMatchInlineSnapshot( - `"

Hello!

"` + `"

Hello!

"` ); }); @@ -85,7 +85,7 @@ describe('BannersList', () => { // Two new banners should be rendered expect(component.html()).toMatchInlineSnapshot( - `"

First Banner!

Second banner!

"` + `"

First Banner!

Second banner!

"` ); // Original banner should be unmounted expect(unmount).toHaveBeenCalled(); diff --git a/src/core/public/overlays/banners/banners_list.tsx b/src/core/public/overlays/banners/banners_list.tsx index 6503af985f9c8..30acf6abff70b 100644 --- a/src/core/public/overlays/banners/banners_list.tsx +++ b/src/core/public/overlays/banners/banners_list.tsx @@ -59,6 +59,11 @@ const BannerItem: React.FunctionComponent<{ banner: OverlayBanner }> = ({ banner useEffect(() => banner.mount(element.current!), [banner]); // Only unmount / remount if banner object changed. return ( -
+
); }; diff --git a/src/core/public/overlays/banners/user_banner_service.tsx b/src/core/public/overlays/banners/user_banner_service.tsx index 643d95a1e3bb4..2b93c3e4b6c21 100644 --- a/src/core/public/overlays/banners/user_banner_service.tsx +++ b/src/core/public/overlays/banners/user_banner_service.tsx @@ -19,12 +19,11 @@ import React, { Fragment } from 'react'; import ReactDOM from 'react-dom'; -import ReactMarkdown from 'react-markdown'; import { filter } from 'rxjs/operators'; import { Subscription } from 'rxjs'; import { FormattedMessage } from '@kbn/i18n/react'; -import { EuiCallOut, EuiButton } from '@elastic/eui'; +import { EuiCallOut, EuiButton, EuiLoadingSpinner } from '@elastic/eui'; import { I18nStart } from '../../i18n'; import { IUiSettingsClient } from '../../ui_settings'; @@ -36,6 +35,8 @@ interface StartDeps { uiSettings: IUiSettingsClient; } +const ReactMarkdownLazy = React.lazy(() => import('react-markdown')); + /** * Sets up the custom banner that can be specified in advanced settings. * @internal @@ -75,7 +76,15 @@ export class UserBannerService { } iconType="help" > - {content.trim()} + + +
+ } + > + + banners.remove(id!)}> ; // @public (undocumented) export interface App { @@ -539,6 +539,7 @@ export interface DocLinksStart { readonly gettingStarted: string; }; readonly query: { + readonly eql: string; readonly luceneQuerySyntax: string; readonly queryDsl: string; readonly kueryQuerySyntax: string; @@ -1029,8 +1030,9 @@ export class SavedObjectsClient { }>) => Promise>; bulkUpdate(objects?: SavedObjectsBulkUpdateObject[]): Promise>; create: (type: string, attributes: T, options?: SavedObjectsCreateOptions) => Promise>; + // Warning: (ae-forgotten-export) The symbol "SavedObjectsDeleteOptions" needs to be exported by the entry point index.d.ts // Warning: (ae-forgotten-export) The symbol "SavedObjectsClientContract" needs to be exported by the entry point index.d.ts - delete: (type: string, id: string) => ReturnType; + delete: (type: string, id: string, options?: SavedObjectsDeleteOptions | undefined) => ReturnType; // Warning: (ae-forgotten-export) The symbol "SavedObjectsFindOptions" needs to be exported by the entry point index.d.ts find: (options: SavedObjectsFindOptions_2) => Promise>; get: (type: string, id: string) => Promise>; @@ -1079,6 +1081,7 @@ export interface SavedObjectsFindOptions { sortOrder?: string; // (undocumented) type: string | string[]; + typeToNamespacesMap?: Map; } // @public diff --git a/src/core/public/saved_objects/saved_objects_client.test.ts b/src/core/public/saved_objects/saved_objects_client.test.ts index 20824af38af0f..fab651379ea6a 100644 --- a/src/core/public/saved_objects/saved_objects_client.test.ts +++ b/src/core/public/saved_objects/saved_objects_client.test.ts @@ -132,7 +132,9 @@ describe('SavedObjectsClient', () => { Object { "body": undefined, "method": "DELETE", - "query": undefined, + "query": Object { + "force": false, + }, }, ] `); diff --git a/src/core/public/saved_objects/saved_objects_client.ts b/src/core/public/saved_objects/saved_objects_client.ts index 5a8949ca2f55f..beed3e6fe0a18 100644 --- a/src/core/public/saved_objects/saved_objects_client.ts +++ b/src/core/public/saved_objects/saved_objects_client.ts @@ -34,7 +34,7 @@ import { HttpFetchOptions, HttpSetup } from '../http'; type SavedObjectsFindOptions = Omit< SavedObjectFindOptionsServer, - 'namespace' | 'sortOrder' | 'rootSearchFields' + 'sortOrder' | 'rootSearchFields' | 'typeToNamespacesMap' >; type PromiseType> = T extends Promise ? U : never; @@ -96,6 +96,12 @@ export interface SavedObjectsBatchResponse { savedObjects: Array>; } +/** @public */ +export interface SavedObjectsDeleteOptions { + /** Force deletion of an object that exists in multiple namespaces */ + force?: boolean; +} + /** * Return type of the Saved Objects `find()` method. * @@ -261,12 +267,20 @@ export class SavedObjectsClient { * @param id * @returns */ - public delete = (type: string, id: string): ReturnType => { + public delete = ( + type: string, + id: string, + options?: SavedObjectsDeleteOptions + ): ReturnType => { if (!type || !id) { return Promise.reject(new Error('requires type and id')); } - return this.savedObjectsFetch(this.getPath([type, id]), { method: 'DELETE' }); + const query = { + force: !!options?.force, + }; + + return this.savedObjectsFetch(this.getPath([type, id]), { method: 'DELETE', query }); }; /** diff --git a/src/core/server/capabilities/capabilities_service.mock.ts b/src/core/server/capabilities/capabilities_service.mock.ts index 7d134f9592dc7..72824693705d9 100644 --- a/src/core/server/capabilities/capabilities_service.mock.ts +++ b/src/core/server/capabilities/capabilities_service.mock.ts @@ -18,6 +18,7 @@ */ import type { PublicMethodsOf } from '@kbn/utility-types'; import { CapabilitiesService, CapabilitiesSetup, CapabilitiesStart } from './capabilities_service'; +import { Capabilities } from './types'; const createSetupContractMock = () => { const setupContract: jest.Mocked = { @@ -34,6 +35,14 @@ const createStartContractMock = () => { return setupContract; }; +const createCapabilitiesMock = (): Capabilities => { + return { + navLinks: {}, + management: {}, + catalogue: {}, + }; +}; + type CapabilitiesServiceContract = PublicMethodsOf; const createMock = () => { const mocked: jest.Mocked = { @@ -47,4 +56,5 @@ export const capabilitiesServiceMock = { create: createMock, createSetupContract: createSetupContractMock, createStartContract: createStartContractMock, + createCapabilities: createCapabilitiesMock, }; diff --git a/src/core/server/config/deprecation/core_deprecations.ts b/src/core/server/config/deprecation/core_deprecations.ts index 2701edcf44e03..6c85cfbed8e82 100644 --- a/src/core/server/config/deprecation/core_deprecations.ts +++ b/src/core/server/config/deprecation/core_deprecations.ts @@ -136,6 +136,8 @@ export const coreDeprecationProvider: ConfigDeprecationProvider = ({ rename, unu unusedFromRoot('optimize.workers'), unusedFromRoot('optimize.profile'), unusedFromRoot('optimize.validateSyntaxOfNodeModules'), + unusedFromRoot('elasticsearch.preserveHost'), + unusedFromRoot('elasticsearch.startupTimeout'), rename('cpu.cgroup.path.override', 'ops.cGroupOverrides.cpuPath'), rename('cpuacct.cgroup.path.override', 'ops.cGroupOverrides.cpuAcctPath'), configPathDeprecation, diff --git a/src/core/server/core_route_handler_context.test.ts b/src/core/server/core_route_handler_context.test.ts new file mode 100644 index 0000000000000..563e337e6c7e0 --- /dev/null +++ b/src/core/server/core_route_handler_context.test.ts @@ -0,0 +1,239 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +import { CoreRouteHandlerContext } from './core_route_handler_context'; +import { coreMock, httpServerMock } from './mocks'; + +describe('#auditor', () => { + test('returns the results of coreStart.audiTrail.asScoped', () => { + const request = httpServerMock.createKibanaRequest(); + const coreStart = coreMock.createInternalStart(); + const context = new CoreRouteHandlerContext(coreStart, request); + + const auditor = context.auditor; + expect(auditor).toBe(coreStart.auditTrail.asScoped.mock.results[0].value); + }); + + test('lazily created', () => { + const request = httpServerMock.createKibanaRequest(); + const coreStart = coreMock.createInternalStart(); + const context = new CoreRouteHandlerContext(coreStart, request); + + expect(coreStart.auditTrail.asScoped).not.toHaveBeenCalled(); + const auditor = context.auditor; + expect(coreStart.auditTrail.asScoped).toHaveBeenCalled(); + expect(auditor).toBeDefined(); + }); + + test('only creates one instance', () => { + const request = httpServerMock.createKibanaRequest(); + const coreStart = coreMock.createInternalStart(); + const context = new CoreRouteHandlerContext(coreStart, request); + + const auditor1 = context.auditor; + const auditor2 = context.auditor; + expect(coreStart.auditTrail.asScoped.mock.calls.length).toBe(1); + const mockResult = coreStart.auditTrail.asScoped.mock.results[0].value; + expect(auditor1).toBe(mockResult); + expect(auditor2).toBe(mockResult); + }); +}); + +describe('#elasticsearch', () => { + describe('#client', () => { + test('returns the results of coreStart.elasticsearch.client.asScoped', () => { + const request = httpServerMock.createKibanaRequest(); + const coreStart = coreMock.createInternalStart(); + const context = new CoreRouteHandlerContext(coreStart, request); + + const client = context.elasticsearch.client; + expect(client).toBe(coreStart.elasticsearch.client.asScoped.mock.results[0].value); + }); + + test('lazily created', () => { + const request = httpServerMock.createKibanaRequest(); + const coreStart = coreMock.createInternalStart(); + const context = new CoreRouteHandlerContext(coreStart, request); + + expect(coreStart.elasticsearch.client.asScoped).not.toHaveBeenCalled(); + const client = context.elasticsearch.client; + expect(coreStart.elasticsearch.client.asScoped).toHaveBeenCalled(); + expect(client).toBeDefined(); + }); + + test('only creates one instance', () => { + const request = httpServerMock.createKibanaRequest(); + const coreStart = coreMock.createInternalStart(); + const context = new CoreRouteHandlerContext(coreStart, request); + + const client1 = context.elasticsearch.client; + const client2 = context.elasticsearch.client; + expect(coreStart.elasticsearch.client.asScoped.mock.calls.length).toBe(1); + const mockResult = coreStart.elasticsearch.client.asScoped.mock.results[0].value; + expect(client1).toBe(mockResult); + expect(client2).toBe(mockResult); + }); + }); + + describe('#legacy', () => { + describe('#client', () => { + test('returns the results of coreStart.elasticsearch.legacy.client.asScoped', () => { + const request = httpServerMock.createKibanaRequest(); + const coreStart = coreMock.createInternalStart(); + const context = new CoreRouteHandlerContext(coreStart, request); + + const client = context.elasticsearch.legacy.client; + expect(client).toBe(coreStart.elasticsearch.legacy.client.asScoped.mock.results[0].value); + }); + + test('lazily created', () => { + const request = httpServerMock.createKibanaRequest(); + const coreStart = coreMock.createInternalStart(); + const context = new CoreRouteHandlerContext(coreStart, request); + + expect(coreStart.elasticsearch.legacy.client.asScoped).not.toHaveBeenCalled(); + const client = context.elasticsearch.legacy.client; + expect(coreStart.elasticsearch.legacy.client.asScoped).toHaveBeenCalled(); + expect(client).toBeDefined(); + }); + + test('only creates one instance', () => { + const request = httpServerMock.createKibanaRequest(); + const coreStart = coreMock.createInternalStart(); + const context = new CoreRouteHandlerContext(coreStart, request); + + const client1 = context.elasticsearch.legacy.client; + const client2 = context.elasticsearch.legacy.client; + expect(coreStart.elasticsearch.legacy.client.asScoped.mock.calls.length).toBe(1); + const mockResult = coreStart.elasticsearch.legacy.client.asScoped.mock.results[0].value; + expect(client1).toBe(mockResult); + expect(client2).toBe(mockResult); + }); + }); + }); +}); + +describe('#savedObjects', () => { + describe('#client', () => { + test('returns the results of coreStart.savedObjects.getScopedClient', () => { + const request = httpServerMock.createKibanaRequest(); + const coreStart = coreMock.createInternalStart(); + const context = new CoreRouteHandlerContext(coreStart, request); + + const client = context.savedObjects.client; + expect(client).toBe(coreStart.savedObjects.getScopedClient.mock.results[0].value); + }); + + test('lazily created', () => { + const request = httpServerMock.createKibanaRequest(); + const coreStart = coreMock.createInternalStart(); + const context = new CoreRouteHandlerContext(coreStart, request); + + const savedObjects = context.savedObjects; + expect(coreStart.savedObjects.getScopedClient).not.toHaveBeenCalled(); + const client = savedObjects.client; + expect(coreStart.savedObjects.getScopedClient).toHaveBeenCalled(); + expect(client).toBeDefined(); + }); + + test('only creates one instance', () => { + const request = httpServerMock.createKibanaRequest(); + const coreStart = coreMock.createInternalStart(); + const context = new CoreRouteHandlerContext(coreStart, request); + + const client1 = context.savedObjects.client; + const client2 = context.savedObjects.client; + expect(coreStart.savedObjects.getScopedClient.mock.calls.length).toBe(1); + const mockResult = coreStart.savedObjects.getScopedClient.mock.results[0].value; + expect(client1).toBe(mockResult); + expect(client2).toBe(mockResult); + }); + }); + + describe('#typeRegistry', () => { + test('returns the results of coreStart.savedObjects.getTypeRegistry', () => { + const request = httpServerMock.createKibanaRequest(); + const coreStart = coreMock.createInternalStart(); + const context = new CoreRouteHandlerContext(coreStart, request); + + const typeRegistry = context.savedObjects.typeRegistry; + expect(typeRegistry).toBe(coreStart.savedObjects.getTypeRegistry.mock.results[0].value); + }); + + test('lazily created', () => { + const request = httpServerMock.createKibanaRequest(); + const coreStart = coreMock.createInternalStart(); + const context = new CoreRouteHandlerContext(coreStart, request); + + expect(coreStart.savedObjects.getTypeRegistry).not.toHaveBeenCalled(); + const typeRegistry = context.savedObjects.typeRegistry; + expect(coreStart.savedObjects.getTypeRegistry).toHaveBeenCalled(); + expect(typeRegistry).toBeDefined(); + }); + + test('only creates one instance', () => { + const request = httpServerMock.createKibanaRequest(); + const coreStart = coreMock.createInternalStart(); + const context = new CoreRouteHandlerContext(coreStart, request); + + const typeRegistry1 = context.savedObjects.typeRegistry; + const typeRegistry2 = context.savedObjects.typeRegistry; + expect(coreStart.savedObjects.getTypeRegistry.mock.calls.length).toBe(1); + const mockResult = coreStart.savedObjects.getTypeRegistry.mock.results[0].value; + expect(typeRegistry1).toBe(mockResult); + expect(typeRegistry2).toBe(mockResult); + }); + }); +}); + +describe('#uiSettings', () => { + describe('#client', () => { + test('returns the results of coreStart.uiSettings.asScopedToClient', () => { + const request = httpServerMock.createKibanaRequest(); + const coreStart = coreMock.createInternalStart(); + const context = new CoreRouteHandlerContext(coreStart, request); + + const client = context.uiSettings.client; + expect(client).toBe(coreStart.uiSettings.asScopedToClient.mock.results[0].value); + }); + + test('lazily created', () => { + const request = httpServerMock.createKibanaRequest(); + const coreStart = coreMock.createInternalStart(); + const context = new CoreRouteHandlerContext(coreStart, request); + + expect(coreStart.uiSettings.asScopedToClient).not.toHaveBeenCalled(); + const client = context.uiSettings.client; + expect(coreStart.uiSettings.asScopedToClient).toHaveBeenCalled(); + expect(client).toBeDefined(); + }); + + test('only creates one instance', () => { + const request = httpServerMock.createKibanaRequest(); + const coreStart = coreMock.createInternalStart(); + const context = new CoreRouteHandlerContext(coreStart, request); + + const client1 = context.uiSettings.client; + const client2 = context.uiSettings.client; + expect(coreStart.uiSettings.asScopedToClient.mock.calls.length).toBe(1); + const mockResult = coreStart.uiSettings.asScopedToClient.mock.results[0].value; + expect(client1).toBe(mockResult); + expect(client2).toBe(mockResult); + }); + }); +}); diff --git a/src/core/server/core_route_handler_context.ts b/src/core/server/core_route_handler_context.ts new file mode 100644 index 0000000000000..8a182a523f52c --- /dev/null +++ b/src/core/server/core_route_handler_context.ts @@ -0,0 +1,132 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +// eslint-disable-next-line max-classes-per-file +import { InternalCoreStart } from './internal_types'; +import { KibanaRequest } from './http/router'; +import { SavedObjectsClientContract } from './saved_objects/types'; +import { InternalSavedObjectsServiceStart, ISavedObjectTypeRegistry } from './saved_objects'; +import { + InternalElasticsearchServiceStart, + IScopedClusterClient, + LegacyScopedClusterClient, +} from './elasticsearch'; +import { Auditor } from './audit_trail'; +import { InternalUiSettingsServiceStart, IUiSettingsClient } from './ui_settings'; + +class CoreElasticsearchRouteHandlerContext { + #client?: IScopedClusterClient; + #legacy?: { + client: Pick; + }; + + constructor( + private readonly elasticsearchStart: InternalElasticsearchServiceStart, + private readonly request: KibanaRequest + ) {} + + public get client() { + if (this.#client == null) { + this.#client = this.elasticsearchStart.client.asScoped(this.request); + } + return this.#client; + } + + public get legacy() { + if (this.#legacy == null) { + this.#legacy = { + client: this.elasticsearchStart.legacy.client.asScoped(this.request), + }; + } + return this.#legacy; + } +} + +class CoreSavedObjectsRouteHandlerContext { + constructor( + private readonly savedObjectsStart: InternalSavedObjectsServiceStart, + private readonly request: KibanaRequest + ) {} + #scopedSavedObjectsClient?: SavedObjectsClientContract; + #typeRegistry?: ISavedObjectTypeRegistry; + + public get client() { + if (this.#scopedSavedObjectsClient == null) { + this.#scopedSavedObjectsClient = this.savedObjectsStart.getScopedClient(this.request); + } + return this.#scopedSavedObjectsClient; + } + + public get typeRegistry() { + if (this.#typeRegistry == null) { + this.#typeRegistry = this.savedObjectsStart.getTypeRegistry(); + } + return this.#typeRegistry; + } +} + +class CoreUiSettingsRouteHandlerContext { + #client?: IUiSettingsClient; + constructor( + private readonly uiSettingsStart: InternalUiSettingsServiceStart, + private readonly savedObjectsRouterHandlerContext: CoreSavedObjectsRouteHandlerContext + ) {} + + public get client() { + if (this.#client == null) { + this.#client = this.uiSettingsStart.asScopedToClient( + this.savedObjectsRouterHandlerContext.client + ); + } + return this.#client; + } +} + +export class CoreRouteHandlerContext { + #auditor?: Auditor; + + readonly elasticsearch: CoreElasticsearchRouteHandlerContext; + readonly savedObjects: CoreSavedObjectsRouteHandlerContext; + readonly uiSettings: CoreUiSettingsRouteHandlerContext; + + constructor( + private readonly coreStart: InternalCoreStart, + private readonly request: KibanaRequest + ) { + this.elasticsearch = new CoreElasticsearchRouteHandlerContext( + this.coreStart.elasticsearch, + this.request + ); + this.savedObjects = new CoreSavedObjectsRouteHandlerContext( + this.coreStart.savedObjects, + this.request + ); + this.uiSettings = new CoreUiSettingsRouteHandlerContext( + this.coreStart.uiSettings, + this.savedObjects + ); + } + + public get auditor() { + if (this.#auditor == null) { + this.#auditor = this.coreStart.auditTrail.asScoped(this.request); + } + return this.#auditor; + } +} diff --git a/src/core/server/core_usage_data/core_usage_data_service.mock.ts b/src/core/server/core_usage_data/core_usage_data_service.mock.ts new file mode 100644 index 0000000000000..c443ce72f5ed7 --- /dev/null +++ b/src/core/server/core_usage_data/core_usage_data_service.mock.ts @@ -0,0 +1,153 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { PublicMethodsOf } from '@kbn/utility-types'; +import { BehaviorSubject } from 'rxjs'; +import { CoreUsageDataService } from './core_usage_data_service'; +import { CoreUsageData, CoreUsageDataStart } from './types'; + +const createStartContractMock = () => { + const startContract: jest.Mocked = { + getCoreUsageData: jest.fn().mockResolvedValue( + new BehaviorSubject({ + config: { + elasticsearch: { + apiVersion: 'master', + customHeadersConfigured: false, + healthCheckDelayMs: 2500, + logQueries: false, + numberOfHostsConfigured: 1, + pingTimeoutMs: 30000, + requestHeadersWhitelistConfigured: false, + requestTimeoutMs: 30000, + shardTimeoutMs: 30000, + sniffIntervalMs: -1, + sniffOnConnectionFault: false, + sniffOnStart: false, + ssl: { + alwaysPresentCertificate: false, + certificateAuthoritiesConfigured: false, + certificateConfigured: false, + keyConfigured: false, + verificationMode: 'full', + keystoreConfigured: false, + truststoreConfigured: false, + }, + }, + http: { + basePathConfigured: false, + compression: { + enabled: true, + referrerWhitelistConfigured: false, + }, + keepaliveTimeout: 120000, + maxPayloadInBytes: 1048576, + requestId: { + allowFromAnyIp: false, + ipAllowlistConfigured: false, + }, + rewriteBasePath: false, + socketTimeout: 120000, + ssl: { + certificateAuthoritiesConfigured: false, + certificateConfigured: false, + cipherSuites: [ + 'ECDHE-RSA-AES128-GCM-SHA256', + 'ECDHE-ECDSA-AES128-GCM-SHA256', + 'ECDHE-RSA-AES256-GCM-SHA384', + 'ECDHE-ECDSA-AES256-GCM-SHA384', + 'DHE-RSA-AES128-GCM-SHA256', + 'ECDHE-RSA-AES128-SHA256', + 'DHE-RSA-AES128-SHA256', + 'ECDHE-RSA-AES256-SHA384', + 'DHE-RSA-AES256-SHA384', + 'ECDHE-RSA-AES256-SHA256', + 'DHE-RSA-AES256-SHA256', + 'HIGH', + '!aNULL', + '!eNULL', + '!EXPORT', + '!DES', + '!RC4', + '!MD5', + '!PSK', + '!SRP', + '!CAMELLIA', + ], + clientAuthentication: 'none', + keyConfigured: false, + keystoreConfigured: false, + redirectHttpFromPortConfigured: false, + supportedProtocols: ['TLSv1.1', 'TLSv1.2'], + truststoreConfigured: false, + }, + xsrf: { + disableProtection: false, + whitelistConfigured: false, + }, + }, + logging: { + appendersTypesUsed: [], + loggersConfiguredCount: 0, + }, + savedObjects: { + maxImportExportSizeBytes: 10000, + maxImportPayloadBytes: 10485760, + }, + }, + environment: { + memory: { + heapSizeLimit: 1, + heapTotalBytes: 1, + heapUsedBytes: 1, + }, + }, + services: { + savedObjects: { + indices: [ + { + docsCount: 1, + docsDeleted: 1, + alias: 'test_index', + primaryStoreSizeBytes: 1, + storeSizeBytes: 1, + }, + ], + }, + }, + }) + ), + }; + + return startContract; +}; + +const createMock = () => { + const mocked: jest.Mocked> = { + setup: jest.fn(), + start: jest.fn().mockReturnValue(createStartContractMock()), + stop: jest.fn(), + }; + return mocked; +}; + +export const coreUsageDataServiceMock = { + create: createMock, + createStartContract: createStartContractMock, +}; diff --git a/src/core/server/core_usage_data/core_usage_data_service.test.ts b/src/core/server/core_usage_data/core_usage_data_service.test.ts new file mode 100644 index 0000000000000..a664f6514e9c8 --- /dev/null +++ b/src/core/server/core_usage_data/core_usage_data_service.test.ts @@ -0,0 +1,259 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { BehaviorSubject, Observable } from 'rxjs'; +import { HotObservable } from 'rxjs/internal/testing/HotObservable'; +import { TestScheduler } from 'rxjs/testing'; + +import { configServiceMock } from '../config/mocks'; + +import { mockCoreContext } from '../core_context.mock'; +import { config as RawElasticsearchConfig } from '../elasticsearch/elasticsearch_config'; +import { config as RawHttpConfig } from '../http/http_config'; +import { config as RawLoggingConfig } from '../logging/logging_config'; +import { config as RawKibanaConfig } from '../kibana_config'; +import { savedObjectsConfig as RawSavedObjectsConfig } from '../saved_objects/saved_objects_config'; +import { metricsServiceMock } from '../metrics/metrics_service.mock'; +import { savedObjectsServiceMock } from '../saved_objects/saved_objects_service.mock'; + +import { CoreUsageDataService } from './core_usage_data_service'; +import { elasticsearchServiceMock } from '../elasticsearch/elasticsearch_service.mock'; + +describe('CoreUsageDataService', () => { + const getTestScheduler = () => + new TestScheduler((actual, expected) => { + expect(actual).toEqual(expected); + }); + + let service: CoreUsageDataService; + const configService = configServiceMock.create(); + configService.atPath.mockImplementation((path) => { + if (path === 'elasticsearch') { + return new BehaviorSubject(RawElasticsearchConfig.schema.validate({})); + } else if (path === 'server') { + return new BehaviorSubject(RawHttpConfig.schema.validate({})); + } else if (path === 'logging') { + return new BehaviorSubject(RawLoggingConfig.schema.validate({})); + } else if (path === 'savedObjects') { + return new BehaviorSubject(RawSavedObjectsConfig.schema.validate({})); + } else if (path === 'kibana') { + return new BehaviorSubject(RawKibanaConfig.schema.validate({})); + } + return new BehaviorSubject({}); + }); + const coreContext = mockCoreContext.create({ configService }); + + beforeEach(() => { + service = new CoreUsageDataService(coreContext); + }); + + describe('start', () => { + describe('getCoreUsageData', () => { + it('returns core metrics for default config', () => { + const metrics = metricsServiceMock.createInternalSetupContract(); + service.setup({ metrics }); + const elasticsearch = elasticsearchServiceMock.createStart(); + elasticsearch.client.asInternalUser.cat.indices.mockResolvedValueOnce({ + body: [ + { + name: '.kibana_task_manager_1', + 'docs.count': 10, + 'docs.deleted': 10, + 'store.size': 1000, + 'pri.store.size': 2000, + }, + ], + } as any); + elasticsearch.client.asInternalUser.cat.indices.mockResolvedValueOnce({ + body: [ + { + name: '.kibana_1', + 'docs.count': 20, + 'docs.deleted': 20, + 'store.size': 2000, + 'pri.store.size': 4000, + }, + ], + } as any); + const typeRegistry = savedObjectsServiceMock.createTypeRegistryMock(); + typeRegistry.getAllTypes.mockReturnValue([ + { name: 'type 1', indexPattern: '.kibana' }, + { name: 'type 2', indexPattern: '.kibana_task_manager' }, + ] as any); + + const { getCoreUsageData } = service.start({ + savedObjects: savedObjectsServiceMock.createInternalStartContract(typeRegistry), + elasticsearch, + }); + expect(getCoreUsageData()).resolves.toMatchInlineSnapshot(` + Object { + "config": Object { + "elasticsearch": Object { + "apiVersion": "master", + "customHeadersConfigured": false, + "healthCheckDelayMs": 2500, + "logQueries": false, + "numberOfHostsConfigured": 1, + "pingTimeoutMs": 30000, + "requestHeadersWhitelistConfigured": false, + "requestTimeoutMs": 30000, + "shardTimeoutMs": 30000, + "sniffIntervalMs": -1, + "sniffOnConnectionFault": false, + "sniffOnStart": false, + "ssl": Object { + "alwaysPresentCertificate": false, + "certificateAuthoritiesConfigured": false, + "certificateConfigured": false, + "keyConfigured": false, + "keystoreConfigured": false, + "truststoreConfigured": false, + "verificationMode": "full", + }, + }, + "http": Object { + "basePathConfigured": false, + "compression": Object { + "enabled": true, + "referrerWhitelistConfigured": false, + }, + "keepaliveTimeout": 120000, + "maxPayloadInBytes": 1048576, + "requestId": Object { + "allowFromAnyIp": false, + "ipAllowlistConfigured": false, + }, + "rewriteBasePath": false, + "socketTimeout": 120000, + "ssl": Object { + "certificateAuthoritiesConfigured": false, + "certificateConfigured": false, + "cipherSuites": Array [ + "ECDHE-RSA-AES128-GCM-SHA256", + "ECDHE-ECDSA-AES128-GCM-SHA256", + "ECDHE-RSA-AES256-GCM-SHA384", + "ECDHE-ECDSA-AES256-GCM-SHA384", + "DHE-RSA-AES128-GCM-SHA256", + "ECDHE-RSA-AES128-SHA256", + "DHE-RSA-AES128-SHA256", + "ECDHE-RSA-AES256-SHA384", + "DHE-RSA-AES256-SHA384", + "ECDHE-RSA-AES256-SHA256", + "DHE-RSA-AES256-SHA256", + "HIGH", + "!aNULL", + "!eNULL", + "!EXPORT", + "!DES", + "!RC4", + "!MD5", + "!PSK", + "!SRP", + "!CAMELLIA", + ], + "clientAuthentication": "none", + "keyConfigured": false, + "keystoreConfigured": false, + "redirectHttpFromPortConfigured": false, + "supportedProtocols": Array [ + "TLSv1.1", + "TLSv1.2", + ], + "truststoreConfigured": false, + }, + "xsrf": Object { + "disableProtection": false, + "whitelistConfigured": false, + }, + }, + "logging": Object { + "appendersTypesUsed": Array [], + "loggersConfiguredCount": 0, + }, + "savedObjects": Object { + "maxImportExportSizeBytes": 10000, + "maxImportPayloadBytes": 10485760, + }, + }, + "environment": Object { + "memory": Object { + "heapSizeLimit": 1, + "heapTotalBytes": 1, + "heapUsedBytes": 1, + }, + }, + "services": Object { + "savedObjects": Object { + "indices": Array [ + Object { + "alias": ".kibana", + "docsCount": 10, + "docsDeleted": 10, + "primaryStoreSizeBytes": 2000, + "storeSizeBytes": 1000, + }, + Object { + "alias": ".kibana_task_manager", + "docsCount": 20, + "docsDeleted": 20, + "primaryStoreSizeBytes": 4000, + "storeSizeBytes": 2000, + }, + ], + }, + }, + } + `); + }); + }); + }); + + describe('setup and stop', () => { + it('subscribes and unsubscribes from all config paths and metrics', () => { + getTestScheduler().run(({ cold, hot, expectSubscriptions }) => { + const observables: Array> = []; + configService.atPath.mockImplementation(() => { + const newObservable = hot('-a-------'); + observables.push(newObservable); + return newObservable; + }); + const metrics = metricsServiceMock.createInternalSetupContract(); + metrics.getOpsMetrics$.mockImplementation(() => { + const newObservable = hot('-a-------'); + observables.push(newObservable); + return newObservable as Observable; + }); + + service.setup({ metrics }); + + // Use the stopTimer$ to delay calling stop() until the third frame + const stopTimer$ = cold('---a|'); + stopTimer$.subscribe(() => { + service.stop(); + }); + + const subs = '^--!'; + + observables.forEach((o) => { + expectSubscriptions(o.subscriptions).toBe(subs); + }); + }); + }); + }); +}); 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 new file mode 100644 index 0000000000000..f729e23cb68bc --- /dev/null +++ b/src/core/server/core_usage_data/core_usage_data_service.ts @@ -0,0 +1,285 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { Subject } from 'rxjs'; +import { takeUntil } from 'rxjs/operators'; + +import { CoreService } from 'src/core/types'; +import { SavedObjectsServiceStart } from 'src/core/server'; +import { CoreContext } from '../core_context'; +import { ElasticsearchConfigType } from '../elasticsearch/elasticsearch_config'; +import { HttpConfigType } from '../http'; +import { LoggingConfigType } from '../logging'; +import { SavedObjectsConfigType } from '../saved_objects/saved_objects_config'; +import { CoreServicesUsageData, CoreUsageData, CoreUsageDataStart } from './types'; +import { isConfigured } from './is_configured'; +import { ElasticsearchServiceStart } from '../elasticsearch'; +import { KibanaConfigType } from '../kibana_config'; +import { MetricsServiceSetup, OpsMetrics } from '..'; + +export interface SetupDeps { + metrics: MetricsServiceSetup; +} + +export interface StartDeps { + savedObjects: SavedObjectsServiceStart; + elasticsearch: ElasticsearchServiceStart; +} + +/** + * Because users can configure their Saved Object to any arbitrary index name, + * we need to map customized index names back to a "standard" index name. + * + * e.g. If a user configures `kibana.index: .my_saved_objects` we want to the + * collected data to be grouped under `.kibana` not ".my_saved_objects". + * + * This is rather brittle, but the option to configure index names might go + * away completely anyway (see #60053). + * + * @param index The index name configured for this SO type + * @param kibanaConfigIndex The default kibana index as configured by the user + * with `kibana.index` + */ +const kibanaOrTaskManagerIndex = (index: string, kibanaConfigIndex: string) => { + return index === kibanaConfigIndex ? '.kibana' : '.kibana_task_manager'; +}; + +export class CoreUsageDataService implements CoreService { + private elasticsearchConfig?: ElasticsearchConfigType; + private configService: CoreContext['configService']; + private httpConfig?: HttpConfigType; + private loggingConfig?: LoggingConfigType; + private soConfig?: SavedObjectsConfigType; + private stop$: Subject; + private opsMetrics?: OpsMetrics; + private kibanaConfig?: KibanaConfigType; + + constructor(core: CoreContext) { + this.configService = core.configService; + this.stop$ = new Subject(); + } + + private async getSavedObjectIndicesUsageData( + savedObjects: SavedObjectsServiceStart, + elasticsearch: ElasticsearchServiceStart + ): Promise { + const indices = await Promise.all( + Array.from( + savedObjects + .getTypeRegistry() + .getAllTypes() + .reduce((acc, type) => { + const index = type.indexPattern ?? this.kibanaConfig!.index; + return index != null ? acc.add(index) : acc; + }, new Set()) + .values() + ).map((index) => { + // The _cat/indices API returns the _index_ and doesn't return a way + // to map back from the index to the alias. So we have to make an API + // call for every alias + return elasticsearch.client.asInternalUser.cat + .indices({ + index, + format: 'JSON', + bytes: 'b', + }) + .then(({ body }) => { + const stats = body[0]; + return { + alias: kibanaOrTaskManagerIndex(index, this.kibanaConfig!.index), + docsCount: stats['docs.count'], + docsDeleted: stats['docs.deleted'], + storeSizeBytes: stats['store.size'], + primaryStoreSizeBytes: stats['pri.store.size'], + }; + }); + }) + ); + + return { + indices, + }; + } + + private async getCoreUsageData( + savedObjects: SavedObjectsServiceStart, + elasticsearch: ElasticsearchServiceStart + ): Promise { + if ( + this.elasticsearchConfig == null || + this.httpConfig == null || + this.soConfig == null || + this.opsMetrics == null + ) { + throw new Error('Unable to read config values. Ensure that setup() has completed.'); + } + + const es = this.elasticsearchConfig; + const soUsageData = await this.getSavedObjectIndicesUsageData(savedObjects, elasticsearch); + + const http = this.httpConfig; + return { + config: { + elasticsearch: { + apiVersion: es.apiVersion, + sniffOnStart: es.sniffOnStart, + sniffIntervalMs: es.sniffInterval !== false ? es.sniffInterval.asMilliseconds() : -1, + sniffOnConnectionFault: es.sniffOnConnectionFault, + numberOfHostsConfigured: Array.isArray(es.hosts) + ? es.hosts.length + : isConfigured.string(es.hosts) + ? 1 + : 0, + customHeadersConfigured: isConfigured.record(es.customHeaders), + healthCheckDelayMs: es.healthCheck.delay.asMilliseconds(), + logQueries: es.logQueries, + pingTimeoutMs: es.pingTimeout.asMilliseconds(), + requestHeadersWhitelistConfigured: isConfigured.stringOrArray( + es.requestHeadersWhitelist, + ['authorization'] + ), + requestTimeoutMs: es.requestTimeout.asMilliseconds(), + shardTimeoutMs: es.shardTimeout.asMilliseconds(), + ssl: { + alwaysPresentCertificate: es.ssl.alwaysPresentCertificate, + certificateAuthoritiesConfigured: isConfigured.stringOrArray( + es.ssl.certificateAuthorities + ), + certificateConfigured: isConfigured.string(es.ssl.certificate), + keyConfigured: isConfigured.string(es.ssl.key), + verificationMode: es.ssl.verificationMode, + truststoreConfigured: isConfigured.record(es.ssl.truststore), + keystoreConfigured: isConfigured.record(es.ssl.keystore), + }, + }, + http: { + basePathConfigured: isConfigured.string(http.basePath), + maxPayloadInBytes: http.maxPayload.getValueInBytes(), + rewriteBasePath: http.rewriteBasePath, + keepaliveTimeout: http.keepaliveTimeout, + socketTimeout: http.socketTimeout, + compression: { + enabled: http.compression.enabled, + referrerWhitelistConfigured: isConfigured.array(http.compression.referrerWhitelist), + }, + xsrf: { + disableProtection: http.xsrf.disableProtection, + whitelistConfigured: isConfigured.array(http.xsrf.whitelist), + }, + requestId: { + allowFromAnyIp: http.requestId.allowFromAnyIp, + ipAllowlistConfigured: isConfigured.array(http.requestId.ipAllowlist), + }, + ssl: { + certificateAuthoritiesConfigured: isConfigured.stringOrArray( + http.ssl.certificateAuthorities + ), + certificateConfigured: isConfigured.string(http.ssl.certificate), + cipherSuites: http.ssl.cipherSuites, + keyConfigured: isConfigured.string(http.ssl.key), + redirectHttpFromPortConfigured: isConfigured.number(http.ssl.redirectHttpFromPort), + supportedProtocols: http.ssl.supportedProtocols, + clientAuthentication: http.ssl.clientAuthentication, + keystoreConfigured: isConfigured.record(http.ssl.keystore), + truststoreConfigured: isConfigured.record(http.ssl.truststore), + }, + }, + + logging: { + appendersTypesUsed: Array.from( + Array.from(this.loggingConfig?.appenders.values() ?? []) + .reduce((acc, a) => acc.add(a.kind), new Set()) + .values() + ), + loggersConfiguredCount: this.loggingConfig?.loggers.length ?? 0, + }, + + savedObjects: { + maxImportPayloadBytes: this.soConfig.maxImportPayloadBytes.getValueInBytes(), + maxImportExportSizeBytes: this.soConfig.maxImportExportSize.getValueInBytes(), + }, + }, + environment: { + memory: { + heapSizeLimit: this.opsMetrics.process.memory.heap.size_limit, + heapTotalBytes: this.opsMetrics.process.memory.heap.total_in_bytes, + heapUsedBytes: this.opsMetrics.process.memory.heap.used_in_bytes, + }, + }, + services: { + savedObjects: soUsageData, + }, + }; + } + + setup({ metrics }: SetupDeps) { + metrics + .getOpsMetrics$() + .pipe(takeUntil(this.stop$)) + .subscribe((opsMetrics) => (this.opsMetrics = opsMetrics)); + + this.configService + .atPath('elasticsearch') + .pipe(takeUntil(this.stop$)) + .subscribe((config) => { + this.elasticsearchConfig = config; + }); + + this.configService + .atPath('server') + .pipe(takeUntil(this.stop$)) + .subscribe((config) => { + this.httpConfig = config; + }); + + this.configService + .atPath('logging') + .pipe(takeUntil(this.stop$)) + .subscribe((config) => { + this.loggingConfig = config; + }); + + this.configService + .atPath('savedObjects') + .pipe(takeUntil(this.stop$)) + .subscribe((config) => { + this.soConfig = config; + }); + + this.configService + .atPath('kibana') + .pipe(takeUntil(this.stop$)) + .subscribe((config) => { + this.kibanaConfig = config; + }); + } + + start({ savedObjects, elasticsearch }: StartDeps) { + return { + getCoreUsageData: () => { + return this.getCoreUsageData(savedObjects, elasticsearch); + }, + }; + } + + stop() { + this.stop$.next(); + this.stop$.complete(); + } +} diff --git a/src/core/server/core_usage_data/index.ts b/src/core/server/core_usage_data/index.ts new file mode 100644 index 0000000000000..b78c126657ef6 --- /dev/null +++ b/src/core/server/core_usage_data/index.ts @@ -0,0 +1,31 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +export { CoreUsageDataStart } from './types'; +export { CoreUsageDataService } from './core_usage_data_service'; + +// Because of #79265 we need to explicity import, then export these types for +// scripts/telemetry_check.js to work as expected +import { + CoreUsageData, + CoreConfigUsageData, + CoreEnvironmentUsageData, + CoreServicesUsageData, +} from './types'; + +export { CoreUsageData, CoreConfigUsageData, CoreEnvironmentUsageData, CoreServicesUsageData }; diff --git a/src/core/server/core_usage_data/is_configured.test.ts b/src/core/server/core_usage_data/is_configured.test.ts new file mode 100644 index 0000000000000..e5d04946b8766 --- /dev/null +++ b/src/core/server/core_usage_data/is_configured.test.ts @@ -0,0 +1,137 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { isConfigured } from './is_configured'; + +describe('isConfigured', () => { + describe('#string', () => { + it('returns true for a non-empty string', () => { + expect(isConfigured.string('I am configured')).toEqual(true); + }); + + it('returns false for an empty string', () => { + expect(isConfigured.string(' ')).toEqual(false); + expect(isConfigured.string(' ')).toEqual(false); + }); + + it('returns false for undefined', () => { + expect(isConfigured.string(undefined)).toEqual(false); + }); + + it('returns false for null', () => { + expect(isConfigured.string(null as any)).toEqual(false); + }); + + it('returns false for a record', () => { + expect(isConfigured.string({} as any)).toEqual(false); + expect(isConfigured.string({ key: 'hello' } as any)).toEqual(false); + }); + + it('returns false for an array', () => { + expect(isConfigured.string([] as any)).toEqual(false); + expect(isConfigured.string(['hello'] as any)).toEqual(false); + }); + }); + + describe('array', () => { + it('returns true for a non-empty array', () => { + expect(isConfigured.array(['a'])).toEqual(true); + expect(isConfigured.array([{}])).toEqual(true); + expect(isConfigured.array([{ key: 'hello' }])).toEqual(true); + }); + + it('returns false for an empty array', () => { + expect(isConfigured.array([])).toEqual(false); + }); + + it('returns false for undefined', () => { + expect(isConfigured.array(undefined)).toEqual(false); + }); + + it('returns false for null', () => { + expect(isConfigured.array(null as any)).toEqual(false); + }); + + it('returns false for a string', () => { + expect(isConfigured.array('string')).toEqual(false); + }); + + it('returns false for a record', () => { + expect(isConfigured.array({} as any)).toEqual(false); + }); + }); + + describe('stringOrArray', () => { + const arraySpy = jest.spyOn(isConfigured, 'array'); + const stringSpy = jest.spyOn(isConfigured, 'string'); + + it('calls #array for an array', () => { + isConfigured.stringOrArray([]); + expect(arraySpy).toHaveBeenCalledWith([]); + }); + + it('calls #string for non-array values', () => { + isConfigured.stringOrArray('string'); + expect(stringSpy).toHaveBeenCalledWith('string'); + }); + }); + + describe('record', () => { + it('returns true for a non-empty record', () => { + expect(isConfigured.record({ key: 'hello' })).toEqual(true); + expect(isConfigured.record({ key: undefined })).toEqual(true); + }); + + it('returns false for an empty record', () => { + expect(isConfigured.record({})).toEqual(false); + }); + it('returns false for undefined', () => { + expect(isConfigured.record(undefined)).toEqual(false); + }); + it('returns false for null', () => { + expect(isConfigured.record(null as any)).toEqual(false); + }); + }); + + describe('number', () => { + it('returns true for a valid number', () => { + expect(isConfigured.number(0)).toEqual(true); + expect(isConfigured.number(-0)).toEqual(true); + expect(isConfigured.number(1)).toEqual(true); + expect(isConfigured.number(-0)).toEqual(true); + }); + + it('returns false for NaN', () => { + expect(isConfigured.number(Number.NaN)).toEqual(false); + }); + + it('returns false for a string', () => { + expect(isConfigured.number('1' as any)).toEqual(false); + expect(isConfigured.number('' as any)).toEqual(false); + }); + + it('returns false for undefined', () => { + expect(isConfigured.number(undefined)).toEqual(false); + }); + + it('returns false for null', () => { + expect(isConfigured.number(null as any)).toEqual(false); + }); + }); +}); diff --git a/src/core/server/core_usage_data/is_configured.ts b/src/core/server/core_usage_data/is_configured.ts new file mode 100644 index 0000000000000..e66f990f1037c --- /dev/null +++ b/src/core/server/core_usage_data/is_configured.ts @@ -0,0 +1,65 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { isEqual } from 'lodash'; + +/** + * Test whether a given config value is configured based on it's schema type. + * Our configuration schema and code often accept and ignore empty values like + * `elasticsearch.customHeaders: {}`. However, for telemetry purposes, we're + * only interested when these values have been set to something that will + * change the behaviour of Kibana. + */ +export const isConfigured = { + /** + * config is a string with non-zero length + */ + string: (config?: string): boolean => { + return (config?.trim?.()?.length ?? 0) > 0; + }, + /** + * config is an array with non-zero length + */ + array: (config?: unknown[] | string, defaultValue?: any): boolean => { + return Array.isArray(config) + ? (config?.length ?? 0) > 0 && !isEqual(config, defaultValue) + : false; + }, + /** + * config is a string or array of strings where each element has non-zero length + */ + stringOrArray: (config?: string[] | string, defaultValue?: any): boolean => { + return Array.isArray(config) + ? isConfigured.array(config, defaultValue) + : isConfigured.string(config); + }, + /** + * config is a record with at least one key + */ + record: (config?: Record): boolean => { + return config != null && typeof config === 'object' && Object.keys(config).length > 0; + }, + /** + * config is a number + */ + number: (config?: number): boolean => { + // kbn-config-schema already does NaN validation, but doesn't hurt to be sure + return typeof config === 'number' && !isNaN(config); + }, +}; diff --git a/src/core/server/core_usage_data/types.ts b/src/core/server/core_usage_data/types.ts new file mode 100644 index 0000000000000..52d2eadcf1377 --- /dev/null +++ b/src/core/server/core_usage_data/types.ts @@ -0,0 +1,162 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +/** + * Type describing Core's usage data payload + * @internal + */ +export interface CoreUsageData { + config: CoreConfigUsageData; + services: CoreServicesUsageData; + environment: CoreEnvironmentUsageData; +} + +/** + * Usage data from Core services + * @internal + */ +export interface CoreServicesUsageData { + savedObjects: { + // scripts/telemetry_check.js does not support parsing Array<{...}> types + // so we have to disable eslint here and use {...}[] + // eslint-disable-next-line @typescript-eslint/array-type + indices: { + alias: string; + docsCount: number; + docsDeleted: number; + storeSizeBytes: number; + primaryStoreSizeBytes: number; + }[]; + }; +} + +/** + * Usage data on this Kibana node's runtime environment. + * @internal + */ +export interface CoreEnvironmentUsageData { + memory: { + heapTotalBytes: number; + heapUsedBytes: number; + /** V8 heap size limit */ + heapSizeLimit: number; + }; +} + +/** + * Usage data on this cluster's configuration of Core features + * @internal + */ +export interface CoreConfigUsageData { + elasticsearch: { + sniffOnStart: boolean; + sniffIntervalMs?: number; + sniffOnConnectionFault: boolean; + numberOfHostsConfigured: number; + requestHeadersWhitelistConfigured: boolean; + customHeadersConfigured: boolean; + shardTimeoutMs: number; + requestTimeoutMs: number; + pingTimeoutMs: number; + logQueries: boolean; + ssl: { + verificationMode: 'none' | 'certificate' | 'full'; + certificateAuthoritiesConfigured: boolean; + certificateConfigured: boolean; + keyConfigured: boolean; + keystoreConfigured: boolean; + truststoreConfigured: boolean; + alwaysPresentCertificate: boolean; + }; + apiVersion: string; + healthCheckDelayMs: number; + }; + + http: { + basePathConfigured: boolean; + maxPayloadInBytes: number; + rewriteBasePath: boolean; + keepaliveTimeout: number; + socketTimeout: number; + compression: { + enabled: boolean; + referrerWhitelistConfigured: boolean; + }; + xsrf: { + disableProtection: boolean; + whitelistConfigured: boolean; + }; + requestId: { + allowFromAnyIp: boolean; + ipAllowlistConfigured: boolean; + }; + ssl: { + certificateAuthoritiesConfigured: boolean; + certificateConfigured: boolean; + cipherSuites: string[]; + keyConfigured: boolean; + keystoreConfigured: boolean; + truststoreConfigured: boolean; + redirectHttpFromPortConfigured: boolean; + supportedProtocols: string[]; + clientAuthentication: 'none' | 'optional' | 'required'; + }; + }; + + logging: { + appendersTypesUsed: string[]; + loggersConfiguredCount: number; + }; + + // plugins: { + // /** list of built-in plugins that are disabled */ + // firstPartyDisabled: string[]; + // /** list of third-party plugins that are installed and enabled */ + // thirdParty: string[]; + // }; + + savedObjects: { + maxImportPayloadBytes: number; + maxImportExportSizeBytes: number; + }; + + // uiSettings: { + // overridesCount: number; + // }; +} + +/** + * Internal API for getting Core's usage data payload. + * + * @note This API should never be used to drive application logic and is only + * intended for telemetry purposes. + * + * @internal + */ +export interface CoreUsageDataStart { + /** + * Internal API for getting Core's usage data payload. + * + * @note This API should never be used to drive application logic and is only + * intended for telemetry purposes. + * + * @internal + * */ + getCoreUsageData(): Promise; +} diff --git a/src/core/server/elasticsearch/client/client_config.test.ts b/src/core/server/elasticsearch/client/client_config.test.ts index 675d8840e7118..e8083836d3c1e 100644 --- a/src/core/server/elasticsearch/client/client_config.test.ts +++ b/src/core/server/elasticsearch/client/client_config.test.ts @@ -19,6 +19,7 @@ import { duration } from 'moment'; import { ElasticsearchClientConfig, parseClientOptions } from './client_config'; +import { DEFAULT_HEADERS } from '../default_headers'; const createConfig = ( parts: Partial = {} @@ -36,6 +37,18 @@ const createConfig = ( }; describe('parseClientOptions', () => { + it('includes headers designing the HTTP request as originating from Kibana by default', () => { + const config = createConfig({}); + + expect(parseClientOptions(config, false)).toEqual( + expect.objectContaining({ + headers: { + ...DEFAULT_HEADERS, + }, + }) + ); + }); + describe('basic options', () => { it('`customHeaders` option', () => { const config = createConfig({ @@ -48,6 +61,7 @@ describe('parseClientOptions', () => { expect(parseClientOptions(config, false)).toEqual( expect.objectContaining({ headers: { + ...DEFAULT_HEADERS, foo: 'bar', hello: 'dolly', }, @@ -55,6 +69,25 @@ describe('parseClientOptions', () => { ); }); + it('`customHeaders` take precedence to default kibana headers', () => { + const customHeader = { + [Object.keys(DEFAULT_HEADERS)[0]]: 'foo', + }; + const config = createConfig({ + customHeaders: { + ...customHeader, + }, + }); + + expect(parseClientOptions(config, false)).toEqual( + expect.objectContaining({ + headers: { + ...customHeader, + }, + }) + ); + }); + it('`keepAlive` option', () => { expect(parseClientOptions(createConfig({ keepAlive: true }), false)).toEqual( expect.objectContaining({ agent: { keepAlive: true } }) diff --git a/src/core/server/elasticsearch/client/client_config.ts b/src/core/server/elasticsearch/client/client_config.ts index f365ca331cfea..f24c0d86550b8 100644 --- a/src/core/server/elasticsearch/client/client_config.ts +++ b/src/core/server/elasticsearch/client/client_config.ts @@ -22,6 +22,7 @@ import { URL } from 'url'; import { Duration } from 'moment'; import { ClientOptions, NodeOptions } from '@elastic/elasticsearch'; import { ElasticsearchConfig } from '../elasticsearch_config'; +import { DEFAULT_HEADERS } from '../default_headers'; /** * Configuration options to be used to create a {@link IClusterClient | cluster client} using the @@ -61,7 +62,10 @@ export function parseClientOptions( const clientOptions: ClientOptions = { sniffOnStart: config.sniffOnStart, sniffOnConnectionFault: config.sniffOnConnectionFault, - headers: config.customHeaders, + headers: { + ...DEFAULT_HEADERS, + ...config.customHeaders, + }, }; if (config.pingTimeout != null) { diff --git a/src/core/server/elasticsearch/client/cluster_client.test.ts b/src/core/server/elasticsearch/client/cluster_client.test.ts index 121ef3aa42d51..429fea65704d8 100644 --- a/src/core/server/elasticsearch/client/cluster_client.test.ts +++ b/src/core/server/elasticsearch/client/cluster_client.test.ts @@ -24,6 +24,7 @@ import { GetAuthHeaders } from '../../http'; import { elasticsearchClientMock } from './mocks'; import { ClusterClient } from './cluster_client'; import { ElasticsearchClientConfig } from './client_config'; +import { DEFAULT_HEADERS } from '../default_headers'; const createConfig = ( parts: Partial = {} @@ -127,7 +128,7 @@ describe('ClusterClient', () => { expect(scopedClient.child).toHaveBeenCalledTimes(1); expect(scopedClient.child).toHaveBeenCalledWith({ - headers: { foo: 'bar', 'x-opaque-id': expect.any(String) }, + headers: { ...DEFAULT_HEADERS, foo: 'bar', 'x-opaque-id': expect.any(String) }, }); }); @@ -147,7 +148,7 @@ describe('ClusterClient', () => { expect(scopedClient.child).toHaveBeenCalledTimes(1); expect(scopedClient.child).toHaveBeenCalledWith({ - headers: { authorization: 'auth', 'x-opaque-id': expect.any(String) }, + headers: { ...DEFAULT_HEADERS, authorization: 'auth', 'x-opaque-id': expect.any(String) }, }); }); @@ -171,7 +172,7 @@ describe('ClusterClient', () => { expect(scopedClient.child).toHaveBeenCalledTimes(1); expect(scopedClient.child).toHaveBeenCalledWith({ - headers: { authorization: 'auth', 'x-opaque-id': expect.any(String) }, + headers: { ...DEFAULT_HEADERS, authorization: 'auth', 'x-opaque-id': expect.any(String) }, }); }); @@ -193,6 +194,7 @@ describe('ClusterClient', () => { expect(scopedClient.child).toHaveBeenCalledTimes(1); expect(scopedClient.child).toHaveBeenCalledWith({ headers: { + ...DEFAULT_HEADERS, foo: 'bar', hello: 'dolly', 'x-opaque-id': expect.any(String), @@ -206,7 +208,7 @@ describe('ClusterClient', () => { const clusterClient = new ClusterClient(config, logger, getAuthHeaders); const request = httpServerMock.createKibanaRequest({ - kibanaRequestState: { requestId: 'my-fake-id' }, + kibanaRequestState: { requestId: 'my-fake-id', requestUuid: 'ignore-this-id' }, }); clusterClient.asScoped(request); @@ -214,6 +216,7 @@ describe('ClusterClient', () => { expect(scopedClient.child).toHaveBeenCalledTimes(1); expect(scopedClient.child).toHaveBeenCalledWith({ headers: { + ...DEFAULT_HEADERS, 'x-opaque-id': 'my-fake-id', }, }); @@ -239,6 +242,7 @@ describe('ClusterClient', () => { expect(scopedClient.child).toHaveBeenCalledTimes(1); expect(scopedClient.child).toHaveBeenCalledWith({ headers: { + ...DEFAULT_HEADERS, foo: 'auth', hello: 'dolly', 'x-opaque-id': expect.any(String), @@ -266,6 +270,7 @@ describe('ClusterClient', () => { expect(scopedClient.child).toHaveBeenCalledTimes(1); expect(scopedClient.child).toHaveBeenCalledWith({ headers: { + ...DEFAULT_HEADERS, foo: 'request', hello: 'dolly', 'x-opaque-id': expect.any(String), @@ -273,6 +278,52 @@ describe('ClusterClient', () => { }); }); + it('respect the precedence of config headers over default headers', () => { + const headerKey = Object.keys(DEFAULT_HEADERS)[0]; + const config = createConfig({ + customHeaders: { + [headerKey]: 'foo', + }, + }); + getAuthHeaders.mockReturnValue({}); + + const clusterClient = new ClusterClient(config, logger, getAuthHeaders); + const request = httpServerMock.createKibanaRequest(); + + clusterClient.asScoped(request); + + expect(scopedClient.child).toHaveBeenCalledTimes(1); + expect(scopedClient.child).toHaveBeenCalledWith({ + headers: { + [headerKey]: 'foo', + 'x-opaque-id': expect.any(String), + }, + }); + }); + + it('respect the precedence of request headers over default headers', () => { + const headerKey = Object.keys(DEFAULT_HEADERS)[0]; + const config = createConfig({ + requestHeadersWhitelist: [headerKey], + }); + getAuthHeaders.mockReturnValue({}); + + const clusterClient = new ClusterClient(config, logger, getAuthHeaders); + const request = httpServerMock.createKibanaRequest({ + headers: { [headerKey]: 'foo' }, + }); + + clusterClient.asScoped(request); + + expect(scopedClient.child).toHaveBeenCalledTimes(1); + expect(scopedClient.child).toHaveBeenCalledWith({ + headers: { + [headerKey]: 'foo', + 'x-opaque-id': expect.any(String), + }, + }); + }); + it('respect the precedence of x-opaque-id header over config headers', () => { const config = createConfig({ customHeaders: { @@ -284,7 +335,7 @@ describe('ClusterClient', () => { const clusterClient = new ClusterClient(config, logger, getAuthHeaders); const request = httpServerMock.createKibanaRequest({ headers: { foo: 'request' }, - kibanaRequestState: { requestId: 'from request' }, + kibanaRequestState: { requestId: 'from request', requestUuid: 'ignore-this-id' }, }); clusterClient.asScoped(request); @@ -292,6 +343,7 @@ describe('ClusterClient', () => { expect(scopedClient.child).toHaveBeenCalledTimes(1); expect(scopedClient.child).toHaveBeenCalledWith({ headers: { + ...DEFAULT_HEADERS, 'x-opaque-id': 'from request', }, }); @@ -315,7 +367,7 @@ describe('ClusterClient', () => { expect(scopedClient.child).toHaveBeenCalledTimes(1); expect(scopedClient.child).toHaveBeenCalledWith({ - headers: { authorization: 'auth' }, + headers: { ...DEFAULT_HEADERS, authorization: 'auth' }, }); }); @@ -339,7 +391,7 @@ describe('ClusterClient', () => { expect(scopedClient.child).toHaveBeenCalledTimes(1); expect(scopedClient.child).toHaveBeenCalledWith({ - headers: { foo: 'bar' }, + headers: { ...DEFAULT_HEADERS, foo: 'bar' }, }); }); }); diff --git a/src/core/server/elasticsearch/client/cluster_client.ts b/src/core/server/elasticsearch/client/cluster_client.ts index ffe0c10321fff..2294df89d4274 100644 --- a/src/core/server/elasticsearch/client/cluster_client.ts +++ b/src/core/server/elasticsearch/client/cluster_client.ts @@ -26,6 +26,7 @@ import { ElasticsearchClient } from './types'; import { configureClient } from './configure_client'; import { ElasticsearchClientConfig } from './client_config'; import { ScopedClusterClient, IScopedClusterClient } from './scoped_cluster_client'; +import { DEFAULT_HEADERS } from '../default_headers'; const noop = () => undefined; @@ -108,6 +109,7 @@ export class ClusterClient implements ICustomClusterClient { } return { + ...DEFAULT_HEADERS, ...this.config.customHeaders, ...scopedHeaders, }; diff --git a/src/core/server/elasticsearch/client/mocks.ts b/src/core/server/elasticsearch/client/mocks.ts index 6fb3dc090bfb4..fb2826c787718 100644 --- a/src/core/server/elasticsearch/client/mocks.ts +++ b/src/core/server/elasticsearch/client/mocks.ts @@ -31,6 +31,7 @@ const createInternalClientMock = (): DeeplyMockedKeys => { '_events', '_eventsCount', '_maxListeners', + 'constructor', 'name', 'serializer', 'connectionPool', @@ -38,35 +39,57 @@ const createInternalClientMock = (): DeeplyMockedKeys => { 'helpers', ]; + const getAllPropertyDescriptors = (obj: Record) => { + const descriptors = Object.entries(Object.getOwnPropertyDescriptors(obj)); + let prototype = Object.getPrototypeOf(obj); + while (prototype != null && prototype !== Object.prototype) { + descriptors.push(...Object.entries(Object.getOwnPropertyDescriptors(prototype))); + prototype = Object.getPrototypeOf(prototype); + } + return descriptors; + }; + const mockify = (obj: Record, omitted: string[] = []) => { - Object.keys(obj) - .filter((key) => !omitted.includes(key)) - .forEach((key) => { - const propType = typeof obj[key]; - if (propType === 'function') { + // the @elastic/elasticsearch::Client uses prototypical inheritance + // so we have to crawl up the prototype chain and get all descriptors + // to find everything that we should be mocking + const descriptors = getAllPropertyDescriptors(obj); + descriptors + .filter(([key]) => !omitted.includes(key)) + .forEach(([key, descriptor]) => { + if (typeof descriptor.value === 'function') { obj[key] = jest.fn(() => createSuccessTransportRequestPromise({})); - } else if (propType === 'object' && obj[key] != null) { - mockify(obj[key]); + } else if (typeof obj[key] === 'object' && obj[key] != null) { + mockify(obj[key], omitted); } }); }; mockify(client, omittedProps); - // client got some read-only (getter) properties - // so we need to extend it to override the getter-only props. - const mock: any = { ...client }; + client.close = jest.fn().mockReturnValue(Promise.resolve()); + client.child = jest.fn().mockImplementation(() => createInternalClientMock()); + + const mockGetter = (obj: Record, propertyName: string) => { + Object.defineProperty(obj, propertyName, { + configurable: true, + enumerable: false, + get: () => jest.fn(), + set: undefined, + }); + }; - mock.transport = { + // `on`, `off`, and `once` are properties without a setter. + // We can't `client.on = jest.fn()` because the following error will be thrown: + // TypeError: Cannot set property on of # which has only a getter + mockGetter(client, 'on'); + mockGetter(client, 'off'); + mockGetter(client, 'once'); + client.transport = { request: jest.fn(), }; - mock.close = jest.fn().mockReturnValue(Promise.resolve()); - mock.child = jest.fn().mockImplementation(() => createInternalClientMock()); - mock.on = jest.fn(); - mock.off = jest.fn(); - mock.once = jest.fn(); - return (mock as unknown) as DeeplyMockedKeys; + return client as DeeplyMockedKeys; }; export type ElasticsearchClientMock = DeeplyMockedKeys; diff --git a/src/core/server/elasticsearch/default_headers.ts b/src/core/server/elasticsearch/default_headers.ts new file mode 100644 index 0000000000000..4cc4b4b2507c4 --- /dev/null +++ b/src/core/server/elasticsearch/default_headers.ts @@ -0,0 +1,27 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { deepFreeze } from '@kbn/std'; + +export const DEFAULT_HEADERS = deepFreeze({ + // Elasticsearch uses this to identify when a request is coming from Kibana, to allow Kibana to + // access system indices using the standard ES APIs without logging a warning. After migrating to + // use the new system index APIs, this header can be removed. + 'x-elastic-product-origin': 'kibana', +}); diff --git a/src/core/server/elasticsearch/elasticsearch_config.ts b/src/core/server/elasticsearch/elasticsearch_config.ts index cac8c75a04486..cfc1edfbd318e 100644 --- a/src/core/server/elasticsearch/elasticsearch_config.ts +++ b/src/core/server/elasticsearch/elasticsearch_config.ts @@ -45,7 +45,6 @@ export const configSchema = schema.object({ hosts: schema.oneOf([hostURISchema, schema.arrayOf(hostURISchema, { minSize: 1 })], { defaultValue: 'http://localhost:9200', }), - preserveHost: schema.boolean({ defaultValue: true }), username: schema.maybe( schema.conditional( schema.contextRef('dist'), @@ -71,7 +70,6 @@ export const configSchema = schema.object({ shardTimeout: schema.duration({ defaultValue: '30s' }), requestTimeout: schema.duration({ defaultValue: '30s' }), pingTimeout: schema.duration({ defaultValue: schema.siblingRef('requestTimeout') }), - startupTimeout: schema.duration({ defaultValue: '5s' }), logQueries: schema.boolean({ defaultValue: false }), ssl: schema.object( { diff --git a/src/core/server/elasticsearch/legacy/cluster_client.test.ts b/src/core/server/elasticsearch/legacy/cluster_client.test.ts index 73d941053e84b..745ef4304d0b1 100644 --- a/src/core/server/elasticsearch/legacy/cluster_client.test.ts +++ b/src/core/server/elasticsearch/legacy/cluster_client.test.ts @@ -351,7 +351,9 @@ describe('#asScoped', () => { test('passes x-opaque-id header with request id', () => { clusterClient.asScoped( - httpServerMock.createKibanaRequest({ kibanaRequestState: { requestId: 'alpha' } }) + httpServerMock.createKibanaRequest({ + kibanaRequestState: { requestId: 'alpha', requestUuid: 'ignore-this-id' }, + }) ); expect(MockScopedClusterClient).toHaveBeenCalledTimes(1); diff --git a/src/core/server/elasticsearch/legacy/elasticsearch_client_config.test.ts b/src/core/server/elasticsearch/legacy/elasticsearch_client_config.test.ts index d6b65da7726d2..1e85932caa8ae 100644 --- a/src/core/server/elasticsearch/legacy/elasticsearch_client_config.test.ts +++ b/src/core/server/elasticsearch/legacy/elasticsearch_client_config.test.ts @@ -23,6 +23,7 @@ import { LegacyElasticsearchClientConfig, parseElasticsearchClientConfig, } from './elasticsearch_client_config'; +import { DEFAULT_HEADERS } from '../default_headers'; const logger = loggingSystemMock.create(); afterEach(() => jest.clearAllMocks()); @@ -41,26 +42,27 @@ test('parses minimally specified config', () => { logger.get() ) ).toMatchInlineSnapshot(` -Object { - "apiVersion": "master", - "hosts": Array [ Object { - "headers": Object { - "xsrf": "something", - }, - "host": "localhost", - "path": "/elasticsearch", - "port": "80", - "protocol": "http:", - "query": null, - }, - ], - "keepAlive": true, - "log": [Function], - "sniffOnConnectionFault": false, - "sniffOnStart": false, -} -`); + "apiVersion": "master", + "hosts": Array [ + Object { + "headers": Object { + "x-elastic-product-origin": "kibana", + "xsrf": "something", + }, + "host": "localhost", + "path": "/elasticsearch", + "port": "80", + "protocol": "http:", + "query": null, + }, + ], + "keepAlive": true, + "log": [Function], + "sniffOnConnectionFault": false, + "sniffOnStart": false, + } + `); }); test('parses fully specified config', () => { @@ -104,63 +106,66 @@ test('parses fully specified config', () => { expect(elasticsearchConfig.ssl).not.toBe(elasticsearchClientConfig.ssl); expect(elasticsearchClientConfig).toMatchInlineSnapshot(` -Object { - "apiVersion": "v7.0.0", - "hosts": Array [ - Object { - "auth": "elastic:changeme", - "headers": Object { - "xsrf": "something", - }, - "host": "localhost", - "path": "/elasticsearch", - "port": "80", - "protocol": "http:", - "query": null, - }, - Object { - "auth": "elastic:changeme", - "headers": Object { - "xsrf": "something", - }, - "host": "domain.com", - "path": "/elasticsearch", - "port": "1234", - "protocol": "http:", - "query": null, - }, Object { - "auth": "elastic:changeme", - "headers": Object { - "xsrf": "something", + "apiVersion": "v7.0.0", + "hosts": Array [ + Object { + "auth": "elastic:changeme", + "headers": Object { + "x-elastic-product-origin": "kibana", + "xsrf": "something", + }, + "host": "localhost", + "path": "/elasticsearch", + "port": "80", + "protocol": "http:", + "query": null, + }, + Object { + "auth": "elastic:changeme", + "headers": Object { + "x-elastic-product-origin": "kibana", + "xsrf": "something", + }, + "host": "domain.com", + "path": "/elasticsearch", + "port": "1234", + "protocol": "http:", + "query": null, + }, + Object { + "auth": "elastic:changeme", + "headers": Object { + "x-elastic-product-origin": "kibana", + "xsrf": "something", + }, + "host": "es.local", + "path": "/", + "port": "443", + "protocol": "https:", + "query": null, + }, + ], + "keepAlive": true, + "log": [Function], + "pingTimeout": 12345, + "requestTimeout": 54321, + "sniffInterval": 11223344, + "sniffOnConnectionFault": true, + "sniffOnStart": true, + "ssl": Object { + "ca": Array [ + "content-of-ca-path-1", + "content-of-ca-path-2", + ], + "cert": "content-of-certificate-path", + "checkServerIdentity": [Function], + "key": "content-of-key-path", + "passphrase": "key-pass", + "rejectUnauthorized": true, }, - "host": "es.local", - "path": "/", - "port": "443", - "protocol": "https:", - "query": null, - }, - ], - "keepAlive": true, - "log": [Function], - "pingTimeout": 12345, - "requestTimeout": 54321, - "sniffInterval": 11223344, - "sniffOnConnectionFault": true, - "sniffOnStart": true, - "ssl": Object { - "ca": Array [ - "content-of-ca-path-1", - "content-of-ca-path-2", - ], - "cert": "content-of-certificate-path", - "checkServerIdentity": [Function], - "key": "content-of-key-path", - "passphrase": "key-pass", - "rejectUnauthorized": true, - }, -} -`); + } + `); }); test('parses config timeouts of moment.Duration type', () => { @@ -181,29 +186,30 @@ test('parses config timeouts of moment.Duration type', () => { logger.get() ) ).toMatchInlineSnapshot(` -Object { - "apiVersion": "master", - "hosts": Array [ Object { - "headers": Object { - "xsrf": "something", - }, - "host": "localhost", - "path": "/elasticsearch", - "port": "9200", - "protocol": "http:", - "query": null, - }, - ], - "keepAlive": true, - "log": [Function], - "pingTimeout": 100, - "requestTimeout": 30000, - "sniffInterval": 60000, - "sniffOnConnectionFault": false, - "sniffOnStart": false, -} -`); + "apiVersion": "master", + "hosts": Array [ + Object { + "headers": Object { + "x-elastic-product-origin": "kibana", + "xsrf": "something", + }, + "host": "localhost", + "path": "/elasticsearch", + "port": "9200", + "protocol": "http:", + "query": null, + }, + ], + "keepAlive": true, + "log": [Function], + "pingTimeout": 100, + "requestTimeout": 30000, + "sniffInterval": 60000, + "sniffOnConnectionFault": false, + "sniffOnStart": false, + } + `); }); describe('#auth', () => { @@ -225,36 +231,38 @@ describe('#auth', () => { { auth: false } ) ).toMatchInlineSnapshot(` -Object { - "apiVersion": "v7.0.0", - "hosts": Array [ - Object { - "headers": Object { - "xsrf": "something", - }, - "host": "localhost", - "path": "/elasticsearch", - "port": "80", - "protocol": "http:", - "query": null, - }, - Object { - "headers": Object { - "xsrf": "something", - }, - "host": "es.local", - "path": "/", - "port": "443", - "protocol": "https:", - "query": null, - }, - ], - "keepAlive": true, - "log": [Function], - "sniffOnConnectionFault": true, - "sniffOnStart": true, -} -`); + Object { + "apiVersion": "v7.0.0", + "hosts": Array [ + Object { + "headers": Object { + "x-elastic-product-origin": "kibana", + "xsrf": "something", + }, + "host": "localhost", + "path": "/elasticsearch", + "port": "80", + "protocol": "http:", + "query": null, + }, + Object { + "headers": Object { + "x-elastic-product-origin": "kibana", + "xsrf": "something", + }, + "host": "es.local", + "path": "/", + "port": "443", + "protocol": "https:", + "query": null, + }, + ], + "keepAlive": true, + "log": [Function], + "sniffOnConnectionFault": true, + "sniffOnStart": true, + } + `); }); test('is not set if username is not specified', () => { @@ -274,26 +282,27 @@ Object { { auth: true } ) ).toMatchInlineSnapshot(` -Object { - "apiVersion": "v7.0.0", - "hosts": Array [ - Object { - "headers": Object { - "xsrf": "something", - }, - "host": "es.local", - "path": "/", - "port": "443", - "protocol": "https:", - "query": null, - }, - ], - "keepAlive": true, - "log": [Function], - "sniffOnConnectionFault": true, - "sniffOnStart": true, -} -`); + Object { + "apiVersion": "v7.0.0", + "hosts": Array [ + Object { + "headers": Object { + "x-elastic-product-origin": "kibana", + "xsrf": "something", + }, + "host": "es.local", + "path": "/", + "port": "443", + "protocol": "https:", + "query": null, + }, + ], + "keepAlive": true, + "log": [Function], + "sniffOnConnectionFault": true, + "sniffOnStart": true, + } + `); }); test('is not set if password is not specified', () => { @@ -313,26 +322,48 @@ Object { { auth: true } ) ).toMatchInlineSnapshot(` -Object { - "apiVersion": "v7.0.0", - "hosts": Array [ - Object { - "headers": Object { - "xsrf": "something", + Object { + "apiVersion": "v7.0.0", + "hosts": Array [ + Object { + "headers": Object { + "x-elastic-product-origin": "kibana", + "xsrf": "something", + }, + "host": "es.local", + "path": "/", + "port": "443", + "protocol": "https:", + "query": null, + }, + ], + "keepAlive": true, + "log": [Function], + "sniffOnConnectionFault": true, + "sniffOnStart": true, + } + `); + }); +}); + +describe('#customHeaders', () => { + test('override the default headers', () => { + const headerKey = Object.keys(DEFAULT_HEADERS)[0]; + const parsedConfig = parseElasticsearchClientConfig( + { + apiVersion: 'master', + customHeaders: { [headerKey]: 'foo' }, + logQueries: false, + sniffOnStart: false, + sniffOnConnectionFault: false, + hosts: ['http://localhost/elasticsearch'], + requestHeadersWhitelist: [], }, - "host": "es.local", - "path": "/", - "port": "443", - "protocol": "https:", - "query": null, - }, - ], - "keepAlive": true, - "log": [Function], - "sniffOnConnectionFault": true, - "sniffOnStart": true, -} -`); + logger.get() + ); + expect(parsedConfig.hosts[0].headers).toEqual({ + [headerKey]: 'foo', + }); }); }); @@ -361,24 +392,24 @@ describe('#log', () => { expect(typeof esLogger.close).toBe('function'); expect(loggingSystemMock.collect(logger)).toMatchInlineSnapshot(` -Object { - "debug": Array [], - "error": Array [ - Array [ - "some-error", - ], - ], - "fatal": Array [], - "info": Array [], - "log": Array [], - "trace": Array [], - "warn": Array [ - Array [ - "some-warning", - ], - ], -} -`); + Object { + "debug": Array [], + "error": Array [ + Array [ + "some-error", + ], + ], + "fatal": Array [], + "info": Array [], + "log": Array [], + "trace": Array [], + "warn": Array [ + Array [ + "some-warning", + ], + ], + } + `); }); test('default logger with #logQueries = true', () => { @@ -407,35 +438,35 @@ Object { expect(typeof esLogger.close).toBe('function'); expect(loggingSystemMock.collect(logger)).toMatchInlineSnapshot(` -Object { - "debug": Array [ - Array [ - "304 -METHOD /some-path -?query=2", Object { - "tags": Array [ - "query", + "debug": Array [ + Array [ + "304 + METHOD /some-path + ?query=2", + Object { + "tags": Array [ + "query", + ], + }, + ], ], - }, - ], - ], - "error": Array [ - Array [ - "some-error", - ], - ], - "fatal": Array [], - "info": Array [], - "log": Array [], - "trace": Array [], - "warn": Array [ - Array [ - "some-warning", - ], - ], -} -`); + "error": Array [ + Array [ + "some-error", + ], + ], + "fatal": Array [], + "info": Array [], + "log": Array [], + "trace": Array [], + "warn": Array [ + Array [ + "some-warning", + ], + ], + } + `); }); test('custom logger', () => { @@ -476,28 +507,30 @@ describe('#ssl', () => { logger.get() ) ).toMatchInlineSnapshot(` -Object { - "apiVersion": "v7.0.0", - "hosts": Array [ - Object { - "headers": Object {}, - "host": "es.local", - "path": "/", - "port": "443", - "protocol": "https:", - "query": null, - }, - ], - "keepAlive": true, - "log": [Function], - "sniffOnConnectionFault": true, - "sniffOnStart": true, - "ssl": Object { - "ca": undefined, - "rejectUnauthorized": false, - }, -} -`); + Object { + "apiVersion": "v7.0.0", + "hosts": Array [ + Object { + "headers": Object { + "x-elastic-product-origin": "kibana", + }, + "host": "es.local", + "path": "/", + "port": "443", + "protocol": "https:", + "query": null, + }, + ], + "keepAlive": true, + "log": [Function], + "sniffOnConnectionFault": true, + "sniffOnStart": true, + "ssl": Object { + "ca": undefined, + "rejectUnauthorized": false, + }, + } + `); }); test('#verificationMode = certificate', () => { @@ -521,29 +554,31 @@ Object { ).toBeUndefined(); expect(clientConfig).toMatchInlineSnapshot(` -Object { - "apiVersion": "v7.0.0", - "hosts": Array [ - Object { - "headers": Object {}, - "host": "es.local", - "path": "/", - "port": "443", - "protocol": "https:", - "query": null, - }, - ], - "keepAlive": true, - "log": [Function], - "sniffOnConnectionFault": true, - "sniffOnStart": true, - "ssl": Object { - "ca": undefined, - "checkServerIdentity": [Function], - "rejectUnauthorized": true, - }, -} -`); + Object { + "apiVersion": "v7.0.0", + "hosts": Array [ + Object { + "headers": Object { + "x-elastic-product-origin": "kibana", + }, + "host": "es.local", + "path": "/", + "port": "443", + "protocol": "https:", + "query": null, + }, + ], + "keepAlive": true, + "log": [Function], + "sniffOnConnectionFault": true, + "sniffOnStart": true, + "ssl": Object { + "ca": undefined, + "checkServerIdentity": [Function], + "rejectUnauthorized": true, + }, + } + `); }); test('#verificationMode = full', () => { @@ -562,28 +597,30 @@ Object { logger.get() ) ).toMatchInlineSnapshot(` -Object { - "apiVersion": "v7.0.0", - "hosts": Array [ - Object { - "headers": Object {}, - "host": "es.local", - "path": "/", - "port": "443", - "protocol": "https:", - "query": null, - }, - ], - "keepAlive": true, - "log": [Function], - "sniffOnConnectionFault": true, - "sniffOnStart": true, - "ssl": Object { - "ca": undefined, - "rejectUnauthorized": true, - }, -} -`); + Object { + "apiVersion": "v7.0.0", + "hosts": Array [ + Object { + "headers": Object { + "x-elastic-product-origin": "kibana", + }, + "host": "es.local", + "path": "/", + "port": "443", + "protocol": "https:", + "query": null, + }, + ], + "keepAlive": true, + "log": [Function], + "sniffOnConnectionFault": true, + "sniffOnStart": true, + "ssl": Object { + "ca": undefined, + "rejectUnauthorized": true, + }, + } + `); }); test('#verificationMode is unknown', () => { @@ -628,30 +665,32 @@ Object { { ignoreCertAndKey: true } ) ).toMatchInlineSnapshot(` -Object { - "apiVersion": "v7.0.0", - "hosts": Array [ - Object { - "headers": Object {}, - "host": "es.local", - "path": "/", - "port": "443", - "protocol": "https:", - "query": null, - }, - ], - "keepAlive": true, - "log": [Function], - "sniffOnConnectionFault": true, - "sniffOnStart": true, - "ssl": Object { - "ca": Array [ - "content-of-ca-path", - ], - "checkServerIdentity": [Function], - "rejectUnauthorized": true, - }, -} -`); + Object { + "apiVersion": "v7.0.0", + "hosts": Array [ + Object { + "headers": Object { + "x-elastic-product-origin": "kibana", + }, + "host": "es.local", + "path": "/", + "port": "443", + "protocol": "https:", + "query": null, + }, + ], + "keepAlive": true, + "log": [Function], + "sniffOnConnectionFault": true, + "sniffOnStart": true, + "ssl": Object { + "ca": Array [ + "content-of-ca-path", + ], + "checkServerIdentity": [Function], + "rejectUnauthorized": true, + }, + } + `); }); }); diff --git a/src/core/server/elasticsearch/legacy/elasticsearch_client_config.ts b/src/core/server/elasticsearch/legacy/elasticsearch_client_config.ts index 6896c0a2e301f..35681ac7a247d 100644 --- a/src/core/server/elasticsearch/legacy/elasticsearch_client_config.ts +++ b/src/core/server/elasticsearch/legacy/elasticsearch_client_config.ts @@ -25,6 +25,7 @@ import url from 'url'; import { pick } from '@kbn/std'; import { Logger } from '../../logging'; import { ElasticsearchConfig } from '../elasticsearch_config'; +import { DEFAULT_HEADERS } from '../default_headers'; /** * @privateRemarks Config that consumers can pass to the Elasticsearch JS client is complex and includes @@ -130,7 +131,10 @@ export function parseElasticsearchClientConfig( protocol: uri.protocol, path: uri.pathname, query: uri.query, - headers: config.customHeaders, + headers: { + ...DEFAULT_HEADERS, + ...config.customHeaders, + }, }; if (needsAuth) { diff --git a/src/core/server/http/http_server.mocks.ts b/src/core/server/http/http_server.mocks.ts index 6d096b76263b5..6aad232cf42b6 100644 --- a/src/core/server/http/http_server.mocks.ts +++ b/src/core/server/http/http_server.mocks.ts @@ -68,7 +68,7 @@ function createKibanaRequestMock

({ routeAuthRequired, validation = {}, kibanaRouteOptions = { xsrfRequired: true }, - kibanaRequestState = { requestId: '123' }, + kibanaRequestState = { requestId: '123', requestUuid: '123e4567-e89b-12d3-a456-426614174000' }, auth = { isAuthenticated: true }, }: RequestFixtureOptions = {}) { const queryString = stringify(query, { sort: false }); @@ -175,6 +175,7 @@ type ToolkitMock = jest.Mocked { return { + render: jest.fn(), next: jest.fn(), rewriteUrl: jest.fn(), }; diff --git a/src/core/server/http/http_server.ts b/src/core/server/http/http_server.ts index 7609f23fe0c51..2440f2b1da0bd 100644 --- a/src/core/server/http/http_server.ts +++ b/src/core/server/http/http_server.ts @@ -19,6 +19,7 @@ import { Server } from 'hapi'; import HapiStaticFiles from 'inert'; import url from 'url'; +import uuid from 'uuid'; import { Logger, LoggerFactory } from '../logging'; import { HttpConfig } from './http_config'; @@ -315,6 +316,7 @@ export class HttpServer { request.app = { ...(request.app ?? {}), requestId: getRequestId(request, config.requestId), + requestUuid: uuid.v4(), } as KibanaRequestState; return responseToolkit.continue; }); diff --git a/src/core/server/http/http_service.mock.ts b/src/core/server/http/http_service.mock.ts index f81708145edc4..df837dc35505a 100644 --- a/src/core/server/http/http_service.mock.ts +++ b/src/core/server/http/http_service.mock.ts @@ -198,6 +198,7 @@ const createAuthToolkitMock = (): jest.Mocked => ({ }); const createOnPreResponseToolkitMock = (): jest.Mocked => ({ + render: jest.fn(), next: jest.fn(), }); diff --git a/src/core/server/http/index.ts b/src/core/server/http/index.ts index 7513e60966085..cb842b2f60268 100644 --- a/src/core/server/http/index.ts +++ b/src/core/server/http/index.ts @@ -83,6 +83,7 @@ export { OnPreAuthHandler, OnPreAuthToolkit } from './lifecycle/on_pre_auth'; export { OnPreResponseHandler, OnPreResponseToolkit, + OnPreResponseRender, OnPreResponseExtensions, OnPreResponseInfo, } from './lifecycle/on_pre_response'; diff --git a/src/core/server/http/integration_tests/lifecycle.test.ts b/src/core/server/http/integration_tests/lifecycle.test.ts index b9548bf7a8d70..59090d101acbc 100644 --- a/src/core/server/http/integration_tests/lifecycle.test.ts +++ b/src/core/server/http/integration_tests/lifecycle.test.ts @@ -1286,6 +1286,67 @@ describe('OnPreResponse', () => { expect(requestBody).toStrictEqual({}); }); + + it('supports rendering a different response body', async () => { + const { registerOnPreResponse, server: innerServer, createRouter } = await server.setup( + setupDeps + ); + const router = createRouter('/'); + + router.get({ path: '/', validate: false }, (context, req, res) => { + return res.ok({ + headers: { + 'Original-Header-A': 'A', + }, + body: 'original', + }); + }); + + registerOnPreResponse((req, res, t) => { + return t.render({ body: 'overridden' }); + }); + + await server.start(); + + const result = await supertest(innerServer.listener).get('/').expect(200, 'overridden'); + + expect(result.header['original-header-a']).toBe('A'); + }); + + it('supports rendering a different response body + headers', async () => { + const { registerOnPreResponse, server: innerServer, createRouter } = await server.setup( + setupDeps + ); + const router = createRouter('/'); + + router.get({ path: '/', validate: false }, (context, req, res) => { + return res.ok({ + headers: { + 'Original-Header-A': 'A', + 'Original-Header-B': 'B', + }, + body: 'original', + }); + }); + + registerOnPreResponse((req, res, t) => { + return t.render({ + headers: { + 'Original-Header-A': 'AA', + 'New-Header-C': 'C', + }, + body: 'overridden', + }); + }); + + await server.start(); + + const result = await supertest(innerServer.listener).get('/').expect(200, 'overridden'); + + expect(result.header['original-header-a']).toBe('AA'); + expect(result.header['original-header-b']).toBe('B'); + expect(result.header['new-header-c']).toBe('C'); + }); }); describe('run interceptors in the right order', () => { diff --git a/src/core/server/http/integration_tests/request.test.ts b/src/core/server/http/integration_tests/request.test.ts index 0727ff848c189..0170e94867c06 100644 --- a/src/core/server/http/integration_tests/request.test.ts +++ b/src/core/server/http/integration_tests/request.test.ts @@ -16,6 +16,11 @@ * specific language governing permissions and limitations * under the License. */ + +jest.mock('uuid', () => ({ + v4: jest.fn().mockReturnValue('xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'), +})); + import supertest from 'supertest'; import { HttpService } from '../http_service'; @@ -308,4 +313,20 @@ describe('KibanaRequest', () => { expect(resp3.body).toEqual({ requestId: 'gamma' }); }); }); + + describe('request uuid', () => { + it('generates a UUID', async () => { + const { server: innerServer, createRouter } = await server.setup(setupDeps); + const router = createRouter('/'); + router.get({ path: '/', validate: false }, async (context, req, res) => { + return res.ok({ body: { requestUuid: req.uuid } }); + }); + await server.start(); + + const st = supertest(innerServer.listener); + + const resp1 = await st.get('/').expect(200); + expect(resp1.body.requestUuid).toBe('xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'); + }); + }); }); diff --git a/src/core/server/http/lifecycle/on_pre_response.ts b/src/core/server/http/lifecycle/on_pre_response.ts index 4d1b53313a51f..37dddf4dd4767 100644 --- a/src/core/server/http/lifecycle/on_pre_response.ts +++ b/src/core/server/http/lifecycle/on_pre_response.ts @@ -17,16 +17,23 @@ * under the License. */ -import { Lifecycle, Request, ResponseToolkit as HapiResponseToolkit } from 'hapi'; +import { Lifecycle, Request, ResponseObject, ResponseToolkit as HapiResponseToolkit } from 'hapi'; import Boom from 'boom'; import { Logger } from '../../logging'; import { HapiResponseAdapter, KibanaRequest, ResponseHeaders } from '../router'; enum ResultType { + render = 'render', next = 'next', } +interface Render { + type: ResultType.render; + body: string; + headers?: ResponseHeaders; +} + interface Next { type: ResultType.next; headers?: ResponseHeaders; @@ -35,7 +42,18 @@ interface Next { /** * @internal */ -type OnPreResponseResult = Next; +type OnPreResponseResult = Render | Next; + +/** + * Additional data to extend a response when rendering a new body + * @public + */ +export interface OnPreResponseRender { + /** additional headers to attach to the response */ + headers?: ResponseHeaders; + /** the body to use in the response */ + body: string; +} /** * Additional data to extend a response. @@ -55,6 +73,12 @@ export interface OnPreResponseInfo { } const preResponseResult = { + render(responseRender: OnPreResponseRender): OnPreResponseResult { + return { type: ResultType.render, body: responseRender.body, headers: responseRender?.headers }; + }, + isRender(result: OnPreResponseResult): result is Render { + return result && result.type === ResultType.render; + }, next(responseExtensions?: OnPreResponseExtensions): OnPreResponseResult { return { type: ResultType.next, headers: responseExtensions?.headers }; }, @@ -68,11 +92,14 @@ const preResponseResult = { * @public */ export interface OnPreResponseToolkit { + /** To override the response with a different body */ + render: (responseRender: OnPreResponseRender) => OnPreResponseResult; /** To pass request to the next handler */ next: (responseExtensions?: OnPreResponseExtensions) => OnPreResponseResult; } const toolkit: OnPreResponseToolkit = { + render: preResponseResult.render, next: preResponseResult.next, }; @@ -106,26 +133,36 @@ export function adoptToHapiOnPreResponseFormat(fn: OnPreResponseHandler, log: Lo : response.statusCode; const result = await fn(KibanaRequest.from(request), { statusCode }, toolkit); - if (!preResponseResult.isNext(result)) { + + if (preResponseResult.isNext(result)) { + if (result.headers) { + if (isBoom(response)) { + findHeadersIntersection(response.output.headers, result.headers, log); + // hapi wraps all error response in Boom object internally + response.output.headers = { + ...response.output.headers, + ...(result.headers as any), // hapi types don't specify string[] as valid value + }; + } else { + findHeadersIntersection(response.headers, result.headers, log); + setHeaders(response, result.headers); + } + } + } else if (preResponseResult.isRender(result)) { + const overriddenResponse = responseToolkit.response(result.body).code(statusCode); + + const originalHeaders = isBoom(response) ? response.output.headers : response.headers; + setHeaders(overriddenResponse, originalHeaders); + if (result.headers) { + setHeaders(overriddenResponse, result.headers); + } + + return overriddenResponse; + } else { throw new Error( `Unexpected result from OnPreResponse. Expected OnPreResponseResult, but given: ${result}.` ); } - if (result.headers) { - if (isBoom(response)) { - findHeadersIntersection(response.output.headers, result.headers, log); - // hapi wraps all error response in Boom object internally - response.output.headers = { - ...response.output.headers, - ...(result.headers as any), // hapi types don't specify string[] as valid value - }; - } else { - findHeadersIntersection(response.headers, result.headers, log); - for (const [headerName, headerValue] of Object.entries(result.headers)) { - response.header(headerName, headerValue as any); // hapi types don't specify string[] as valid value - } - } - } } } catch (error) { log.error(error); @@ -140,6 +177,12 @@ function isBoom(response: any): response is Boom { return response instanceof Boom; } +function setHeaders(response: ResponseObject, headers: ResponseHeaders) { + for (const [headerName, headerValue] of Object.entries(headers)) { + response.header(headerName, headerValue as any); // hapi types don't specify string[] as valid value + } +} + // NOTE: responseHeaders contains not a full list of response headers, but only explicitly set on a response object. // any headers added by hapi internally, like `content-type`, `content-length`, etc. are not present here. function findHeadersIntersection( diff --git a/src/core/server/http/router/request.test.ts b/src/core/server/http/router/request.test.ts index e741121f3d70c..0bf81a7aca852 100644 --- a/src/core/server/http/router/request.test.ts +++ b/src/core/server/http/router/request.test.ts @@ -55,6 +55,34 @@ describe('KibanaRequest', () => { }); }); + describe('uuid property', () => { + it('uses the request.app.requestUuid property if present', () => { + const request = httpServerMock.createRawRequest({ + app: { requestUuid: '123e4567-e89b-12d3-a456-426614174000' }, + }); + const kibanaRequest = KibanaRequest.from(request); + expect(kibanaRequest.uuid).toEqual('123e4567-e89b-12d3-a456-426614174000'); + }); + + it('generates a new UUID if request.app property is not present', () => { + // Undefined app property + const request = httpServerMock.createRawRequest({ + app: undefined, + }); + const kibanaRequest = KibanaRequest.from(request); + expect(kibanaRequest.uuid).toEqual('xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'); + }); + + it('generates a new UUID if request.app.requestUuid property is not present', () => { + // Undefined app.requestUuid property + const request = httpServerMock.createRawRequest({ + app: {}, + }); + const kibanaRequest = KibanaRequest.from(request); + expect(kibanaRequest.uuid).toEqual('xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'); + }); + }); + describe('get all headers', () => { it('returns all headers', () => { const request = httpServerMock.createRawRequest({ diff --git a/src/core/server/http/router/request.ts b/src/core/server/http/router/request.ts index e04f8585981b5..903eb75022df3 100644 --- a/src/core/server/http/router/request.ts +++ b/src/core/server/http/router/request.ts @@ -44,6 +44,7 @@ export interface KibanaRouteOptions extends RouteOptionsApp { */ export interface KibanaRequestState extends ApplicationState { requestId: string; + requestUuid: string; } /** @@ -152,6 +153,14 @@ export class KibanaRequest< * per request. */ public readonly id: string; + /** + * A UUID to identify this request. + * + * @remarks + * This value is NOT sourced from the incoming request's `X-Opaque-Id` header. it + * is always a UUID uniquely identifying the request. + */ + public readonly uuid: string; /** a WHATWG URL standard object. */ public readonly url: Url; /** matched route details */ @@ -189,10 +198,11 @@ export class KibanaRequest< // until that time we have to expose all the headers private readonly withoutSecretHeaders: boolean ) { - // The `requestId` property will not be populated for requests that are 'faked' by internal systems that leverage + // The `requestId` and `requestUuid` properties will not be populated for requests that are 'faked' by internal systems that leverage // KibanaRequest in conjunction with scoped Elaticcsearch and SavedObjectsClient in order to pass credentials. - // In these cases, the id defaults to a newly generated UUID. + // In these cases, the ids default to a newly generated UUID. this.id = (request.app as KibanaRequestState | undefined)?.requestId ?? uuid.v4(); + this.uuid = (request.app as KibanaRequestState | undefined)?.requestUuid ?? uuid.v4(); this.url = request.url; this.headers = deepFreeze({ ...request.headers }); diff --git a/src/core/server/index.ts b/src/core/server/index.ts index e136c699f7246..fc091bd17bdf4 100644 --- a/src/core/server/index.ts +++ b/src/core/server/index.ts @@ -64,6 +64,18 @@ import { MetricsServiceSetup, MetricsServiceStart } from './metrics'; import { StatusServiceSetup } from './status'; import { Auditor, AuditTrailSetup, AuditTrailStart } from './audit_trail'; import { AppenderConfigType, appendersSchema, LoggingServiceSetup } from './logging'; +import { CoreUsageDataStart } from './core_usage_data'; + +// Because of #79265 we need to explicity import, then export these types for +// scripts/telemetry_check.js to work as expected +import { + CoreUsageData, + CoreConfigUsageData, + CoreEnvironmentUsageData, + CoreServicesUsageData, +} from './core_usage_data'; + +export { CoreUsageData, CoreConfigUsageData, CoreEnvironmentUsageData, CoreServicesUsageData }; export { AuditableEvent, Auditor, AuditorFactory, AuditTrailSetup } from './audit_trail'; export { bootstrap } from './bootstrap'; @@ -161,6 +173,7 @@ export { OnPostAuthToolkit, OnPreResponseHandler, OnPreResponseToolkit, + OnPreResponseRender, OnPreResponseExtensions, OnPreResponseInfo, RedirectResponseOptions, @@ -339,14 +352,7 @@ export { SavedObjectsMigrationVersion, } from './types'; -export { - LegacyServiceSetupDeps, - LegacyServiceStartDeps, - LegacyServiceDiscoverPlugins, - LegacyConfig, - LegacyUiExports, - LegacyInternals, -} from './legacy'; +export { LegacyServiceSetupDeps, LegacyServiceStartDeps, LegacyConfig } from './legacy'; export { CoreStatus, @@ -356,6 +362,8 @@ export { StatusServiceSetup, } from './status'; +export { CoreUsageDataStart } from './core_usage_data'; + /** * Plugin specific context passed to a route handler. * @@ -463,6 +471,8 @@ export interface CoreStart { uiSettings: UiSettingsServiceStart; /** {@link AuditTrailSetup} */ auditTrail: AuditTrailStart; + /** @internal {@link CoreUsageDataStart} */ + coreUsageData: CoreUsageDataStart; } export { diff --git a/src/core/server/internal_types.ts b/src/core/server/internal_types.ts index f5a5edffb0a74..ce58348a14153 100644 --- a/src/core/server/internal_types.ts +++ b/src/core/server/internal_types.ts @@ -39,6 +39,7 @@ import { InternalHttpResourcesSetup } from './http_resources'; import { InternalStatusServiceSetup } from './status'; import { AuditTrailSetup, AuditTrailStart } from './audit_trail'; import { InternalLoggingServiceSetup } from './logging'; +import { CoreUsageDataStart } from './core_usage_data'; /** @internal */ export interface InternalCoreSetup { @@ -68,6 +69,7 @@ export interface InternalCoreStart { savedObjects: InternalSavedObjectsServiceStart; uiSettings: InternalUiSettingsServiceStart; auditTrail: AuditTrailStart; + coreUsageData: CoreUsageDataStart; } /** diff --git a/src/core/server/legacy/config/ensure_valid_configuration.test.ts b/src/core/server/legacy/config/ensure_valid_configuration.test.ts index 702840b8a0a6a..700fe69954655 100644 --- a/src/core/server/legacy/config/ensure_valid_configuration.test.ts +++ b/src/core/server/legacy/config/ensure_valid_configuration.test.ts @@ -39,17 +39,12 @@ describe('ensureValidConfiguration', () => { configService as any, { settings: 'settings', - pluginSpecs: 'pluginSpecs', - disabledPluginSpecs: 'disabledPluginSpecs', - pluginExtendedConfig: 'pluginExtendedConfig', - uiExports: 'uiExports', + legacyConfig: 'pluginExtendedConfig', } as any ); expect(getUnusedConfigKeys).toHaveBeenCalledTimes(1); expect(getUnusedConfigKeys).toHaveBeenCalledWith({ coreHandledConfigPaths: ['core', 'elastic'], - pluginSpecs: 'pluginSpecs', - disabledPluginSpecs: 'disabledPluginSpecs', settings: 'settings', legacyConfig: 'pluginExtendedConfig', }); diff --git a/src/core/server/legacy/config/ensure_valid_configuration.ts b/src/core/server/legacy/config/ensure_valid_configuration.ts index 5cd1603ea65fb..34f98b9b3a795 100644 --- a/src/core/server/legacy/config/ensure_valid_configuration.ts +++ b/src/core/server/legacy/config/ensure_valid_configuration.ts @@ -19,19 +19,17 @@ import { getUnusedConfigKeys } from './get_unused_config_keys'; import { ConfigService } from '../../config'; -import { LegacyServiceDiscoverPlugins } from '../types'; import { CriticalError } from '../../errors'; +import { LegacyServiceSetupConfig } from '../types'; export async function ensureValidConfiguration( configService: ConfigService, - { pluginSpecs, disabledPluginSpecs, pluginExtendedConfig, settings }: LegacyServiceDiscoverPlugins + { legacyConfig, settings }: LegacyServiceSetupConfig ) { const unusedConfigKeys = await getUnusedConfigKeys({ coreHandledConfigPaths: await configService.getUsedPaths(), - pluginSpecs, - disabledPluginSpecs, settings, - legacyConfig: pluginExtendedConfig, + legacyConfig, }); if (unusedConfigKeys.length > 0) { diff --git a/src/core/server/legacy/config/get_unused_config_keys.test.ts b/src/core/server/legacy/config/get_unused_config_keys.test.ts index f8506b5744030..6ce69fca0270a 100644 --- a/src/core/server/legacy/config/get_unused_config_keys.test.ts +++ b/src/core/server/legacy/config/get_unused_config_keys.test.ts @@ -17,7 +17,7 @@ * under the License. */ -import { LegacyPluginSpec, LegacyConfig, LegacyVars } from '../types'; +import { LegacyConfig, LegacyVars } from '../types'; import { getUnusedConfigKeys } from './get_unused_config_keys'; describe('getUnusedConfigKeys', () => { @@ -35,8 +35,6 @@ describe('getUnusedConfigKeys', () => { expect( await getUnusedConfigKeys({ coreHandledConfigPaths: [], - pluginSpecs: [], - disabledPluginSpecs: [], settings: {}, legacyConfig: getConfig(), }) @@ -47,8 +45,6 @@ describe('getUnusedConfigKeys', () => { expect( await getUnusedConfigKeys({ coreHandledConfigPaths: [], - pluginSpecs: [], - disabledPluginSpecs: [], settings: { presentInBoth: true, alsoInBoth: 'someValue', @@ -65,8 +61,6 @@ describe('getUnusedConfigKeys', () => { expect( await getUnusedConfigKeys({ coreHandledConfigPaths: [], - pluginSpecs: [], - disabledPluginSpecs: [], settings: { presentInBoth: true, }, @@ -82,8 +76,6 @@ describe('getUnusedConfigKeys', () => { expect( await getUnusedConfigKeys({ coreHandledConfigPaths: [], - pluginSpecs: [], - disabledPluginSpecs: [], settings: { presentInBoth: true, onlyInSetting: 'value', @@ -99,8 +91,6 @@ describe('getUnusedConfigKeys', () => { expect( await getUnusedConfigKeys({ coreHandledConfigPaths: [], - pluginSpecs: [], - disabledPluginSpecs: [], settings: { elasticsearch: { username: 'foo', @@ -121,8 +111,6 @@ describe('getUnusedConfigKeys', () => { expect( await getUnusedConfigKeys({ coreHandledConfigPaths: [], - pluginSpecs: [], - disabledPluginSpecs: [], settings: { env: 'development', }, @@ -139,8 +127,6 @@ describe('getUnusedConfigKeys', () => { expect( await getUnusedConfigKeys({ coreHandledConfigPaths: [], - pluginSpecs: [], - disabledPluginSpecs: [], settings: { prop: ['a', 'b', 'c'], }, @@ -152,40 +138,10 @@ describe('getUnusedConfigKeys', () => { }); }); - it('ignores config for plugins that are disabled', async () => { - expect( - await getUnusedConfigKeys({ - coreHandledConfigPaths: [], - pluginSpecs: [], - disabledPluginSpecs: [ - ({ - id: 'foo', - getConfigPrefix: () => 'foo.bar', - } as unknown) as LegacyPluginSpec, - ], - settings: { - foo: { - bar: { - unused: true, - }, - }, - plugin: { - missingProp: false, - }, - }, - legacyConfig: getConfig({ - prop: 'a', - }), - }) - ).toEqual(['plugin.missingProp']); - }); - it('ignores properties managed by the new platform', async () => { expect( await getUnusedConfigKeys({ coreHandledConfigPaths: ['core', 'foo.bar'], - pluginSpecs: [], - disabledPluginSpecs: [], settings: { core: { prop: 'value', @@ -204,8 +160,6 @@ describe('getUnusedConfigKeys', () => { expect( await getUnusedConfigKeys({ coreHandledConfigPaths: ['core', 'array'], - pluginSpecs: [], - disabledPluginSpecs: [], settings: { core: { prop: 'value', diff --git a/src/core/server/legacy/config/get_unused_config_keys.ts b/src/core/server/legacy/config/get_unused_config_keys.ts index c15c3b270df05..5bbe169033e39 100644 --- a/src/core/server/legacy/config/get_unused_config_keys.ts +++ b/src/core/server/legacy/config/get_unused_config_keys.ts @@ -19,30 +19,20 @@ import { difference } from 'lodash'; import { getFlattenedObject } from '@kbn/std'; -import { unset } from '../../../../legacy/utils'; import { hasConfigPathIntersection } from '../../config'; -import { LegacyPluginSpec, LegacyConfig, LegacyVars } from '../types'; +import { LegacyConfig, LegacyVars } from '../types'; const getFlattenedKeys = (object: object) => Object.keys(getFlattenedObject(object)); export async function getUnusedConfigKeys({ coreHandledConfigPaths, - pluginSpecs, - disabledPluginSpecs, settings, legacyConfig, }: { coreHandledConfigPaths: string[]; - pluginSpecs: LegacyPluginSpec[]; - disabledPluginSpecs: LegacyPluginSpec[]; settings: LegacyVars; legacyConfig: LegacyConfig; }) { - // remove config values from disabled plugins - for (const spec of disabledPluginSpecs) { - unset(settings, spec.getConfigPrefix()); - } - const inputKeys = getFlattenedKeys(settings); const appliedKeys = getFlattenedKeys(legacyConfig.get()); diff --git a/src/core/server/legacy/index.ts b/src/core/server/legacy/index.ts index 6b0963e3129c6..1a0bc8955be0f 100644 --- a/src/core/server/legacy/index.ts +++ b/src/core/server/legacy/index.ts @@ -20,8 +20,6 @@ /** @internal */ export { ensureValidConfiguration } from './config'; /** @internal */ -export { LegacyInternals } from './legacy_internals'; -/** @internal */ export { LegacyService, ILegacyService } from './legacy_service'; /** @internal */ export * from './types'; diff --git a/src/core/server/legacy/legacy_internals.test.ts b/src/core/server/legacy/legacy_internals.test.ts deleted file mode 100644 index 935e36a989a0c..0000000000000 --- a/src/core/server/legacy/legacy_internals.test.ts +++ /dev/null @@ -1,211 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { Server } from 'hapi'; - -import { configMock } from '../config/mocks'; -import { httpServiceMock } from '../http/http_service.mock'; -import { httpServerMock } from '../http/http_server.mocks'; -import { findLegacyPluginSpecsMock } from './legacy_service.test.mocks'; -import { LegacyInternals } from './legacy_internals'; -import { ILegacyInternals, LegacyConfig, LegacyVars, LegacyUiExports } from './types'; - -function varsProvider(vars: LegacyVars, configValue?: any) { - return { - fn: jest.fn().mockReturnValue(vars), - pluginSpec: { - readConfigValue: jest.fn().mockReturnValue(configValue), - }, - }; -} - -describe('LegacyInternals', () => { - describe('getInjectedUiAppVars()', () => { - let uiExports: LegacyUiExports; - let config: LegacyConfig; - let server: Server; - let legacyInternals: ILegacyInternals; - - beforeEach(async () => { - uiExports = findLegacyPluginSpecsMock().uiExports; - config = configMock.create() as any; - server = httpServiceMock.createInternalSetupContract().server; - legacyInternals = new LegacyInternals(uiExports, config, server); - }); - - it('gets with no injectors', async () => { - await expect(legacyInternals.getInjectedUiAppVars('core')).resolves.toMatchInlineSnapshot( - `Object {}` - ); - }); - - it('gets with no matching injectors', async () => { - const injector = jest.fn().mockResolvedValue({ not: 'core' }); - legacyInternals.injectUiAppVars('not-core', injector); - - await expect(legacyInternals.getInjectedUiAppVars('core')).resolves.toMatchInlineSnapshot( - `Object {}` - ); - expect(injector).not.toHaveBeenCalled(); - }); - - it('gets with single matching injector', async () => { - const injector = jest.fn().mockResolvedValue({ is: 'core' }); - legacyInternals.injectUiAppVars('core', injector); - - await expect(legacyInternals.getInjectedUiAppVars('core')).resolves.toMatchInlineSnapshot(` - Object { - "is": "core", - } - `); - expect(injector).toHaveBeenCalled(); - }); - - it('gets with multiple matching injectors', async () => { - const injectors = [ - jest.fn().mockResolvedValue({ is: 'core' }), - jest.fn().mockReturnValue({ sync: 'injector' }), - jest.fn().mockResolvedValue({ is: 'merged-core' }), - ]; - - injectors.forEach((injector) => legacyInternals.injectUiAppVars('core', injector)); - - await expect(legacyInternals.getInjectedUiAppVars('core')).resolves.toMatchInlineSnapshot(` - Object { - "is": "merged-core", - "sync": "injector", - } - `); - expect(injectors[0]).toHaveBeenCalled(); - expect(injectors[1]).toHaveBeenCalled(); - expect(injectors[2]).toHaveBeenCalled(); - }); - }); - - describe('getVars()', () => { - let uiExports: LegacyUiExports; - let config: LegacyConfig; - let server: Server; - let legacyInternals: LegacyInternals; - - beforeEach(async () => { - uiExports = findLegacyPluginSpecsMock().uiExports; - config = configMock.create() as any; - server = httpServiceMock.createInternalSetupContract().server; - legacyInternals = new LegacyInternals(uiExports, config, server); - }); - - it('gets: no default injectors, no injected vars replacers, no ui app injectors, no inject arg', async () => { - const vars = await legacyInternals.getVars('core', httpServerMock.createRawRequest()); - - expect(vars).toMatchInlineSnapshot(`Object {}`); - }); - - it('gets: with default injectors, no injected vars replacers, no ui app injectors, no inject arg', async () => { - uiExports.defaultInjectedVarProviders = [ - varsProvider({ alpha: 'alpha' }), - varsProvider({ gamma: 'gamma' }), - varsProvider({ alpha: 'beta' }), - ]; - - const vars = await legacyInternals.getVars('core', httpServerMock.createRawRequest()); - - expect(vars).toMatchInlineSnapshot(` - Object { - "alpha": "beta", - "gamma": "gamma", - } - `); - }); - - it('gets: no default injectors, with injected vars replacers, with ui app injectors, no inject arg', async () => { - uiExports.injectedVarsReplacers = [ - jest.fn(async (vars) => ({ ...vars, added: 'key' })), - jest.fn((vars) => vars), - jest.fn((vars) => ({ replaced: 'all' })), - jest.fn(async (vars) => ({ ...vars, added: 'last-key' })), - ]; - - const request = httpServerMock.createRawRequest(); - const vars = await legacyInternals.getVars('core', request); - - expect(vars).toMatchInlineSnapshot(` - Object { - "added": "last-key", - "replaced": "all", - } - `); - }); - - it('gets: no default injectors, no injected vars replacers, with ui app injectors, no inject arg', async () => { - legacyInternals.injectUiAppVars('core', async () => ({ is: 'core' })); - legacyInternals.injectUiAppVars('core', () => ({ sync: 'injector' })); - legacyInternals.injectUiAppVars('core', async () => ({ is: 'merged-core' })); - - const vars = await legacyInternals.getVars('core', httpServerMock.createRawRequest()); - - expect(vars).toMatchInlineSnapshot(` - Object { - "is": "merged-core", - "sync": "injector", - } - `); - }); - - it('gets: no default injectors, no injected vars replacers, no ui app injectors, with inject arg', async () => { - const vars = await legacyInternals.getVars('core', httpServerMock.createRawRequest(), { - injected: 'arg', - }); - - expect(vars).toMatchInlineSnapshot(` - Object { - "injected": "arg", - } - `); - }); - - it('gets: with default injectors, with injected vars replacers, with ui app injectors, with inject arg', async () => { - uiExports.defaultInjectedVarProviders = [ - varsProvider({ alpha: 'alpha' }), - varsProvider({ gamma: 'gamma' }), - varsProvider({ alpha: 'beta' }), - ]; - uiExports.injectedVarsReplacers = [jest.fn(async (vars) => ({ ...vars, gamma: 'delta' }))]; - - legacyInternals.injectUiAppVars('core', async () => ({ is: 'core' })); - legacyInternals.injectUiAppVars('core', () => ({ sync: 'injector' })); - legacyInternals.injectUiAppVars('core', async () => ({ is: 'merged-core' })); - - const vars = await legacyInternals.getVars('core', httpServerMock.createRawRequest(), { - injected: 'arg', - sync: 'arg', - }); - - expect(vars).toMatchInlineSnapshot(` - Object { - "alpha": "beta", - "gamma": "delta", - "injected": "arg", - "is": "merged-core", - "sync": "arg", - } - `); - }); - }); -}); diff --git a/src/core/server/legacy/legacy_internals.ts b/src/core/server/legacy/legacy_internals.ts deleted file mode 100644 index 628ca4ed12f6b..0000000000000 --- a/src/core/server/legacy/legacy_internals.ts +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { Server } from 'hapi'; - -import { KibanaRequest, LegacyRequest } from '../http'; -import { ensureRawRequest } from '../http/router'; -import { mergeVars } from './merge_vars'; -import { ILegacyInternals, LegacyVars, VarsInjector, LegacyConfig, LegacyUiExports } from './types'; - -/** - * @internal - * @deprecated - */ -export class LegacyInternals implements ILegacyInternals { - private readonly injectors = new Map>(); - private cachedDefaultVars?: LegacyVars; - - constructor( - private readonly uiExports: LegacyUiExports, - private readonly config: LegacyConfig, - private readonly server: Server - ) {} - - private get defaultVars(): LegacyVars { - if (this.cachedDefaultVars) { - return this.cachedDefaultVars; - } - - const { defaultInjectedVarProviders = [] } = this.uiExports; - - return (this.cachedDefaultVars = defaultInjectedVarProviders.reduce( - (vars, { fn, pluginSpec }) => - mergeVars(vars, fn(this.server, pluginSpec.readConfigValue(this.config, []))), - {} - )); - } - - private replaceVars(vars: LegacyVars, request: KibanaRequest | LegacyRequest) { - const { injectedVarsReplacers = [] } = this.uiExports; - - return injectedVarsReplacers.reduce( - async (injected, replacer) => - replacer(await injected, ensureRawRequest(request), this.server), - Promise.resolve(vars) - ); - } - - public injectUiAppVars(id: string, injector: VarsInjector) { - if (!this.injectors.has(id)) { - this.injectors.set(id, new Set()); - } - - this.injectors.get(id)!.add(injector); - } - - public getInjectedUiAppVars(id: string) { - return [...(this.injectors.get(id) || [])].reduce( - async (promise, injector) => ({ - ...(await promise), - ...(await injector()), - }), - Promise.resolve({}) - ); - } - - public async getVars( - id: string, - request: KibanaRequest | LegacyRequest, - injected: LegacyVars = {} - ) { - return this.replaceVars( - mergeVars(this.defaultVars, await this.getInjectedUiAppVars(id), injected), - request - ); - } -} diff --git a/src/core/server/legacy/legacy_service.mock.ts b/src/core/server/legacy/legacy_service.mock.ts index ab501bd6bb53b..781874f702cf8 100644 --- a/src/core/server/legacy/legacy_service.mock.ts +++ b/src/core/server/legacy/legacy_service.mock.ts @@ -18,26 +18,13 @@ */ import type { PublicMethodsOf } from '@kbn/utility-types'; import { LegacyService } from './legacy_service'; -import { LegacyConfig, LegacyServiceDiscoverPlugins, LegacyServiceSetupDeps } from './types'; +import { LegacyConfig, LegacyServiceSetupDeps } from './types'; type LegacyServiceMock = jest.Mocked & { legacyId: symbol }>; -const createDiscoverPluginsMock = (): LegacyServiceDiscoverPlugins => ({ - pluginSpecs: [], - uiExports: {}, - navLinks: [], - pluginExtendedConfig: { - get: jest.fn(), - has: jest.fn(), - set: jest.fn(), - }, - disabledPluginSpecs: [], - settings: {}, -}); - const createLegacyServiceMock = (): LegacyServiceMock => ({ legacyId: Symbol(), - discoverPlugins: jest.fn().mockResolvedValue(createDiscoverPluginsMock()), + setupLegacyConfig: jest.fn(), setup: jest.fn(), start: jest.fn(), stop: jest.fn(), @@ -52,6 +39,5 @@ const createLegacyConfigMock = (): jest.Mocked => ({ export const legacyServiceMock = { create: createLegacyServiceMock, createSetupContract: (deps: LegacyServiceSetupDeps) => createLegacyServiceMock().setup(deps), - createDiscoverPlugins: createDiscoverPluginsMock, createLegacyConfig: createLegacyConfigMock, }; diff --git a/src/core/server/legacy/legacy_service.test.mocks.ts b/src/core/server/legacy/legacy_service.test.mocks.ts deleted file mode 100644 index 9ad554d63add0..0000000000000 --- a/src/core/server/legacy/legacy_service.test.mocks.ts +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { LegacyVars } from './types'; - -export const findLegacyPluginSpecsMock = jest.fn().mockImplementation((settings: LegacyVars) => ({ - pluginSpecs: [], - pluginExtendedConfig: { - has: jest.fn(), - get: jest.fn().mockReturnValue(settings), - set: jest.fn(), - }, - disabledPluginSpecs: [], - uiExports: {}, - navLinks: [], -})); -jest.doMock('./plugins/find_legacy_plugin_specs', () => ({ - findLegacyPluginSpecs: findLegacyPluginSpecsMock, -})); - -export const logLegacyThirdPartyPluginDeprecationWarningMock = jest.fn(); -jest.doMock('./plugins/log_legacy_plugins_warning', () => ({ - logLegacyThirdPartyPluginDeprecationWarning: logLegacyThirdPartyPluginDeprecationWarningMock, -})); diff --git a/src/core/server/legacy/legacy_service.test.ts b/src/core/server/legacy/legacy_service.test.ts index a6fe95deb3979..57009f0d35c16 100644 --- a/src/core/server/legacy/legacy_service.test.ts +++ b/src/core/server/legacy/legacy_service.test.ts @@ -19,10 +19,6 @@ jest.mock('../../../legacy/server/kbn_server'); jest.mock('./cluster_manager'); -import { - findLegacyPluginSpecsMock, - logLegacyThirdPartyPluginDeprecationWarningMock, -} from './legacy_service.test.mocks'; import { BehaviorSubject, throwError } from 'rxjs'; import { REPO_ROOT } from '@kbn/dev-utils'; @@ -44,8 +40,7 @@ import { capabilitiesServiceMock } from '../capabilities/capabilities_service.mo import { httpResourcesMock } from '../http_resources/http_resources_service.mock'; import { setupMock as renderingServiceMock } from '../rendering/__mocks__/rendering_service'; import { environmentServiceMock } from '../environment/environment_service.mock'; -import { findLegacyPluginSpecs } from './plugins'; -import { LegacyVars, LegacyServiceSetupDeps, LegacyServiceStartDeps } from './types'; +import { LegacyServiceSetupDeps, LegacyServiceStartDeps } from './types'; import { LegacyService } from './legacy_service'; import { coreMock } from '../mocks'; import { statusServiceMock } from '../status/status_service.mock'; @@ -73,7 +68,6 @@ beforeEach(() => { configService = configServiceMock.create(); environmentSetup = environmentServiceMock.createSetupContract(); - findLegacyPluginSpecsMock.mockClear(); MockKbnServer.prototype.ready = jest.fn().mockReturnValue(Promise.resolve()); MockKbnServer.prototype.listen = jest.fn(); @@ -149,10 +143,10 @@ describe('once LegacyService is set up with connection info', () => { coreId, env, logger, - configService: configService as any, + configService, }); - await legacyService.discoverPlugins(); + await legacyService.setupLegacyConfig(); await legacyService.setup(setupDeps); await legacyService.start(startDeps); @@ -160,13 +154,14 @@ describe('once LegacyService is set up with connection info', () => { expect(MockKbnServer).toHaveBeenCalledWith( { path: { autoListen: true }, server: { autoListen: true } }, // Because of the mock, path also gets the value expect.objectContaining({ get: expect.any(Function) }), - expect.any(Object), - { disabledPluginSpecs: [], pluginSpecs: [], uiExports: {}, navLinks: [] } + expect.any(Object) + ); + expect(MockKbnServer.mock.calls[0][1].get()).toEqual( + expect.objectContaining({ + path: expect.objectContaining({ autoListen: true }), + server: expect.objectContaining({ autoListen: true }), + }) ); - expect(MockKbnServer.mock.calls[0][1].get()).toEqual({ - path: { autoListen: true }, - server: { autoListen: true }, - }); const [mockKbnServer] = MockKbnServer.mock.instances; expect(mockKbnServer.listen).toHaveBeenCalledTimes(1); @@ -182,7 +177,7 @@ describe('once LegacyService is set up with connection info', () => { logger, configService: configService as any, }); - await legacyService.discoverPlugins(); + await legacyService.setupLegacyConfig(); await legacyService.setup(setupDeps); await legacyService.start(startDeps); @@ -190,13 +185,12 @@ describe('once LegacyService is set up with connection info', () => { expect(MockKbnServer).toHaveBeenCalledWith( { path: { autoListen: false }, server: { autoListen: true } }, expect.objectContaining({ get: expect.any(Function) }), - expect.any(Object), - { disabledPluginSpecs: [], pluginSpecs: [], uiExports: {}, navLinks: [] } + expect.any(Object) ); - expect(MockKbnServer.mock.calls[0][1].get()).toEqual({ - path: { autoListen: false }, - server: { autoListen: true }, - }); + + const legacyConfig = MockKbnServer.mock.calls[0][1].get(); + expect(legacyConfig.path.autoListen).toBe(false); + expect(legacyConfig.server.autoListen).toBe(true); const [mockKbnServer] = MockKbnServer.mock.instances; expect(mockKbnServer.ready).toHaveBeenCalledTimes(1); @@ -214,7 +208,7 @@ describe('once LegacyService is set up with connection info', () => { configService: configService as any, }); - await legacyService.discoverPlugins(); + await legacyService.setupLegacyConfig(); await legacyService.setup(setupDeps); await expect(legacyService.start(startDeps)).rejects.toThrowErrorMatchingInlineSnapshot( `"something failed"` @@ -234,11 +228,11 @@ describe('once LegacyService is set up with connection info', () => { configService: configService as any, }); - await expect(legacyService.discoverPlugins()).rejects.toThrowErrorMatchingInlineSnapshot( + await expect(legacyService.setupLegacyConfig()).rejects.toThrowErrorMatchingInlineSnapshot( `"something failed"` ); await expect(legacyService.setup(setupDeps)).rejects.toThrowErrorMatchingInlineSnapshot( - `"Legacy service has not discovered legacy plugins yet. Ensure LegacyService.discoverPlugins() is called before LegacyService.setup()"` + `"Legacy config not initialized yet. Ensure LegacyService.setupLegacyConfig() is called before LegacyService.setup()"` ); await expect(legacyService.start(startDeps)).rejects.toThrowErrorMatchingInlineSnapshot( `"Legacy service is not setup yet."` @@ -255,7 +249,7 @@ describe('once LegacyService is set up with connection info', () => { logger, configService: configService as any, }); - await legacyService.discoverPlugins(); + await legacyService.setupLegacyConfig(); await legacyService.setup(setupDeps); await legacyService.start(startDeps); @@ -276,7 +270,7 @@ describe('once LegacyService is set up with connection info', () => { logger, configService: configService as any, }); - await legacyService.discoverPlugins(); + await legacyService.setupLegacyConfig(); await legacyService.setup(setupDeps); await legacyService.start(startDeps); @@ -301,7 +295,7 @@ describe('once LegacyService is set up with connection info', () => { logger, configService: configService as any, }); - await legacyService.discoverPlugins(); + await legacyService.setupLegacyConfig(); await legacyService.setup(setupDeps); await legacyService.start(startDeps); @@ -321,7 +315,7 @@ describe('once LegacyService is set up without connection info', () => { let legacyService: LegacyService; beforeEach(async () => { legacyService = new LegacyService({ coreId, env, logger, configService: configService as any }); - await legacyService.discoverPlugins(); + await legacyService.setupLegacyConfig(); await legacyService.setup(setupDeps); await legacyService.start(startDeps); }); @@ -331,13 +325,13 @@ describe('once LegacyService is set up without connection info', () => { expect(MockKbnServer).toHaveBeenCalledWith( { path: {}, server: { autoListen: true } }, expect.objectContaining({ get: expect.any(Function) }), - expect.any(Object), - { disabledPluginSpecs: [], pluginSpecs: [], uiExports: {}, navLinks: [] } + expect.any(Object) + ); + expect(MockKbnServer.mock.calls[0][1].get()).toEqual( + expect.objectContaining({ + server: expect.objectContaining({ autoListen: true }), + }) ); - expect(MockKbnServer.mock.calls[0][1].get()).toEqual({ - path: {}, - server: { autoListen: true }, - }); }); test('reconfigures logging configuration if new config is received.', async () => { @@ -375,7 +369,7 @@ describe('once LegacyService is set up in `devClusterMaster` mode', () => { configService: configService as any, }); - await devClusterLegacyService.discoverPlugins(); + await devClusterLegacyService.setupLegacyConfig(); await devClusterLegacyService.setup(setupDeps); await devClusterLegacyService.start(startDeps); @@ -404,7 +398,7 @@ describe('once LegacyService is set up in `devClusterMaster` mode', () => { configService: configService as any, }); - await devClusterLegacyService.discoverPlugins(); + await devClusterLegacyService.setupLegacyConfig(); await devClusterLegacyService.setup(setupDeps); await devClusterLegacyService.start(startDeps); @@ -434,50 +428,6 @@ describe('start', () => { }); }); -describe('#discoverPlugins()', () => { - it('calls findLegacyPluginSpecs with correct parameters', async () => { - const legacyService = new LegacyService({ - coreId, - env, - logger, - configService: configService as any, - }); - - await legacyService.discoverPlugins(); - expect(findLegacyPluginSpecs).toHaveBeenCalledTimes(1); - expect(findLegacyPluginSpecs).toHaveBeenCalledWith(expect.any(Object), logger, env.packageInfo); - }); - - it(`logs deprecations for legacy third party plugins`, async () => { - const pluginSpecs = [{ getId: () => 'pluginA' }, { getId: () => 'pluginB' }]; - findLegacyPluginSpecsMock.mockImplementation( - (settings) => - Promise.resolve({ - pluginSpecs, - pluginExtendedConfig: settings, - disabledPluginSpecs: [], - uiExports: {}, - navLinks: [], - }) as any - ); - - const legacyService = new LegacyService({ - coreId, - env, - logger, - configService: configService as any, - }); - - await legacyService.discoverPlugins(); - - expect(logLegacyThirdPartyPluginDeprecationWarningMock).toHaveBeenCalledTimes(1); - expect(logLegacyThirdPartyPluginDeprecationWarningMock).toHaveBeenCalledWith({ - specs: pluginSpecs, - log: expect.any(Object), - }); - }); -}); - test('Sets the server.uuid property on the legacy configuration', async () => { configService.atPath.mockReturnValue(new BehaviorSubject({ autoListen: true })); const legacyService = new LegacyService({ @@ -489,23 +439,8 @@ test('Sets the server.uuid property on the legacy configuration', async () => { environmentSetup.instanceUuid = 'UUID_FROM_SERVICE'; - const configSetMock = jest.fn(); - - findLegacyPluginSpecsMock.mockImplementation((settings: LegacyVars) => ({ - pluginSpecs: [], - pluginExtendedConfig: { - has: jest.fn(), - get: jest.fn().mockReturnValue(settings), - set: configSetMock, - }, - disabledPluginSpecs: [], - uiExports: {}, - navLinks: [], - })); - - await legacyService.discoverPlugins(); + const { legacyConfig } = await legacyService.setupLegacyConfig(); await legacyService.setup(setupDeps); - expect(configSetMock).toHaveBeenCalledTimes(1); - expect(configSetMock).toHaveBeenCalledWith('server.uuid', 'UUID_FROM_SERVICE'); + expect(legacyConfig.get('server.uuid')).toBe('UUID_FROM_SERVICE'); }); diff --git a/src/core/server/legacy/legacy_service.ts b/src/core/server/legacy/legacy_service.ts index 4dc22be2a9971..75e8ae6524920 100644 --- a/src/core/server/legacy/legacy_service.ts +++ b/src/core/server/legacy/legacy_service.ts @@ -16,11 +16,14 @@ * specific language governing permissions and limitations * under the License. */ -import type { PublicMethodsOf } from '@kbn/utility-types'; + import { combineLatest, ConnectableObservable, EMPTY, Observable, Subscription } from 'rxjs'; import { first, map, publishReplay, tap } from 'rxjs/operators'; - +import type { PublicMethodsOf } from '@kbn/utility-types'; import { PathConfigType } from '@kbn/utils'; + +// @ts-expect-error legacy config class +import { Config as LegacyConfigClass } from '../../../legacy/server/config'; import { CoreService } from '../../types'; import { Config } from '../config'; import { CoreContext } from '../core_context'; @@ -28,17 +31,7 @@ import { CspConfigType, config as cspConfig } from '../csp'; import { DevConfig, DevConfigType, config as devConfig } from '../dev'; import { BasePathProxyServer, HttpConfig, HttpConfigType, config as httpConfig } from '../http'; import { Logger } from '../logging'; -import { findLegacyPluginSpecs, logLegacyThirdPartyPluginDeprecationWarning } from './plugins'; -import { - ILegacyInternals, - LegacyServiceSetupDeps, - LegacyServiceStartDeps, - LegacyPlugins, - LegacyServiceDiscoverPlugins, - LegacyConfig, - LegacyVars, -} from './types'; -import { LegacyInternals } from './legacy_internals'; +import { LegacyServiceSetupDeps, LegacyServiceStartDeps, LegacyConfig, LegacyVars } from './types'; import { CoreSetup, CoreStart } from '..'; interface LegacyKbnServer { @@ -80,9 +73,7 @@ export class LegacyService implements CoreService { private setupDeps?: LegacyServiceSetupDeps; private update$?: ConnectableObservable<[Config, PathConfigType]>; private legacyRawConfig?: LegacyConfig; - private legacyPlugins?: LegacyPlugins; private settings?: LegacyVars; - public legacyInternals?: ILegacyInternals; constructor(private readonly coreContext: CoreContext) { const { logger, configService } = coreContext; @@ -97,11 +88,11 @@ export class LegacyService implements CoreService { ).pipe(map(([http, csp]) => new HttpConfig(http, csp))); } - public async discoverPlugins(): Promise { - this.update$ = combineLatest( + public async setupLegacyConfig() { + this.update$ = combineLatest([ this.coreContext.configService.getConfig$(), - this.coreContext.configService.atPath('path') - ).pipe( + this.coreContext.configService.atPath('path'), + ]).pipe( tap(([config, pathConfig]) => { if (this.kbnServer !== undefined) { this.kbnServer.applyLoggingConfiguration(getLegacyRawConfig(config, pathConfig)); @@ -120,74 +111,33 @@ export class LegacyService implements CoreService { ) .toPromise(); - const { - pluginSpecs, - pluginExtendedConfig, - disabledPluginSpecs, - uiExports, - navLinks, - } = await findLegacyPluginSpecs( - this.settings, - this.coreContext.logger, - this.coreContext.env.packageInfo - ); - - logLegacyThirdPartyPluginDeprecationWarning({ - specs: pluginSpecs, - log: this.log, - }); - - this.legacyPlugins = { - pluginSpecs, - disabledPluginSpecs, - uiExports, - navLinks, - }; - - this.legacyRawConfig = pluginExtendedConfig; - - // check for unknown uiExport types - if (uiExports.unknown && uiExports.unknown.length > 0) { - throw new Error( - `Unknown uiExport types: ${uiExports.unknown - .map(({ pluginSpec, type }) => `${type} from ${pluginSpec.getId()}`) - .join(', ')}` - ); - } + this.legacyRawConfig = LegacyConfigClass.withDefaultSchema(this.settings); return { - pluginSpecs, - disabledPluginSpecs, - uiExports, - navLinks, - pluginExtendedConfig, settings: this.settings, + legacyConfig: this.legacyRawConfig!, }; } public async setup(setupDeps: LegacyServiceSetupDeps) { this.log.debug('setting up legacy service'); - if (!this.legacyPlugins) { + if (!this.legacyRawConfig) { throw new Error( - 'Legacy service has not discovered legacy plugins yet. Ensure LegacyService.discoverPlugins() is called before LegacyService.setup()' + 'Legacy config not initialized yet. Ensure LegacyService.setupLegacyConfig() is called before LegacyService.setup()' ); } // propagate the instance uuid to the legacy config, as it was the legacy way to access it. this.legacyRawConfig!.set('server.uuid', setupDeps.core.environment.instanceUuid); + this.setupDeps = setupDeps; - this.legacyInternals = new LegacyInternals( - this.legacyPlugins.uiExports, - this.legacyRawConfig!, - setupDeps.core.http.server - ); } public async start(startDeps: LegacyServiceStartDeps) { const { setupDeps } = this; - if (!setupDeps || !this.legacyPlugins) { + if (!setupDeps || !this.legacyRawConfig) { throw new Error('Legacy service is not setup yet.'); } @@ -201,8 +151,7 @@ export class LegacyService implements CoreService { this.settings!, this.legacyRawConfig!, setupDeps, - startDeps, - this.legacyPlugins! + startDeps ); } } @@ -245,8 +194,7 @@ export class LegacyService implements CoreService { settings: LegacyVars, config: LegacyConfig, setupDeps: LegacyServiceSetupDeps, - startDeps: LegacyServiceStartDeps, - legacyPlugins: LegacyPlugins + startDeps: LegacyServiceStartDeps ) { const coreStart: CoreStart = { capabilities: startDeps.core.capabilities, @@ -269,6 +217,11 @@ export class LegacyService implements CoreService { }, uiSettings: { asScopedToClient: startDeps.core.uiSettings.asScopedToClient }, auditTrail: startDeps.core.auditTrail, + coreUsageData: { + getCoreUsageData: () => { + throw new Error('core.start.coreUsageData.getCoreUsageData is unsupported in legacy'); + }, + }, }; const router = setupDeps.core.http.createRouter('', this.legacyId); @@ -337,36 +290,26 @@ export class LegacyService implements CoreService { // eslint-disable-next-line @typescript-eslint/no-var-requires const KbnServer = require('../../../legacy/server/kbn_server'); - const kbnServer: LegacyKbnServer = new KbnServer( - settings, - config, - { - env: { - mode: this.coreContext.env.mode, - packageInfo: this.coreContext.env.packageInfo, - }, - setupDeps: { - core: coreSetup, - plugins: setupDeps.plugins, - }, - startDeps: { - core: coreStart, - plugins: startDeps.plugins, - }, - __internals: { - http: { - registerStaticDir: setupDeps.core.http.registerStaticDir, - }, - hapiServer: setupDeps.core.http.server, - uiPlugins: setupDeps.uiPlugins, - elasticsearch: setupDeps.core.elasticsearch, - rendering: setupDeps.core.rendering, - legacy: this.legacyInternals, - }, - logger: this.coreContext.logger, + const kbnServer: LegacyKbnServer = new KbnServer(settings, config, { + env: { + mode: this.coreContext.env.mode, + packageInfo: this.coreContext.env.packageInfo, }, - legacyPlugins - ); + setupDeps: { + core: coreSetup, + plugins: setupDeps.plugins, + }, + startDeps: { + core: coreStart, + plugins: startDeps.plugins, + }, + __internals: { + hapiServer: setupDeps.core.http.server, + uiPlugins: setupDeps.uiPlugins, + rendering: setupDeps.core.rendering, + }, + logger: this.coreContext.logger, + }); // The kbnWorkerType check is necessary to prevent the repl // from being started multiple times in different processes. diff --git a/src/core/server/legacy/plugins/collect_ui_exports.js b/src/core/server/legacy/plugins/collect_ui_exports.js deleted file mode 100644 index 842ab554d79d1..0000000000000 --- a/src/core/server/legacy/plugins/collect_ui_exports.js +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -// eslint-disable-next-line @kbn/eslint/no-restricted-paths -export { collectUiExports } from '../../../../legacy/ui/ui_exports/collect_ui_exports'; diff --git a/src/core/server/legacy/plugins/find_legacy_plugin_specs.ts b/src/core/server/legacy/plugins/find_legacy_plugin_specs.ts deleted file mode 100644 index cb4277b130a88..0000000000000 --- a/src/core/server/legacy/plugins/find_legacy_plugin_specs.ts +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { Observable, merge, forkJoin } from 'rxjs'; -import { toArray, tap, distinct, map } from 'rxjs/operators'; - -import { - findPluginSpecs, - defaultConfig, - // @ts-expect-error -} from '../../../../legacy/plugin_discovery/find_plugin_specs.js'; -// @ts-expect-error -import { collectUiExports as collectLegacyUiExports } from './collect_ui_exports'; - -import { LoggerFactory } from '../../logging'; -import { PackageInfo } from '../../config'; -import { LegacyUiExports, LegacyPluginSpec, LegacyPluginPack, LegacyConfig } from '../types'; - -export async function findLegacyPluginSpecs( - settings: unknown, - loggerFactory: LoggerFactory, - packageInfo: PackageInfo -) { - const configToMutate: LegacyConfig = defaultConfig(settings); - const { - pack$, - invalidDirectoryError$, - invalidPackError$, - otherError$, - deprecation$, - invalidVersionSpec$, - spec$, - disabledSpec$, - }: { - pack$: Observable; - invalidDirectoryError$: Observable<{ path: string }>; - invalidPackError$: Observable<{ path: string }>; - otherError$: Observable; - deprecation$: Observable<{ spec: LegacyPluginSpec; message: string }>; - invalidVersionSpec$: Observable; - spec$: Observable; - disabledSpec$: Observable; - } = findPluginSpecs(settings, configToMutate) as any; - - const logger = loggerFactory.get('legacy-plugins'); - - const log$ = merge( - pack$.pipe( - tap((definition) => { - const path = definition.getPath(); - logger.debug(`Found plugin at ${path}`, { path }); - }) - ), - - invalidDirectoryError$.pipe( - tap((error) => { - logger.warn(`Unable to scan directory for plugins "${error.path}"`, { - err: error, - dir: error.path, - }); - }) - ), - - invalidPackError$.pipe( - tap((error) => { - logger.warn(`Skipping non-plugin directory at ${error.path}`, { - path: error.path, - }); - }) - ), - - otherError$.pipe( - tap((error) => { - // rethrow unhandled errors, which will fail the server - throw error; - }) - ), - - invalidVersionSpec$.pipe( - map((spec) => { - const name = spec.getId(); - const pluginVersion = spec.getExpectedKibanaVersion(); - const kibanaVersion = packageInfo.version; - return `Plugin "${name}" was disabled because it expected Kibana version "${pluginVersion}", and found "${kibanaVersion}".`; - }), - distinct(), - tap((message) => { - logger.warn(message); - }) - ), - - deprecation$.pipe( - tap(({ spec, message }) => { - const deprecationLogger = loggerFactory.get( - 'plugins', - spec.getConfigPrefix(), - 'config', - 'deprecation' - ); - deprecationLogger.warn(message); - }) - ) - ); - - const [disabledPluginSpecs, pluginSpecs] = await forkJoin( - disabledSpec$.pipe(toArray()), - spec$.pipe(toArray()), - log$.pipe(toArray()) - ).toPromise(); - const uiExports: LegacyUiExports = collectLegacyUiExports(pluginSpecs); - - return { - disabledPluginSpecs, - pluginSpecs, - pluginExtendedConfig: configToMutate, - uiExports, - navLinks: [], - }; -} diff --git a/src/core/server/legacy/plugins/index.ts b/src/core/server/legacy/plugins/index.ts deleted file mode 100644 index 7ec5dbc1983ab..0000000000000 --- a/src/core/server/legacy/plugins/index.ts +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -export { findLegacyPluginSpecs } from './find_legacy_plugin_specs'; -export { logLegacyThirdPartyPluginDeprecationWarning } from './log_legacy_plugins_warning'; diff --git a/src/core/server/legacy/plugins/log_legacy_plugins_warning.test.ts b/src/core/server/legacy/plugins/log_legacy_plugins_warning.test.ts deleted file mode 100644 index 2317f1036ce42..0000000000000 --- a/src/core/server/legacy/plugins/log_legacy_plugins_warning.test.ts +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { loggerMock } from '../../logging/logger.mock'; -import { logLegacyThirdPartyPluginDeprecationWarning } from './log_legacy_plugins_warning'; -import { LegacyPluginSpec } from '../types'; - -const createPluginSpec = ({ id, path }: { id: string; path: string }): LegacyPluginSpec => { - return { - getId: () => id, - getExpectedKibanaVersion: () => 'kibana', - getConfigPrefix: () => 'plugin.config', - getPack: () => ({ - getPath: () => path, - }), - }; -}; - -describe('logLegacyThirdPartyPluginDeprecationWarning', () => { - let log: ReturnType; - - beforeEach(() => { - log = loggerMock.create(); - }); - - it('logs warning for third party plugins', () => { - logLegacyThirdPartyPluginDeprecationWarning({ - specs: [createPluginSpec({ id: 'plugin', path: '/some-external-path' })], - log, - }); - expect(log.warn).toHaveBeenCalledTimes(1); - expect(log.warn.mock.calls[0]).toMatchInlineSnapshot(` - Array [ - "Some installed third party plugin(s) [plugin] are using the legacy plugin format and will no longer work in a future Kibana release. Please refer to https://ela.st/kibana-breaking-changes-8-0 for a list of breaking changes and https://ela.st/kibana-platform-migration for documentation on how to migrate legacy plugins.", - ] - `); - }); - - it('lists all the deprecated plugins and only log once', () => { - logLegacyThirdPartyPluginDeprecationWarning({ - specs: [ - createPluginSpec({ id: 'pluginA', path: '/abs/path/to/pluginA' }), - createPluginSpec({ id: 'pluginB', path: '/abs/path/to/pluginB' }), - createPluginSpec({ id: 'pluginC', path: '/abs/path/to/pluginC' }), - ], - log, - }); - expect(log.warn).toHaveBeenCalledTimes(1); - expect(log.warn.mock.calls[0]).toMatchInlineSnapshot(` - Array [ - "Some installed third party plugin(s) [pluginA, pluginB, pluginC] are using the legacy plugin format and will no longer work in a future Kibana release. Please refer to https://ela.st/kibana-breaking-changes-8-0 for a list of breaking changes and https://ela.st/kibana-platform-migration for documentation on how to migrate legacy plugins.", - ] - `); - }); - - it('does not log warning for internal legacy plugins', () => { - logLegacyThirdPartyPluginDeprecationWarning({ - specs: [ - createPluginSpec({ - id: 'plugin', - path: '/absolute/path/to/kibana/src/legacy/core_plugins', - }), - createPluginSpec({ - id: 'plugin', - path: '/absolute/path/to/kibana/x-pack', - }), - ], - log, - }); - - expect(log.warn).not.toHaveBeenCalled(); - }); -}); diff --git a/src/core/server/legacy/plugins/log_legacy_plugins_warning.ts b/src/core/server/legacy/plugins/log_legacy_plugins_warning.ts deleted file mode 100644 index 4a4a1b1b0e60b..0000000000000 --- a/src/core/server/legacy/plugins/log_legacy_plugins_warning.ts +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { Logger } from '../../logging'; -import { LegacyPluginSpec } from '../types'; - -const internalPaths = ['/src/legacy/core_plugins', '/x-pack']; - -// Use shortened URLs so destinations can be updated if/when documentation moves -// All platform team members have access to edit these -const breakingChangesUrl = 'https://ela.st/kibana-breaking-changes-8-0'; -const migrationGuideUrl = 'https://ela.st/kibana-platform-migration'; - -export const logLegacyThirdPartyPluginDeprecationWarning = ({ - specs, - log, -}: { - specs: LegacyPluginSpec[]; - log: Logger; -}) => { - const thirdPartySpecs = specs.filter(isThirdPartyPluginSpec); - if (thirdPartySpecs.length > 0) { - const pluginIds = thirdPartySpecs.map((spec) => spec.getId()); - log.warn( - `Some installed third party plugin(s) [${pluginIds.join( - ', ' - )}] are using the legacy plugin format and will no longer work in a future Kibana release. ` + - `Please refer to ${breakingChangesUrl} for a list of breaking changes ` + - `and ${migrationGuideUrl} for documentation on how to migrate legacy plugins.` - ); - } -}; - -const isThirdPartyPluginSpec = (spec: LegacyPluginSpec): boolean => { - const pluginPath = spec.getPack().getPath(); - return !internalPaths.some((internalPath) => pluginPath.indexOf(internalPath) > -1); -}; diff --git a/src/core/server/legacy/types.ts b/src/core/server/legacy/types.ts index 1105308fd44cf..12bfddfff1961 100644 --- a/src/core/server/legacy/types.ts +++ b/src/core/server/legacy/types.ts @@ -17,10 +17,6 @@ * under the License. */ -import { Server } from 'hapi'; - -import { ChromeNavLink } from '../../public'; -import { KibanaRequest, LegacyRequest } from '../http'; import { InternalCoreSetup, InternalCoreStart } from '../internal_types'; import { PluginsServiceSetup, PluginsServiceStart, UiPlugins } from '../plugins'; import { InternalRenderingServiceSetup } from '../rendering'; @@ -50,91 +46,6 @@ export interface LegacyConfig { set(config: LegacyVars): void; } -/** - * @internal - * @deprecated - */ -export interface LegacyPluginPack { - getPath(): string; -} - -/** - * @internal - * @deprecated - */ -export interface LegacyPluginSpec { - getId: () => unknown; - getExpectedKibanaVersion: () => string; - getConfigPrefix: () => string; - getPack: () => LegacyPluginPack; -} - -/** - * @internal - * @deprecated - */ -export interface VarsProvider { - fn: (server: Server, configValue: any) => LegacyVars; - pluginSpec: { - readConfigValue(config: any, key: string | string[]): any; - }; -} - -/** - * @internal - * @deprecated - */ -export type VarsInjector = () => LegacyVars; - -/** - * @internal - * @deprecated - */ -export type VarsReplacer = ( - vars: LegacyVars, - request: LegacyRequest, - server: Server -) => LegacyVars | Promise; - -/** - * @internal - * @deprecated - */ -export type LegacyNavLinkSpec = Partial & { - id: string; - title: string; - url: string; -}; - -/** - * @internal - * @deprecated - */ -export type LegacyAppSpec = Partial & { - pluginId?: string; - listed?: boolean; -}; - -/** - * @internal - * @deprecated - */ -export type LegacyNavLink = Omit & { - order: number; -}; - -/** - * @internal - * @deprecated - */ -export interface LegacyUiExports { - defaultInjectedVarProviders?: VarsProvider[]; - injectedVarsReplacers?: VarsReplacer[]; - navLinkSpecs?: LegacyNavLinkSpec[] | null; - uiAppSpecs?: Array; - unknown?: [{ pluginSpec: LegacyPluginSpec; type: unknown }]; -} - /** * @public * @deprecated @@ -158,43 +69,7 @@ export interface LegacyServiceStartDeps { * @internal * @deprecated */ -export interface ILegacyInternals { - /** - * Inject UI app vars for a particular plugin - */ - injectUiAppVars(id: string, injector: VarsInjector): void; - - /** - * Get all the merged injected UI app vars for a particular plugin - */ - getInjectedUiAppVars(id: string): Promise; - - /** - * Get the metadata vars for a particular plugin - */ - getVars( - id: string, - request: KibanaRequest | LegacyRequest, - injected?: LegacyVars - ): Promise; -} - -/** - * @internal - * @deprecated - */ -export interface LegacyPlugins { - disabledPluginSpecs: LegacyPluginSpec[]; - pluginSpecs: LegacyPluginSpec[]; - uiExports: LegacyUiExports; - navLinks: LegacyNavLink[]; -} - -/** - * @internal - * @deprecated - */ -export interface LegacyServiceDiscoverPlugins extends LegacyPlugins { - pluginExtendedConfig: LegacyConfig; +export interface LegacyServiceSetupConfig { + legacyConfig: LegacyConfig; settings: LegacyVars; } diff --git a/src/core/server/metrics/collectors/cgroup.test.ts b/src/core/server/metrics/collectors/cgroup.test.ts index 39f917b9f0ba1..163646bf55424 100644 --- a/src/core/server/metrics/collectors/cgroup.test.ts +++ b/src/core/server/metrics/collectors/cgroup.test.ts @@ -18,6 +18,7 @@ */ import mockFs from 'mock-fs'; +import { loggerMock } from '@kbn/logging/target/mocks'; import { OsCgroupMetricsCollector } from './cgroup'; describe('OsCgroupMetricsCollector', () => { @@ -30,8 +31,10 @@ describe('OsCgroupMetricsCollector', () => { }, }); - const collector = new OsCgroupMetricsCollector({}); + const logger = loggerMock.create(); + const collector = new OsCgroupMetricsCollector({ logger }); expect(await collector.collect()).toEqual({}); + expect(logger.error).not.toHaveBeenCalled(); }); it('collects default cgroup data', async () => { @@ -51,7 +54,7 @@ throttled_time 666 `, }); - const collector = new OsCgroupMetricsCollector({}); + const collector = new OsCgroupMetricsCollector({ logger: loggerMock.create() }); expect(await collector.collect()).toMatchInlineSnapshot(` Object { "cpu": Object { @@ -90,6 +93,7 @@ throttled_time 666 }); const collector = new OsCgroupMetricsCollector({ + logger: loggerMock.create(), cpuAcctPath: 'xxcustomcpuacctxx', cpuPath: 'xxcustomcpuxx', }); @@ -112,4 +116,23 @@ throttled_time 666 } `); }); + + it('returns empty object and logs error on an EACCES error', async () => { + mockFs({ + '/proc/self/cgroup': ` +123:memory:/groupname +123:cpu:/groupname +123:cpuacct:/groupname + `, + '/sys/fs/cgroup': mockFs.directory({ mode: parseInt('0000', 8) }), + }); + + const logger = loggerMock.create(); + + const collector = new OsCgroupMetricsCollector({ logger }); + expect(await collector.collect()).toEqual({}); + expect(logger.error).toHaveBeenCalledWith( + "cgroup metrics could not be read due to error: [Error: EACCES, permission denied '/sys/fs/cgroup/cpuacct/groupname/cpuacct.usage']" + ); + }); }); diff --git a/src/core/server/metrics/collectors/cgroup.ts b/src/core/server/metrics/collectors/cgroup.ts index 867ea44dff1ae..42f5d30d115fe 100644 --- a/src/core/server/metrics/collectors/cgroup.ts +++ b/src/core/server/metrics/collectors/cgroup.ts @@ -19,11 +19,13 @@ import fs from 'fs'; import { join as joinPath } from 'path'; +import { Logger } from '@kbn/logging'; import { MetricsCollector, OpsOsMetrics } from './types'; type OsCgroupMetrics = Pick; interface OsCgroupMetricsCollectorOptions { + logger: Logger; cpuPath?: string; cpuAcctPath?: string; } @@ -38,8 +40,12 @@ export class OsCgroupMetricsCollector implements MetricsCollector { try { + if (this.noCgroupPresent) { + return {}; + } + await this.initializePaths(); - if (this.noCgroupPresent || !this.cpuAcctPath || !this.cpuPath) { + if (!this.cpuAcctPath || !this.cpuPath) { return {}; } @@ -64,12 +70,15 @@ export class OsCgroupMetricsCollector implements MetricsCollector (cb: Function) => cb(null, { dist: 'distrib', release: 'release' })); +import { loggerMock } from '@kbn/logging/target/mocks'; import os from 'os'; import { cgroupCollectorMock } from './os.test.mocks'; import { OsMetricsCollector } from './os'; @@ -27,7 +28,7 @@ describe('OsMetricsCollector', () => { let collector: OsMetricsCollector; beforeEach(() => { - collector = new OsMetricsCollector(); + collector = new OsMetricsCollector({ logger: loggerMock.create() }); cgroupCollectorMock.collect.mockReset(); cgroupCollectorMock.reset.mockReset(); }); diff --git a/src/core/server/metrics/collectors/os.ts b/src/core/server/metrics/collectors/os.ts index eae49278405a9..a9d727e57aaf9 100644 --- a/src/core/server/metrics/collectors/os.ts +++ b/src/core/server/metrics/collectors/os.ts @@ -20,12 +20,14 @@ import os from 'os'; import getosAsync, { LinuxOs } from 'getos'; import { promisify } from 'util'; +import { Logger } from '@kbn/logging'; import { OpsOsMetrics, MetricsCollector } from './types'; import { OsCgroupMetricsCollector } from './cgroup'; const getos = promisify(getosAsync); export interface OpsMetricsCollectorOptions { + logger: Logger; cpuPath?: string; cpuAcctPath?: string; } @@ -33,8 +35,11 @@ export interface OpsMetricsCollectorOptions { export class OsMetricsCollector implements MetricsCollector { private readonly cgroupCollector: OsCgroupMetricsCollector; - constructor(options: OpsMetricsCollectorOptions = {}) { - this.cgroupCollector = new OsCgroupMetricsCollector(options); + constructor(options: OpsMetricsCollectorOptions) { + this.cgroupCollector = new OsCgroupMetricsCollector({ + ...options, + logger: options.logger.get('cgroup'), + }); } public async collect(): Promise { diff --git a/src/core/server/metrics/metrics_service.ts b/src/core/server/metrics/metrics_service.ts index ab58a75d49a98..d3495f2748c71 100644 --- a/src/core/server/metrics/metrics_service.ts +++ b/src/core/server/metrics/metrics_service.ts @@ -50,7 +50,10 @@ export class MetricsService .pipe(first()) .toPromise(); - this.metricsCollector = new OpsMetricsCollector(http.server, config.cGroupOverrides); + this.metricsCollector = new OpsMetricsCollector(http.server, { + logger: this.logger, + ...config.cGroupOverrides, + }); await this.refreshMetrics(); diff --git a/src/core/server/metrics/ops_metrics_collector.test.ts b/src/core/server/metrics/ops_metrics_collector.test.ts index 7aa3f7cd3baf0..c748d1cce12e4 100644 --- a/src/core/server/metrics/ops_metrics_collector.test.ts +++ b/src/core/server/metrics/ops_metrics_collector.test.ts @@ -17,6 +17,7 @@ * under the License. */ +import { loggerMock } from '@kbn/logging/target/mocks'; import { mockOsCollector, mockProcessCollector, @@ -30,7 +31,7 @@ describe('OpsMetricsCollector', () => { beforeEach(() => { const hapiServer = httpServiceMock.createInternalSetupContract().server; - collector = new OpsMetricsCollector(hapiServer, {}); + collector = new OpsMetricsCollector(hapiServer, { logger: loggerMock.create() }); mockOsCollector.collect.mockResolvedValue('osMetrics'); }); diff --git a/src/core/server/mocks.ts b/src/core/server/mocks.ts index 7e001ffe28100..34e85920efb24 100644 --- a/src/core/server/mocks.ts +++ b/src/core/server/mocks.ts @@ -37,6 +37,7 @@ import { metricsServiceMock } from './metrics/metrics_service.mock'; import { environmentServiceMock } from './environment/environment_service.mock'; import { statusServiceMock } from './status/status_service.mock'; import { auditTrailServiceMock } from './audit_trail/audit_trail_service.mock'; +import { coreUsageDataServiceMock } from './core_usage_data/core_usage_data_service.mock'; export { configServiceMock } from './config/mocks'; export { httpServerMock } from './http/http_server.mocks'; @@ -54,6 +55,8 @@ export { metricsServiceMock } from './metrics/metrics_service.mock'; export { renderingMock } from './rendering/rendering_service.mock'; export { statusServiceMock } from './status/status_service.mock'; export { contextServiceMock } from './context/context_service.mock'; +export { capabilitiesServiceMock } from './capabilities/capabilities_service.mock'; +export { coreUsageDataServiceMock } from './core_usage_data/core_usage_data_service.mock'; export function pluginInitializerContextConfigMock(config: T) { const globalConfig: SharedGlobalConfig = { @@ -66,7 +69,6 @@ export function pluginInitializerContextConfigMock(config: T) { shardTimeout: duration('30s'), requestTimeout: duration('30s'), pingTimeout: duration('30s'), - startupTimeout: duration('30s'), }, path: { data: '/tmp' }, savedObjects: { @@ -157,6 +159,7 @@ function createCoreStartMock() { metrics: metricsServiceMock.createStartContract(), savedObjects: savedObjectsServiceMock.createStartContract(), uiSettings: uiSettingsServiceMock.createStartContract(), + coreUsageData: coreUsageDataServiceMock.createStartContract(), }; return mock; @@ -190,6 +193,7 @@ function createInternalCoreStartMock() { savedObjects: savedObjectsServiceMock.createInternalStartContract(), uiSettings: uiSettingsServiceMock.createStartContract(), auditTrail: auditTrailServiceMock.createStartContract(), + coreUsageData: coreUsageDataServiceMock.createStartContract(), }; return startDeps; } diff --git a/src/core/server/plugins/plugin_context.test.ts b/src/core/server/plugins/plugin_context.test.ts index cb4e8f20be982..7b2a5cd3b35f8 100644 --- a/src/core/server/plugins/plugin_context.test.ts +++ b/src/core/server/plugins/plugin_context.test.ts @@ -91,7 +91,6 @@ describe('createPluginInitializerContext', () => { shardTimeout: duration(30, 's'), requestTimeout: duration(30, 's'), pingTimeout: duration(30, 's'), - startupTimeout: duration(5, 's'), }, path: { data: fromRoot('data') }, savedObjects: { maxImportPayloadBytes: new ByteSizeValue(10485760) }, diff --git a/src/core/server/plugins/plugin_context.ts b/src/core/server/plugins/plugin_context.ts index ab3f471fd7942..a8249ed7e3218 100644 --- a/src/core/server/plugins/plugin_context.ts +++ b/src/core/server/plugins/plugin_context.ts @@ -251,5 +251,6 @@ export function createPluginStartContext( asScopedToClient: deps.uiSettings.asScopedToClient, }, auditTrail: deps.auditTrail, + coreUsageData: deps.coreUsageData, }; } diff --git a/src/core/server/plugins/plugins_service.test.ts b/src/core/server/plugins/plugins_service.test.ts index d36fd2251176a..64a382e539fb0 100644 --- a/src/core/server/plugins/plugins_service.test.ts +++ b/src/core/server/plugins/plugins_service.test.ts @@ -102,35 +102,42 @@ const createPlugin = ( }); }; -describe('PluginsService', () => { - beforeEach(async () => { - mockPackage.raw = { - branch: 'feature-v1', - version: 'v1', - build: { - distributable: true, - number: 100, - sha: 'feature-v1-build-sha', - }, - }; +async function testSetup(options: { isDevClusterMaster?: boolean } = {}) { + mockPackage.raw = { + branch: 'feature-v1', + version: 'v1', + build: { + distributable: true, + number: 100, + sha: 'feature-v1-build-sha', + }, + }; - coreId = Symbol('core'); - env = Env.createDefault(REPO_ROOT, getEnvOptions()); + coreId = Symbol('core'); + env = Env.createDefault(REPO_ROOT, { + ...getEnvOptions(), + isDevClusterMaster: options.isDevClusterMaster ?? false, + }); - config$ = new BehaviorSubject>({ plugins: { initialize: true } }); - const rawConfigService = rawConfigServiceMock.create({ rawConfig$: config$ }); - configService = new ConfigService(rawConfigService, env, logger); - await configService.setSchema(config.path, config.schema); - pluginsService = new PluginsService({ coreId, env, logger, configService }); + config$ = new BehaviorSubject>({ plugins: { initialize: true } }); + const rawConfigService = rawConfigServiceMock.create({ rawConfig$: config$ }); + configService = new ConfigService(rawConfigService, env, logger); + await configService.setSchema(config.path, config.schema); + pluginsService = new PluginsService({ coreId, env, logger, configService }); - [mockPluginSystem] = MockPluginsSystem.mock.instances as any; - mockPluginSystem.uiPlugins.mockReturnValue(new Map()); + [mockPluginSystem] = MockPluginsSystem.mock.instances as any; + mockPluginSystem.uiPlugins.mockReturnValue(new Map()); - environmentSetup = environmentServiceMock.createSetupContract(); - }); + environmentSetup = environmentServiceMock.createSetupContract(); +} - afterEach(() => { - jest.clearAllMocks(); +afterEach(() => { + jest.clearAllMocks(); +}); + +describe('PluginsService', () => { + beforeEach(async () => { + await testSetup(); }); describe('#discover()', () => { @@ -613,3 +620,29 @@ describe('PluginsService', () => { }); }); }); + +describe('PluginService when isDevClusterMaster is true', () => { + beforeEach(async () => { + await testSetup({ + isDevClusterMaster: true, + }); + }); + + describe('#discover()', () => { + it('does not try to run discovery', async () => { + await expect(pluginsService.discover({ environment: environmentSetup })).resolves + .toMatchInlineSnapshot(` + Object { + "pluginTree": undefined, + "uiPlugins": Object { + "browserConfigs": Map {}, + "internal": Map {}, + "public": Map {}, + }, + } + `); + + expect(mockDiscover).not.toHaveBeenCalled(); + }); + }); +}); diff --git a/src/core/server/plugins/plugins_service.ts b/src/core/server/plugins/plugins_service.ts index e8fe42ee491ca..a1062bde7765f 100644 --- a/src/core/server/plugins/plugins_service.ts +++ b/src/core/server/plugins/plugins_service.ts @@ -18,7 +18,7 @@ */ import Path from 'path'; -import { Observable } from 'rxjs'; +import { Observable, EMPTY } from 'rxjs'; import { filter, first, map, mergeMap, tap, toArray } from 'rxjs/operators'; import { pick } from '@kbn/std'; @@ -86,9 +86,11 @@ export class PluginsService implements CoreService; private readonly pluginConfigDescriptors = new Map(); private readonly uiPluginInternalInfo = new Map(); + private readonly discoveryDisabled: boolean; constructor(private readonly coreContext: CoreContext) { this.log = coreContext.logger.get('plugins-service'); + this.discoveryDisabled = coreContext.env.isDevClusterMaster; this.pluginsSystem = new PluginsSystem(coreContext); this.configService = coreContext.configService; this.config$ = coreContext.configService @@ -97,13 +99,17 @@ export class PluginsService implements CoreService = { render: jest.fn(), }; export const mockSetup = jest.fn().mockResolvedValue(setupMock); -export const mockStart = jest.fn(); export const mockStop = jest.fn(); export const mockRenderingService: jest.Mocked = { setup: mockSetup, - start: mockStart, stop: mockStop, }; export const RenderingService = jest.fn( diff --git a/src/core/server/rendering/__snapshots__/rendering_service.test.ts.snap b/src/core/server/rendering/__snapshots__/rendering_service.test.ts.snap index ab828a1780425..07ca59a48c6b0 100644 --- a/src/core/server/rendering/__snapshots__/rendering_service.test.ts.snap +++ b/src/core/server/rendering/__snapshots__/rendering_service.test.ts.snap @@ -27,15 +27,6 @@ Object { "translationsUrl": "/mock-server-basepath/translations/en.json", }, "legacyMetadata": Object { - "app": Object {}, - "basePath": "/mock-server-basepath", - "branch": Any, - "buildNum": Any, - "buildSha": Any, - "bundleId": "app:core", - "devMode": true, - "nav": Array [], - "serverName": "http-server-test", "uiSettings": Object { "defaults": Object { "registered": Object { @@ -44,7 +35,6 @@ Object { }, "user": Object {}, }, - "version": Any, }, "serverBasePath": "/mock-server-basepath", "uiPlugins": Array [], @@ -80,15 +70,6 @@ Object { "translationsUrl": "/mock-server-basepath/translations/en.json", }, "legacyMetadata": Object { - "app": Object {}, - "basePath": "/mock-server-basepath", - "branch": Any, - "buildNum": Any, - "buildSha": Any, - "bundleId": "app:core", - "devMode": true, - "nav": Array [], - "serverName": "http-server-test", "uiSettings": Object { "defaults": Object { "registered": Object { @@ -97,7 +78,6 @@ Object { }, "user": Object {}, }, - "version": Any, }, "serverBasePath": "/mock-server-basepath", "uiPlugins": Array [], @@ -133,15 +113,6 @@ Object { "translationsUrl": "/mock-server-basepath/translations/en.json", }, "legacyMetadata": Object { - "app": Object {}, - "basePath": "/mock-server-basepath", - "branch": Any, - "buildNum": Any, - "buildSha": Any, - "bundleId": "app:core", - "devMode": true, - "nav": Array [], - "serverName": "http-server-test", "uiSettings": Object { "defaults": Object { "registered": Object { @@ -154,7 +125,6 @@ Object { }, }, }, - "version": Any, }, "serverBasePath": "/mock-server-basepath", "uiPlugins": Array [], @@ -190,15 +160,6 @@ Object { "translationsUrl": "/translations/en.json", }, "legacyMetadata": Object { - "app": Object {}, - "basePath": "", - "branch": Any, - "buildNum": Any, - "buildSha": Any, - "bundleId": "app:core", - "devMode": true, - "nav": Array [], - "serverName": "http-server-test", "uiSettings": Object { "defaults": Object { "registered": Object { @@ -207,7 +168,6 @@ Object { }, "user": Object {}, }, - "version": Any, }, "serverBasePath": "/mock-server-basepath", "uiPlugins": Array [], @@ -243,15 +203,6 @@ Object { "translationsUrl": "/mock-server-basepath/translations/en.json", }, "legacyMetadata": Object { - "app": Object {}, - "basePath": "/mock-server-basepath", - "branch": Any, - "buildNum": Any, - "buildSha": Any, - "bundleId": "app:core", - "devMode": true, - "nav": Array [], - "serverName": "http-server-test", "uiSettings": Object { "defaults": Object { "registered": Object { @@ -260,7 +211,6 @@ Object { }, "user": Object {}, }, - "version": Any, }, "serverBasePath": "/mock-server-basepath", "uiPlugins": Array [], diff --git a/src/core/server/rendering/rendering_service.test.ts b/src/core/server/rendering/rendering_service.test.ts index 254bafed5b194..08978cd1df64d 100644 --- a/src/core/server/rendering/rendering_service.test.ts +++ b/src/core/server/rendering/rendering_service.test.ts @@ -43,12 +43,6 @@ const INJECTED_METADATA = { version: expect.any(String), }, }, - legacyMetadata: { - branch: expect.any(String), - buildNum: expect.any(Number), - buildSha: expect.any(String), - version: expect.any(String), - }, }; const { createKibanaRequest, createRawRequest } = httpServerMock; @@ -72,13 +66,6 @@ describe('RenderingService', () => { registered: { name: 'title' }, }); render = (await service.setup(mockRenderingSetupDeps)).render; - await service.start({ - legacy: { - legacyInternals: { - getVars: () => ({}), - }, - }, - } as any); }); it('renders "core" page', async () => { diff --git a/src/core/server/rendering/rendering_service.tsx b/src/core/server/rendering/rendering_service.tsx index 7761c89044f6f..738787f940905 100644 --- a/src/core/server/rendering/rendering_service.tsx +++ b/src/core/server/rendering/rendering_service.tsx @@ -20,14 +20,11 @@ import React from 'react'; import { renderToStaticMarkup } from 'react-dom/server'; import { take } from 'rxjs/operators'; - import { i18n } from '@kbn/i18n'; import { UiPlugins } from '../plugins'; -import { CoreService } from '../../types'; import { CoreContext } from '../core_context'; import { Template } from './views'; -import { LegacyService } from '../legacy'; import { IRenderOptions, RenderingSetupDeps, @@ -36,25 +33,20 @@ import { } from './types'; /** @internal */ -export class RenderingService implements CoreService { - private legacyInternals?: LegacyService['legacyInternals']; +export class RenderingService { constructor(private readonly coreContext: CoreContext) {} public async setup({ http, status, - legacyPlugins, uiPlugins, }: RenderingSetupDeps): Promise { return { render: async ( request, uiSettings, - { app = { getId: () => 'core' }, includeUserSettings = true, vars }: IRenderOptions = {} + { includeUserSettings = true, vars }: IRenderOptions = {} ) => { - if (!this.legacyInternals) { - throw new Error('Cannot render before "start"'); - } const env = { mode: this.coreContext.env.mode, packageInfo: this.coreContext.env.packageInfo, @@ -65,7 +57,6 @@ export class RenderingService implements CoreService ({ id, @@ -96,16 +87,6 @@ export class RenderingService implements CoreService; }>; legacyMetadata: { - app: { getId(): string }; - bundleId: string; - nav: LegacyNavLink[]; - version: string; - branch: string; - buildNum: number; - buildSha: string; - serverName: string; - devMode: boolean; - basePath: string; uiSettings: { defaults: Record; user: Record>; @@ -78,7 +67,6 @@ export interface RenderingMetadata { /** @internal */ export interface RenderingSetupDeps { http: InternalHttpServiceSetup; - legacyPlugins: LegacyServiceDiscoverPlugins; status: InternalStatusServiceSetup; uiPlugins: UiPlugins; } @@ -91,14 +79,6 @@ export interface IRenderOptions { */ includeUserSettings?: boolean; - /** - * Render the bootstrapped HTML content for an optional legacy application. - * Defaults to `core`. - * @deprecated for legacy use only, remove with ui_render_mixin - * @internal - */ - app?: { getId(): string }; - /** * Inject custom vars into the page metadata. * @deprecated for legacy use only, remove with ui_render_mixin diff --git a/src/core/server/saved_objects/migrations/core/migration_es_client.ts b/src/core/server/saved_objects/migrations/core/migration_es_client.ts index ff859057f8fe8..e8482e6352a82 100644 --- a/src/core/server/saved_objects/migrations/core/migration_es_client.ts +++ b/src/core/server/saved_objects/migrations/core/migration_es_client.ts @@ -80,7 +80,7 @@ export function createMigrationEsClient( throw new Error(`unknown ElasticsearchClient client method [${key}]`); } return await migrationRetryCallCluster( - () => fn(params, { maxRetries: 0, ...options }), + () => fn.call(client, params, { maxRetries: 0, ...options }), log, delay ); diff --git a/src/core/server/saved_objects/routes/bulk_create.ts b/src/core/server/saved_objects/routes/bulk_create.ts index af1a7bd2af9b7..b048c5d8f99bf 100644 --- a/src/core/server/saved_objects/routes/bulk_create.ts +++ b/src/core/server/saved_objects/routes/bulk_create.ts @@ -44,6 +44,7 @@ export const registerBulkCreateRoute = (router: IRouter) => { }) ) ), + initialNamespaces: schema.maybe(schema.arrayOf(schema.string(), { minSize: 1 })), }) ), }, diff --git a/src/core/server/saved_objects/routes/create.ts b/src/core/server/saved_objects/routes/create.ts index 6cf906a3b2895..816315705a375 100644 --- a/src/core/server/saved_objects/routes/create.ts +++ b/src/core/server/saved_objects/routes/create.ts @@ -44,15 +44,16 @@ export const registerCreateRoute = (router: IRouter) => { }) ) ), + initialNamespaces: schema.maybe(schema.arrayOf(schema.string(), { minSize: 1 })), }), }, }, router.handleLegacyErrors(async (context, req, res) => { const { type, id } = req.params; const { overwrite } = req.query; - const { attributes, migrationVersion, references } = req.body; + const { attributes, migrationVersion, references, initialNamespaces } = req.body; - const options = { id, overwrite, migrationVersion, references }; + const options = { id, overwrite, migrationVersion, references, initialNamespaces }; const result = await context.core.savedObjects.client.create(type, attributes, options); return res.ok({ body: result }); }) diff --git a/src/core/server/saved_objects/routes/delete.ts b/src/core/server/saved_objects/routes/delete.ts index d119455336212..d99397d2a050c 100644 --- a/src/core/server/saved_objects/routes/delete.ts +++ b/src/core/server/saved_objects/routes/delete.ts @@ -29,11 +29,15 @@ export const registerDeleteRoute = (router: IRouter) => { type: schema.string(), id: schema.string(), }), + query: schema.object({ + force: schema.maybe(schema.boolean()), + }), }, }, router.handleLegacyErrors(async (context, req, res) => { const { type, id } = req.params; - const result = await context.core.savedObjects.client.delete(type, id); + const { force } = req.query; + const result = await context.core.savedObjects.client.delete(type, id, { force }); return res.ok({ body: result }); }) ); diff --git a/src/core/server/saved_objects/routes/integration_tests/delete.test.ts b/src/core/server/saved_objects/routes/integration_tests/delete.test.ts index a58f400ec3e1d..ff8642a34929f 100644 --- a/src/core/server/saved_objects/routes/integration_tests/delete.test.ts +++ b/src/core/server/saved_objects/routes/integration_tests/delete.test.ts @@ -58,6 +58,19 @@ describe('DELETE /api/saved_objects/{type}/{id}', () => { .delete('/api/saved_objects/index-pattern/logstash-*') .expect(200); - expect(savedObjectsClient.delete).toHaveBeenCalledWith('index-pattern', 'logstash-*'); + expect(savedObjectsClient.delete).toHaveBeenCalledWith('index-pattern', 'logstash-*', { + force: undefined, + }); + }); + + it('can specify `force` option', async () => { + await supertest(httpSetup.server.listener) + .delete('/api/saved_objects/index-pattern/logstash-*') + .query({ force: true }) + .expect(200); + + expect(savedObjectsClient.delete).toHaveBeenCalledWith('index-pattern', 'logstash-*', { + force: true, + }); }); }); diff --git a/src/core/server/saved_objects/routes/integration_tests/import.test.ts b/src/core/server/saved_objects/routes/integration_tests/import.test.ts index 0bc03fbcf8038..67be2b56b4447 100644 --- a/src/core/server/saved_objects/routes/integration_tests/import.test.ts +++ b/src/core/server/saved_objects/routes/integration_tests/import.test.ts @@ -471,7 +471,11 @@ describe(`POST ${URL}`, () => { describe('createNewCopies enabled', () => { it('imports objects, regenerating all IDs/reference IDs present, and resetting all origin IDs', async () => { - mockUuidv4.mockReturnValueOnce('new-id-1').mockReturnValueOnce('new-id-2'); + mockUuidv4 + .mockReturnValueOnce('foo') // a uuid.v4() is generated for the request.id + .mockReturnValueOnce('foo') // another uuid.v4() is used for the request.uuid + .mockReturnValueOnce('new-id-1') + .mockReturnValueOnce('new-id-2'); savedObjectsClient.bulkGet.mockResolvedValueOnce({ saved_objects: [mockIndexPattern] }); const obj1 = { type: 'visualization', @@ -490,7 +494,6 @@ describe(`POST ${URL}`, () => { const result = await supertest(httpSetup.server.listener) .post(`${URL}?createNewCopies=true`) .set('content-Type', 'multipart/form-data; boundary=EXAMPLE') - .set('x-opaque-id', uuidv4()) // prevents src/core/server/http/http_tools.ts from using our mocked uuidv4 to generate a unique ID for this request .send( [ '--EXAMPLE', diff --git a/src/core/server/saved_objects/saved_objects_service.mock.ts b/src/core/server/saved_objects/saved_objects_service.mock.ts index bd76658c21731..c56cdabf6e4cd 100644 --- a/src/core/server/saved_objects/saved_objects_service.mock.ts +++ b/src/core/server/saved_objects/saved_objects_service.mock.ts @@ -33,10 +33,11 @@ import { savedObjectsClientMock } from './service/saved_objects_client.mock'; import { typeRegistryMock } from './saved_objects_type_registry.mock'; import { migrationMocks } from './migrations/mocks'; import { ServiceStatusLevels } from '../status'; +import { ISavedObjectTypeRegistry } from './saved_objects_type_registry'; type SavedObjectsServiceContract = PublicMethodsOf; -const createStartContractMock = () => { +const createStartContractMock = (typeRegistry?: jest.Mocked) => { const startContrat: jest.Mocked = { getScopedClient: jest.fn(), createInternalRepository: jest.fn(), @@ -48,13 +49,15 @@ const createStartContractMock = () => { startContrat.getScopedClient.mockReturnValue(savedObjectsClientMock.create()); startContrat.createInternalRepository.mockReturnValue(savedObjectsRepositoryMock.create()); startContrat.createScopedRepository.mockReturnValue(savedObjectsRepositoryMock.create()); - startContrat.getTypeRegistry.mockReturnValue(typeRegistryMock.create()); + startContrat.getTypeRegistry.mockReturnValue(typeRegistry ?? typeRegistryMock.create()); return startContrat; }; -const createInternalStartContractMock = () => { - const internalStartContract: jest.Mocked = createStartContractMock(); +const createInternalStartContractMock = (typeRegistry?: jest.Mocked) => { + const internalStartContract: jest.Mocked = createStartContractMock( + typeRegistry + ); return internalStartContract; }; diff --git a/src/core/server/saved_objects/service/lib/repository.test.js b/src/core/server/saved_objects/service/lib/repository.test.js index 352ce4c1c16eb..e93bdb34ecc75 100644 --- a/src/core/server/saved_objects/service/lib/repository.test.js +++ b/src/core/server/saved_objects/service/lib/repository.test.js @@ -20,6 +20,7 @@ import { SavedObjectsRepository } from './repository'; import * as getSearchDslNS from './search_dsl/search_dsl'; import { SavedObjectsErrorHelpers } from './errors'; +import { ALL_NAMESPACES_STRING } from './utils'; import { SavedObjectsSerializer } from '../../serialization'; import { encodeHitVersion } from '../../version'; import { SavedObjectTypeRegistry } from '../../saved_objects_type_registry'; @@ -634,6 +635,32 @@ describe('SavedObjectsRepository', () => { await test(namespace); }); + it(`adds initialNamespaces instead of namespace`, async () => { + const test = async (namespace) => { + const ns2 = 'bar-namespace'; + const ns3 = 'baz-namespace'; + const objects = [ + { ...obj1, type: MULTI_NAMESPACE_TYPE, initialNamespaces: [ns2] }, + { ...obj2, type: MULTI_NAMESPACE_TYPE, initialNamespaces: [ns3] }, + ]; + await bulkCreateSuccess(objects, { namespace, overwrite: true }); + const body = [ + expect.any(Object), + expect.objectContaining({ namespaces: [ns2] }), + expect.any(Object), + expect.objectContaining({ namespaces: [ns3] }), + ]; + expect(client.bulk).toHaveBeenCalledWith( + expect.objectContaining({ body }), + expect.anything() + ); + client.bulk.mockClear(); + client.mget.mockClear(); + }; + await test(undefined); + await test(namespace); + }); + it(`doesn't add namespaces to request body for any types that are not multi-namespace`, async () => { const test = async (namespace) => { const objects = [obj1, { ...obj2, type: NAMESPACE_AGNOSTIC_TYPE }]; @@ -725,6 +752,40 @@ describe('SavedObjectsRepository', () => { }); }; + it(`throws when options.namespace is '*'`, async () => { + await expect( + savedObjectsRepository.bulkCreate([obj3], { namespace: ALL_NAMESPACES_STRING }) + ).rejects.toThrowError(createBadRequestError('"options.namespace" cannot be "*"')); + }); + + it(`returns error when initialNamespaces is used with a non-multi-namespace object`, async () => { + const test = async (objType) => { + const obj = { ...obj3, type: objType, initialNamespaces: [] }; + await bulkCreateError( + obj, + undefined, + expectErrorResult( + obj, + createBadRequestError('"initialNamespaces" can only be used on multi-namespace types') + ) + ); + }; + await test('dashboard'); + await test(NAMESPACE_AGNOSTIC_TYPE); + }); + + it(`throws when options.initialNamespaces is used with a multi-namespace type and is empty`, async () => { + const obj = { ...obj3, type: MULTI_NAMESPACE_TYPE, initialNamespaces: [] }; + await bulkCreateError( + obj, + undefined, + expectErrorResult( + obj, + createBadRequestError('"initialNamespaces" must be a non-empty array of strings') + ) + ); + }); + it(`returns error when type is invalid`, async () => { const obj = { ...obj3, type: 'unknownType' }; await bulkCreateError(obj, undefined, expectErrorInvalidType(obj)); @@ -1042,6 +1103,13 @@ describe('SavedObjectsRepository', () => { }); }; + it(`throws when options.namespace is '*'`, async () => { + const obj = { type: 'dashboard', id: 'three' }; + await expect( + savedObjectsRepository.bulkGet([obj], { namespace: ALL_NAMESPACES_STRING }) + ).rejects.toThrowError(createBadRequestError('"options.namespace" cannot be "*"')); + }); + it(`returns error when type is invalid`, async () => { const obj = { type: 'unknownType', id: 'three' }; await bulkGetErrorInvalidType([obj1, obj, obj2]); @@ -1467,6 +1535,12 @@ describe('SavedObjectsRepository', () => { }); }; + it(`throws when options.namespace is '*'`, async () => { + await expect( + savedObjectsRepository.bulkUpdate([obj], { namespace: ALL_NAMESPACES_STRING }) + ).rejects.toThrowError(createBadRequestError('"options.namespace" cannot be "*"')); + }); + it(`returns error when type is invalid`, async () => { const _obj = { ...obj, type: 'unknownType' }; await bulkUpdateError(_obj, undefined, expectErrorNotFound(_obj)); @@ -1477,6 +1551,15 @@ describe('SavedObjectsRepository', () => { await bulkUpdateError(_obj, undefined, expectErrorNotFound(_obj)); }); + it(`returns error when object namespace is '*'`, async () => { + const _obj = { ...obj, namespace: '*' }; + await bulkUpdateError( + _obj, + undefined, + expectErrorResult(obj, createBadRequestError('"namespace" cannot be "*"')) + ); + }); + it(`returns error when ES is unable to find the document (mget)`, async () => { const _obj = { ...obj, type: MULTI_NAMESPACE_TYPE, found: false }; const mgetResponse = getMockMgetResponse([_obj]); @@ -1630,7 +1713,7 @@ describe('SavedObjectsRepository', () => { ); }; - describe('cluster calls', () => { + describe('client calls', () => { it(`doesn't make a cluster call if the objects array is empty`, async () => { await checkConflicts([]); expect(client.mget).not.toHaveBeenCalled(); @@ -1662,6 +1745,14 @@ describe('SavedObjectsRepository', () => { }); }); + describe('errors', () => { + it(`throws when options.namespace is '*'`, async () => { + await expect( + savedObjectsRepository.checkConflicts([obj1], { namespace: ALL_NAMESPACES_STRING }) + ).rejects.toThrowError(createBadRequestError('"options.namespace" cannot be "*"')); + }); + }); + describe('returns', () => { it(`expected results`, async () => { const unknownTypeObj = { type: 'unknownType', id: 'three' }; @@ -1858,21 +1949,23 @@ describe('SavedObjectsRepository', () => { ); }); - it(`prepends namespace to the id when providing namespace for single-namespace type`, async () => { + it(`prepends namespace to the id and adds namespace to the body when providing namespace for single-namespace type`, async () => { await createSuccess(type, attributes, { id, namespace }); expect(client.create).toHaveBeenCalledWith( expect.objectContaining({ id: `${namespace}:${type}:${id}`, + body: expect.objectContaining({ namespace }), }), expect.anything() ); }); - it(`doesn't prepend namespace to the id when providing no namespace for single-namespace type`, async () => { + it(`doesn't prepend namespace to the id or add namespace to the body when providing no namespace for single-namespace type`, async () => { await createSuccess(type, attributes, { id }); expect(client.create).toHaveBeenCalledWith( expect.objectContaining({ id: `${type}:${id}`, + body: expect.not.objectContaining({ namespace: expect.anything() }), }), expect.anything() ); @@ -1883,25 +1976,44 @@ describe('SavedObjectsRepository', () => { expect(client.create).toHaveBeenCalledWith( expect.objectContaining({ id: `${type}:${id}`, + body: expect.not.objectContaining({ namespace: expect.anything() }), }), expect.anything() ); }); - it(`doesn't prepend namespace to the id when not using single-namespace type`, async () => { - await createSuccess(NAMESPACE_AGNOSTIC_TYPE, attributes, { id, namespace }); + it(`doesn't prepend namespace to the id and adds namespaces to body when using multi-namespace type`, async () => { + await createSuccess(MULTI_NAMESPACE_TYPE, attributes, { id, namespace }); expect(client.create).toHaveBeenCalledWith( expect.objectContaining({ - id: `${NAMESPACE_AGNOSTIC_TYPE}:${id}`, + id: `${MULTI_NAMESPACE_TYPE}:${id}`, + body: expect.objectContaining({ namespaces: [namespace] }), }), expect.anything() ); - client.create.mockClear(); + }); - await createSuccess(MULTI_NAMESPACE_TYPE, attributes, { id, namespace }); + it(`adds initialNamespaces instead of namespace`, async () => { + const options = { id, namespace, initialNamespaces: ['bar-namespace', 'baz-namespace'] }; + await createSuccess(MULTI_NAMESPACE_TYPE, attributes, options); expect(client.create).toHaveBeenCalledWith( expect.objectContaining({ id: `${MULTI_NAMESPACE_TYPE}:${id}`, + body: expect.objectContaining({ namespaces: options.initialNamespaces }), + }), + expect.anything() + ); + }); + + it(`doesn't prepend namespace to the id or add namespace or namespaces fields when using namespace-agnostic type`, async () => { + await createSuccess(NAMESPACE_AGNOSTIC_TYPE, attributes, { id, namespace }); + expect(client.create).toHaveBeenCalledWith( + expect.objectContaining({ + id: `${NAMESPACE_AGNOSTIC_TYPE}:${id}`, + body: expect.not.objectContaining({ + namespace: expect.anything(), + namespaces: expect.anything(), + }), }), expect.anything() ); @@ -1909,6 +2021,34 @@ describe('SavedObjectsRepository', () => { }); describe('errors', () => { + it(`throws when options.initialNamespaces is used with a non-multi-namespace object`, async () => { + const test = async (objType) => { + await expect( + savedObjectsRepository.create(objType, attributes, { initialNamespaces: [namespace] }) + ).rejects.toThrowError( + createBadRequestError( + '"options.initialNamespaces" can only be used on multi-namespace types' + ) + ); + }; + await test('dashboard'); + await test(NAMESPACE_AGNOSTIC_TYPE); + }); + + it(`throws when options.initialNamespaces is used with a multi-namespace type and is empty`, async () => { + await expect( + savedObjectsRepository.create(MULTI_NAMESPACE_TYPE, attributes, { initialNamespaces: [] }) + ).rejects.toThrowError( + createBadRequestError('"options.initialNamespaces" must be a non-empty array of strings') + ); + }); + + it(`throws when options.namespace is '*'`, async () => { + await expect( + savedObjectsRepository.create(type, attributes, { namespace: ALL_NAMESPACES_STRING }) + ).rejects.toThrowError(createBadRequestError('"options.namespace" cannot be "*"')); + }); + it(`throws when type is invalid`, async () => { await expect(savedObjectsRepository.create('unknownType', attributes)).rejects.toThrowError( createUnsupportedTypeError('unknownType') @@ -2043,31 +2183,17 @@ describe('SavedObjectsRepository', () => { describe('client calls', () => { it(`should use the ES delete action when not using a multi-namespace type`, async () => { await deleteSuccess(type, id); + expect(client.get).not.toHaveBeenCalled(); expect(client.delete).toHaveBeenCalledTimes(1); }); - it(`should use ES get action then delete action when using a multi-namespace type with no namespaces remaining`, async () => { + it(`should use ES get action then delete action when using a multi-namespace type`, async () => { await deleteSuccess(MULTI_NAMESPACE_TYPE, id); expect(client.get).toHaveBeenCalledTimes(1); expect(client.delete).toHaveBeenCalledTimes(1); }); - it(`should use ES get action then update action when using a multi-namespace type with one or more namespaces remaining`, async () => { - const mockResponse = getMockGetResponse({ type: MULTI_NAMESPACE_TYPE, id }); - mockResponse._source.namespaces = ['default', 'some-other-nameespace']; - client.get.mockResolvedValueOnce( - elasticsearchClientMock.createSuccessTransportRequestPromise(mockResponse) - ); - client.update.mockResolvedValueOnce( - elasticsearchClientMock.createSuccessTransportRequestPromise({ result: 'updated' }) - ); - - await savedObjectsRepository.delete(MULTI_NAMESPACE_TYPE, id); - expect(client.get).toHaveBeenCalledTimes(1); - expect(client.update).toHaveBeenCalledTimes(1); - }); - - it(`includes the version of the existing document when type is multi-namespace`, async () => { + it(`includes the version of the existing document when using a multi-namespace type`, async () => { await deleteSuccess(MULTI_NAMESPACE_TYPE, id); const versionProperties = { if_seq_no: mockVersionProps._seq_no, @@ -2134,6 +2260,12 @@ describe('SavedObjectsRepository', () => { ); }; + it(`throws when options.namespace is '*'`, async () => { + await expect( + savedObjectsRepository.delete(type, id, { namespace: ALL_NAMESPACES_STRING }) + ).rejects.toThrowError(createBadRequestError('"options.namespace" cannot be "*"')); + }); + it(`throws when type is invalid`, async () => { await expectNotFoundError('unknownType', id); expect(client.delete).not.toHaveBeenCalled(); @@ -2169,19 +2301,32 @@ describe('SavedObjectsRepository', () => { expect(client.get).toHaveBeenCalledTimes(1); }); - it(`throws when ES is unable to find the document during update`, async () => { - const mockResponse = getMockGetResponse({ type: MULTI_NAMESPACE_TYPE, id }); - mockResponse._source.namespaces = ['default', 'some-other-nameespace']; + it(`throws when the type is multi-namespace and the document has multiple namespaces and the force option is not enabled`, async () => { + const response = getMockGetResponse({ type: MULTI_NAMESPACE_TYPE, id, namespace }); + response._source.namespaces = [namespace, 'bar-namespace']; client.get.mockResolvedValueOnce( - elasticsearchClientMock.createSuccessTransportRequestPromise(mockResponse) + elasticsearchClientMock.createSuccessTransportRequestPromise(response) ); - client.update.mockResolvedValueOnce( - elasticsearchClientMock.createSuccessTransportRequestPromise({}, { statusCode: 404 }) + await expect( + savedObjectsRepository.delete(MULTI_NAMESPACE_TYPE, id, { namespace }) + ).rejects.toThrowError( + 'Unable to delete saved object that exists in multiple namespaces, use the `force` option to delete it anyway' ); + expect(client.get).toHaveBeenCalledTimes(1); + }); - await expectNotFoundError(MULTI_NAMESPACE_TYPE, id); + it(`throws when the type is multi-namespace and the document has all namespaces and the force option is not enabled`, async () => { + const response = getMockGetResponse({ type: MULTI_NAMESPACE_TYPE, id, namespace }); + response._source.namespaces = ['*']; + client.get.mockResolvedValueOnce( + elasticsearchClientMock.createSuccessTransportRequestPromise(response) + ); + await expect( + savedObjectsRepository.delete(MULTI_NAMESPACE_TYPE, id, { namespace }) + ).rejects.toThrowError( + 'Unable to delete saved object that exists in multiple namespaces, use the `force` option to delete it anyway' + ); expect(client.get).toHaveBeenCalledTimes(1); - expect(client.update).toHaveBeenCalledTimes(1); }); it(`throws when ES is unable to find the document during delete`, async () => { @@ -2267,7 +2412,7 @@ describe('SavedObjectsRepository', () => { }); describe('errors', () => { - it(`throws when namespace is not a string`, async () => { + it(`throws when namespace is not a string or is '*'`, async () => { const test = async (namespace) => { await expect(savedObjectsRepository.deleteByNamespace(namespace)).rejects.toThrowError( `namespace is required, and must be a string` @@ -2278,6 +2423,7 @@ describe('SavedObjectsRepository', () => { await test(['namespace']); await test(123); await test(true); + await test(ALL_NAMESPACES_STRING); }); }); @@ -2477,6 +2623,33 @@ describe('SavedObjectsRepository', () => { expect(client.search).not.toHaveBeenCalled(); }); + it(`throws when namespaces is an empty array`, async () => { + await expect( + savedObjectsRepository.find({ type: 'foo', namespaces: [] }) + ).rejects.toThrowError('options.namespaces cannot be an empty array'); + expect(client.search).not.toHaveBeenCalled(); + }); + + it(`throws when type is not falsy and typeToNamespacesMap is defined`, async () => { + await expect( + savedObjectsRepository.find({ type: 'foo', typeToNamespacesMap: new Map() }) + ).rejects.toThrowError( + 'options.type must be an empty string when options.typeToNamespacesMap is used' + ); + expect(client.search).not.toHaveBeenCalled(); + }); + + it(`throws when type is not an empty array and typeToNamespacesMap is defined`, async () => { + const test = async (args) => { + await expect(savedObjectsRepository.find(args)).rejects.toThrowError( + 'options.namespaces must be an empty array when options.typeToNamespacesMap is used' + ); + expect(client.search).not.toHaveBeenCalled(); + }; + await test({ type: '', typeToNamespacesMap: new Map() }); + await test({ type: '', namespaces: ['some-ns'], typeToNamespacesMap: new Map() }); + }); + it(`throws when searchFields is defined but not an array`, async () => { await expect( savedObjectsRepository.find({ type, searchFields: 'string' }) @@ -2493,7 +2666,7 @@ describe('SavedObjectsRepository', () => { it(`throws when KQL filter syntax is invalid`, async () => { const findOpts = { - namespace, + namespaces: [namespace], search: 'foo*', searchFields: ['foo'], type: ['dashboard'], @@ -2577,38 +2750,70 @@ describe('SavedObjectsRepository', () => { const test = async (types) => { const result = await savedObjectsRepository.find({ type: types }); expect(result).toEqual(expect.objectContaining({ saved_objects: [] })); + expect(client.search).not.toHaveBeenCalled(); }; await test('unknownType'); await test(HIDDEN_TYPE); await test(['unknownType', HIDDEN_TYPE]); }); + + it(`should return empty results when attempting to find only invalid or hidden types using typeToNamespacesMap`, async () => { + const test = async (types) => { + const result = await savedObjectsRepository.find({ + typeToNamespacesMap: new Map(types.map((x) => [x, undefined])), + type: '', + namespaces: [], + }); + expect(result).toEqual(expect.objectContaining({ saved_objects: [] })); + expect(client.search).not.toHaveBeenCalled(); + }; + + await test(['unknownType']); + await test([HIDDEN_TYPE]); + await test(['unknownType', HIDDEN_TYPE]); + }); }); describe('search dsl', () => { - it(`passes mappings, registry, search, defaultSearchOperator, searchFields, type, sortField, sortOrder and hasReference to getSearchDsl`, async () => { + const commonOptions = { + type: [type], // cannot be used when `typeToNamespacesMap` is present + namespaces: [namespace], // cannot be used when `typeToNamespacesMap` is present + search: 'foo*', + searchFields: ['foo'], + sortField: 'name', + sortOrder: 'desc', + defaultSearchOperator: 'AND', + hasReference: { + type: 'foo', + id: '1', + }, + kueryNode: undefined, + }; + + it(`passes mappings, registry, and search options to getSearchDsl`, async () => { + await findSuccess(commonOptions, namespace); + expect(getSearchDslNS.getSearchDsl).toHaveBeenCalledWith(mappings, registry, commonOptions); + }); + + it(`accepts typeToNamespacesMap`, async () => { const relevantOpts = { - namespaces: [namespace], - search: 'foo*', - searchFields: ['foo'], - type: [type], - sortField: 'name', - sortOrder: 'desc', - defaultSearchOperator: 'AND', - hasReference: { - type: 'foo', - id: '1', - }, - kueryNode: undefined, + ...commonOptions, + type: '', + namespaces: [], + typeToNamespacesMap: new Map([[type, [namespace]]]), // can only be used when `type` is falsy and `namespaces` is an empty array }; await findSuccess(relevantOpts, namespace); - expect(getSearchDslNS.getSearchDsl).toHaveBeenCalledWith(mappings, registry, relevantOpts); + expect(getSearchDslNS.getSearchDsl).toHaveBeenCalledWith(mappings, registry, { + ...relevantOpts, + type: [type], + }); }); it(`accepts KQL expression filter and passes KueryNode to getSearchDsl`, async () => { const findOpts = { - namespace, + namespaces: [namespace], search: 'foo*', searchFields: ['foo'], type: ['dashboard'], @@ -2649,7 +2854,7 @@ describe('SavedObjectsRepository', () => { it(`accepts KQL KueryNode filter and passes KueryNode to getSearchDsl`, async () => { const findOpts = { - namespace, + namespaces: [namespace], search: 'foo*', searchFields: ['foo'], type: ['dashboard'], @@ -2817,6 +3022,12 @@ describe('SavedObjectsRepository', () => { ); }; + it(`throws when options.namespace is '*'`, async () => { + await expect( + savedObjectsRepository.get(type, id, { namespace: ALL_NAMESPACES_STRING }) + ).rejects.toThrowError(createBadRequestError('"options.namespace" cannot be "*"')); + }); + it(`throws when type is invalid`, async () => { await expectNotFoundError('unknownType', id); expect(client.get).not.toHaveBeenCalled(); @@ -3008,6 +3219,14 @@ describe('SavedObjectsRepository', () => { ); }; + it(`throws when options.namespace is '*'`, async () => { + await expect( + savedObjectsRepository.incrementCounter(type, id, field, { + namespace: ALL_NAMESPACES_STRING, + }) + ).rejects.toThrowError(createBadRequestError('"options.namespace" cannot be "*"')); + }); + it(`throws when type is not a string`, async () => { const test = async (type) => { await expect( @@ -3664,6 +3883,12 @@ describe('SavedObjectsRepository', () => { ); }; + it(`throws when options.namespace is '*'`, async () => { + await expect( + savedObjectsRepository.update(type, id, attributes, { namespace: ALL_NAMESPACES_STRING }) + ).rejects.toThrowError(createBadRequestError('"options.namespace" cannot be "*"')); + }); + it(`throws when type is invalid`, async () => { await expectNotFoundError('unknownType', id); expect(client.update).not.toHaveBeenCalled(); diff --git a/src/core/server/saved_objects/service/lib/repository.ts b/src/core/server/saved_objects/service/lib/repository.ts index 125f97e7feb11..39aacd6b05b7b 100644 --- a/src/core/server/saved_objects/service/lib/repository.ts +++ b/src/core/server/saved_objects/service/lib/repository.ts @@ -67,7 +67,12 @@ import { } from '../../types'; import { SavedObjectTypeRegistry } from '../../saved_objects_type_registry'; import { validateConvertFilterToKueryNode } from './filter_utils'; -import { SavedObjectsUtils } from './utils'; +import { + ALL_NAMESPACES_STRING, + FIND_DEFAULT_PAGE, + FIND_DEFAULT_PER_PAGE, + SavedObjectsUtils, +} from './utils'; // BEWARE: The SavedObjectClient depends on the implementation details of the SavedObjectsRepository // so any breaking changes to this repository are considered breaking changes to the SavedObjectsClient. @@ -225,10 +230,23 @@ export class SavedObjectsRepository { references = [], refresh = DEFAULT_REFRESH_SETTING, originId, + initialNamespaces, version, } = options; const namespace = normalizeNamespace(options.namespace); + if (initialNamespaces) { + if (!this._registry.isMultiNamespace(type)) { + throw SavedObjectsErrorHelpers.createBadRequestError( + '"options.initialNamespaces" can only be used on multi-namespace types' + ); + } else if (!initialNamespaces.length) { + throw SavedObjectsErrorHelpers.createBadRequestError( + '"options.initialNamespaces" must be a non-empty array of strings' + ); + } + } + if (!this._allowedTypes.includes(type)) { throw SavedObjectsErrorHelpers.createUnsupportedTypeError(type); } @@ -242,9 +260,11 @@ export class SavedObjectsRepository { } else if (this._registry.isMultiNamespace(type)) { if (id && overwrite) { // we will overwrite a multi-namespace saved object if it exists; if that happens, ensure we preserve its included namespaces - savedObjectNamespaces = await this.preflightGetNamespaces(type, id, namespace); + // note: this check throws an error if the object is found but does not exist in this namespace + const existingNamespaces = await this.preflightGetNamespaces(type, id, namespace); + savedObjectNamespaces = initialNamespaces || existingNamespaces; } else { - savedObjectNamespaces = getSavedObjectNamespaces(namespace); + savedObjectNamespaces = initialNamespaces || getSavedObjectNamespaces(namespace); } } @@ -300,14 +320,25 @@ export class SavedObjectsRepository { let bulkGetRequestIndexCounter = 0; const expectedResults: Either[] = objects.map((object) => { + let error: DecoratedError | undefined; if (!this._allowedTypes.includes(object.type)) { + error = SavedObjectsErrorHelpers.createUnsupportedTypeError(object.type); + } else if (object.initialNamespaces) { + if (!this._registry.isMultiNamespace(object.type)) { + error = SavedObjectsErrorHelpers.createBadRequestError( + '"initialNamespaces" can only be used on multi-namespace types' + ); + } else if (!object.initialNamespaces.length) { + error = SavedObjectsErrorHelpers.createBadRequestError( + '"initialNamespaces" must be a non-empty array of strings' + ); + } + } + + if (error) { return { tag: 'Left' as 'Left', - error: { - id: object.id, - type: object.type, - error: errorContent(SavedObjectsErrorHelpers.createUnsupportedTypeError(object.type)), - }, + error: { id: object.id, type: object.type, error: errorContent(error) }, }; } @@ -357,7 +388,7 @@ export class SavedObjectsRepository { let versionProperties; const { esRequestIndex, - object: { version, ...object }, + object: { initialNamespaces, version, ...object }, method, } = expectedBulkGetResult.value; if (esRequestIndex !== undefined) { @@ -378,13 +409,14 @@ export class SavedObjectsRepository { }, }; } - savedObjectNamespaces = getSavedObjectNamespaces(namespace, docFound && actualResult); + savedObjectNamespaces = + initialNamespaces || getSavedObjectNamespaces(namespace, docFound && actualResult); versionProperties = getExpectedVersionProperties(version, actualResult); } else { if (this._registry.isSingleNamespace(object.type)) { savedObjectNamespace = namespace; } else if (this._registry.isMultiNamespace(object.type)) { - savedObjectNamespaces = getSavedObjectNamespaces(namespace); + savedObjectNamespaces = initialNamespaces || getSavedObjectNamespaces(namespace); } versionProperties = getExpectedVersionProperties(version); } @@ -553,7 +585,7 @@ export class SavedObjectsRepository { throw SavedObjectsErrorHelpers.createGenericNotFoundError(type, id); } - const { refresh = DEFAULT_REFRESH_SETTING } = options; + const { refresh = DEFAULT_REFRESH_SETTING, force } = options; const namespace = normalizeNamespace(options.namespace); const rawId = this._serializer.generateRawId(namespace, type, id); @@ -561,38 +593,14 @@ export class SavedObjectsRepository { if (this._registry.isMultiNamespace(type)) { preflightResult = await this.preflightCheckIncludesNamespace(type, id, namespace); - const existingNamespaces = getSavedObjectNamespaces(undefined, preflightResult); - const remainingNamespaces = existingNamespaces?.filter( - (x) => x !== SavedObjectsUtils.namespaceIdToString(namespace) - ); - - if (remainingNamespaces?.length) { - // if there is 1 or more namespace remaining, update the saved object - const time = this._getCurrentTime(); - - const doc = { - updated_at: time, - namespaces: remainingNamespaces, - }; - - const { statusCode } = await this.client.update( - { - id: rawId, - index: this.getIndexForType(type), - ...getExpectedVersionProperties(undefined, preflightResult), - refresh, - body: { - doc, - }, - }, - { ignore: [404] } + const existingNamespaces = getSavedObjectNamespaces(undefined, preflightResult) ?? []; + if ( + !force && + (existingNamespaces.length > 1 || existingNamespaces.includes(ALL_NAMESPACES_STRING)) + ) { + throw SavedObjectsErrorHelpers.createBadRequestError( + 'Unable to delete saved object that exists in multiple namespaces, use the `force` option to delete it anyway' ); - - if (statusCode === 404) { - // see "404s from missing index" above - throw SavedObjectsErrorHelpers.createGenericNotFoundError(type, id); - } - return {}; } } @@ -637,8 +645,8 @@ export class SavedObjectsRepository { namespace: string, options: SavedObjectsDeleteByNamespaceOptions = {} ): Promise { - if (!namespace || typeof namespace !== 'string') { - throw new TypeError(`namespace is required, and must be a string`); + if (!namespace || typeof namespace !== 'string' || namespace === '*') { + throw new TypeError(`namespace is required, and must be a string that is not equal to '*'`); } const allTypes = Object.keys(getRootPropertiesObjects(this._mappings)); @@ -693,37 +701,51 @@ export class SavedObjectsRepository { * @property {string} [options.preference] * @returns {promise} - { saved_objects: [{ id, type, version, attributes }], total, per_page, page } */ - async find({ - search, - defaultSearchOperator = 'OR', - searchFields, - rootSearchFields, - hasReference, - page = 1, - perPage = 20, - sortField, - sortOrder, - fields, - namespaces, - type, - filter, - preference, - }: SavedObjectsFindOptions): Promise> { - if (!type) { + async find(options: SavedObjectsFindOptions): Promise> { + const { + search, + defaultSearchOperator = 'OR', + searchFields, + rootSearchFields, + hasReference, + page = FIND_DEFAULT_PAGE, + perPage = FIND_DEFAULT_PER_PAGE, + sortField, + sortOrder, + fields, + namespaces, + type, + typeToNamespacesMap, + filter, + preference, + } = options; + + if (!type && !typeToNamespacesMap) { throw SavedObjectsErrorHelpers.createBadRequestError( 'options.type must be a string or an array of strings' ); + } else if (namespaces?.length === 0 && !typeToNamespacesMap) { + throw SavedObjectsErrorHelpers.createBadRequestError( + 'options.namespaces cannot be an empty array' + ); + } else if (type && typeToNamespacesMap) { + throw SavedObjectsErrorHelpers.createBadRequestError( + 'options.type must be an empty string when options.typeToNamespacesMap is used' + ); + } else if ((!namespaces || namespaces?.length) && typeToNamespacesMap) { + throw SavedObjectsErrorHelpers.createBadRequestError( + 'options.namespaces must be an empty array when options.typeToNamespacesMap is used' + ); } - const types = Array.isArray(type) ? type : [type]; + const types = type + ? Array.isArray(type) + ? type + : [type] + : Array.from(typeToNamespacesMap!.keys()); const allowedTypes = types.filter((t) => this._allowedTypes.includes(t)); if (allowedTypes.length === 0) { - return { - page, - per_page: perPage, - total: 0, - saved_objects: [], - }; + return SavedObjectsUtils.createEmptyFindResponse(options); } if (searchFields && !Array.isArray(searchFields)) { @@ -766,6 +788,7 @@ export class SavedObjectsRepository { sortField, sortOrder, namespaces, + typeToNamespacesMap, hasReference, kueryNode, }), @@ -1238,6 +1261,19 @@ export class SavedObjectsRepository { } const { attributes, references, version, namespace: objectNamespace } = object; + + if (objectNamespace === ALL_NAMESPACES_STRING) { + return { + tag: 'Left' as 'Left', + error: { + id, + type, + error: errorContent( + SavedObjectsErrorHelpers.createBadRequestError('"namespace" cannot be "*"') + ), + }, + }; + } // `objectNamespace` is a namespace string, while `namespace` is a namespace ID. // The object namespace string, if defined, will supersede the operation's namespace ID. @@ -1553,7 +1589,10 @@ export class SavedObjectsRepository { } const namespaces = raw._source.namespaces; - return namespaces?.includes(SavedObjectsUtils.namespaceIdToString(namespace)) ?? false; + const existsInNamespace = + namespaces?.includes(SavedObjectsUtils.namespaceIdToString(namespace)) || + namespaces?.includes('*'); + return existsInNamespace ?? false; } /** @@ -1680,8 +1719,15 @@ function getSavedObjectNamespaces( * Ensure that a namespace is always in its namespace ID representation. * This allows `'default'` to be used interchangeably with `undefined`. */ -const normalizeNamespace = (namespace?: string) => - namespace === undefined ? namespace : SavedObjectsUtils.namespaceStringToId(namespace); +const normalizeNamespace = (namespace?: string) => { + if (namespace === ALL_NAMESPACES_STRING) { + throw SavedObjectsErrorHelpers.createBadRequestError('"options.namespace" cannot be "*"'); + } else if (namespace === undefined) { + return namespace; + } else { + return SavedObjectsUtils.namespaceStringToId(namespace); + } +}; /** * Extracts the contents of a decorated error to return the attributes for bulk operations. diff --git a/src/core/server/saved_objects/service/lib/search_dsl/query_params.test.ts b/src/core/server/saved_objects/service/lib/search_dsl/query_params.test.ts index 4adc92df31805..330fa5066051f 100644 --- a/src/core/server/saved_objects/service/lib/search_dsl/query_params.test.ts +++ b/src/core/server/saved_objects/service/lib/search_dsl/query_params.test.ts @@ -22,6 +22,7 @@ import { esKuery } from '../../../es_query'; type KueryNode = any; import { typeRegistryMock } from '../../../saved_objects_type_registry.mock'; +import { ALL_NAMESPACES_STRING } from '../utils'; import { getQueryParams } from './query_params'; const registry = typeRegistryMock.create(); @@ -50,6 +51,41 @@ const ALL_TYPE_SUBSETS = ALL_TYPES.reduce( .filter((x) => x.length) // exclude empty set .map((x) => (x.length === 1 ? x[0] : x)); // if a subset is a single string, destructure it +const createTypeClause = (type: string, namespaces?: string[]) => { + if (registry.isMultiNamespace(type)) { + const array = [...(namespaces ?? ['default']), ALL_NAMESPACES_STRING]; + return { + bool: { + must: expect.arrayContaining([{ terms: { namespaces: array } }]), + must_not: [{ exists: { field: 'namespace' } }], + }, + }; + } else if (registry.isSingleNamespace(type)) { + const nonDefaultNamespaces = namespaces?.filter((n) => n !== 'default') ?? []; + const should: any = []; + if (nonDefaultNamespaces.length > 0) { + should.push({ terms: { namespace: nonDefaultNamespaces } }); + } + if (namespaces?.includes('default')) { + should.push({ bool: { must_not: [{ exists: { field: 'namespace' } }] } }); + } + return { + bool: { + must: [{ term: { type } }], + should: expect.arrayContaining(should), + minimum_should_match: 1, + must_not: [{ exists: { field: 'namespaces' } }], + }, + }; + } + // isNamespaceAgnostic + return { + bool: expect.objectContaining({ + must_not: [{ exists: { field: 'namespace' } }, { exists: { field: 'namespaces' } }], + }), + }; +}; + /** * Note: these tests cases are defined in the order they appear in the source code, for readability's sake */ @@ -198,40 +234,6 @@ describe('#getQueryParams', () => { }); describe('`namespaces` parameter', () => { - const createTypeClause = (type: string, namespaces?: string[]) => { - if (registry.isMultiNamespace(type)) { - return { - bool: { - must: expect.arrayContaining([{ terms: { namespaces: namespaces ?? ['default'] } }]), - must_not: [{ exists: { field: 'namespace' } }], - }, - }; - } else if (registry.isSingleNamespace(type)) { - const nonDefaultNamespaces = namespaces?.filter((n) => n !== 'default') ?? []; - const should: any = []; - if (nonDefaultNamespaces.length > 0) { - should.push({ terms: { namespace: nonDefaultNamespaces } }); - } - if (namespaces?.includes('default')) { - should.push({ bool: { must_not: [{ exists: { field: 'namespace' } }] } }); - } - return { - bool: { - must: [{ term: { type } }], - should: expect.arrayContaining(should), - minimum_should_match: 1, - must_not: [{ exists: { field: 'namespaces' } }], - }, - }; - } - // isNamespaceAgnostic - return { - bool: expect.objectContaining({ - must_not: [{ exists: { field: 'namespace' } }, { exists: { field: 'namespaces' } }], - }), - }; - }; - const expectResult = (result: Result, ...typeClauses: any) => { expect(result.query.bool.filter).toEqual( expect.arrayContaining([ @@ -281,6 +283,37 @@ describe('#getQueryParams', () => { test(['default']); }); }); + + describe('`typeToNamespacesMap` parameter', () => { + const expectResult = (result: Result, ...typeClauses: any) => { + expect(result.query.bool.filter).toEqual( + expect.arrayContaining([ + { bool: expect.objectContaining({ should: typeClauses, minimum_should_match: 1 }) }, + ]) + ); + }; + + it('supersedes `type` and `namespaces` parameters', () => { + const result = getQueryParams({ + mappings, + registry, + type: ['pending', 'saved', 'shared', 'global'], + namespaces: ['foo', 'bar', 'default'], + typeToNamespacesMap: new Map([ + ['pending', ['foo']], // 'pending' is only authorized in the 'foo' namespace + // 'saved' is not authorized in any namespaces + ['shared', ['bar', 'default']], // 'shared' is only authorized in the 'bar' and 'default' namespaces + ['global', ['foo', 'bar', 'default']], // 'global' is authorized in all namespaces (which are ignored anyway) + ]), + }); + expectResult( + result, + createTypeClause('pending', ['foo']), + createTypeClause('shared', ['bar', 'default']), + createTypeClause('global') + ); + }); + }); }); describe('search clause (query.bool.must.simple_query_string)', () => { diff --git a/src/core/server/saved_objects/service/lib/search_dsl/query_params.ts b/src/core/server/saved_objects/service/lib/search_dsl/query_params.ts index 642d51c70766e..8bd9c7d8312ee 100644 --- a/src/core/server/saved_objects/service/lib/search_dsl/query_params.ts +++ b/src/core/server/saved_objects/service/lib/search_dsl/query_params.ts @@ -22,7 +22,7 @@ type KueryNode = any; import { getRootPropertiesObjects, IndexMapping } from '../../../mappings'; import { ISavedObjectTypeRegistry } from '../../../saved_objects_type_registry'; -import { DEFAULT_NAMESPACE_STRING } from '../utils'; +import { ALL_NAMESPACES_STRING, DEFAULT_NAMESPACE_STRING } from '../utils'; /** * Gets the types based on the type. Uses mappings to support @@ -84,7 +84,10 @@ function getClauseForType( if (registry.isMultiNamespace(type)) { return { bool: { - must: [{ term: { type } }, { terms: { namespaces } }], + must: [ + { term: { type } }, + { terms: { namespaces: [...namespaces, ALL_NAMESPACES_STRING] } }, + ], must_not: [{ exists: { field: 'namespace' } }], }, }; @@ -129,6 +132,7 @@ interface QueryParams { registry: ISavedObjectTypeRegistry; namespaces?: string[]; type?: string | string[]; + typeToNamespacesMap?: Map; search?: string; searchFields?: string[]; rootSearchFields?: string[]; @@ -145,6 +149,7 @@ export function getQueryParams({ registry, namespaces, type, + typeToNamespacesMap, search, searchFields, rootSearchFields, @@ -152,7 +157,10 @@ export function getQueryParams({ hasReference, kueryNode, }: QueryParams) { - const types = getTypes(mappings, type); + const types = getTypes( + mappings, + typeToNamespacesMap ? Array.from(typeToNamespacesMap.keys()) : type + ); // A de-duplicated set of namespaces makes for a more effecient query. // @@ -163,9 +171,12 @@ export function getQueryParams({ // since that is consistent with how a single-namespace search behaves in the OSS distribution. Leaving the wildcard in place // would result in no results being returned, as the wildcard is treated as a literal, and not _actually_ as a wildcard. // We had a good discussion around the tradeoffs here: https://github.com/elastic/kibana/pull/67644#discussion_r441055716 - const normalizedNamespaces = namespaces - ? Array.from(new Set(namespaces.map((x) => (x === '*' ? DEFAULT_NAMESPACE_STRING : x)))) - : undefined; + const normalizeNamespaces = (namespacesToNormalize?: string[]) => + namespacesToNormalize + ? Array.from( + new Set(namespacesToNormalize.map((x) => (x === '*' ? DEFAULT_NAMESPACE_STRING : x))) + ) + : undefined; const bool: any = { filter: [ @@ -197,9 +208,12 @@ export function getQueryParams({ }, ] : undefined, - should: types.map((shouldType) => - getClauseForType(registry, normalizedNamespaces, shouldType) - ), + should: types.map((shouldType) => { + const normalizedNamespaces = normalizeNamespaces( + typeToNamespacesMap ? typeToNamespacesMap.get(shouldType) : namespaces + ); + return getClauseForType(registry, normalizedNamespaces, shouldType); + }), minimum_should_match: 1, }, }, diff --git a/src/core/server/saved_objects/service/lib/search_dsl/search_dsl.test.ts b/src/core/server/saved_objects/service/lib/search_dsl/search_dsl.test.ts index 62e629ad33cc8..7276e505bce7d 100644 --- a/src/core/server/saved_objects/service/lib/search_dsl/search_dsl.test.ts +++ b/src/core/server/saved_objects/service/lib/search_dsl/search_dsl.test.ts @@ -57,10 +57,11 @@ describe('getSearchDsl', () => { }); describe('passes control', () => { - it('passes (mappings, schema, namespaces, type, search, searchFields, rootSearchFields, hasReference) to getQueryParams', () => { + it('passes (mappings, schema, namespaces, type, typeToNamespacesMap, search, searchFields, rootSearchFields, hasReference) to getQueryParams', () => { const opts = { namespaces: ['foo-namespace'], type: 'foo', + typeToNamespacesMap: new Map(), search: 'bar', searchFields: ['baz'], rootSearchFields: ['qux'], @@ -78,6 +79,7 @@ describe('getSearchDsl', () => { registry, namespaces: opts.namespaces, type: opts.type, + typeToNamespacesMap: opts.typeToNamespacesMap, search: opts.search, searchFields: opts.searchFields, rootSearchFields: opts.rootSearchFields, diff --git a/src/core/server/saved_objects/service/lib/search_dsl/search_dsl.ts b/src/core/server/saved_objects/service/lib/search_dsl/search_dsl.ts index aa79a10b2a9be..858770579fb9e 100644 --- a/src/core/server/saved_objects/service/lib/search_dsl/search_dsl.ts +++ b/src/core/server/saved_objects/service/lib/search_dsl/search_dsl.ts @@ -35,6 +35,7 @@ interface GetSearchDslOptions { sortField?: string; sortOrder?: string; namespaces?: string[]; + typeToNamespacesMap?: Map; hasReference?: { type: string; id: string; @@ -56,6 +57,7 @@ export function getSearchDsl( sortField, sortOrder, namespaces, + typeToNamespacesMap, hasReference, kueryNode, } = options; @@ -74,6 +76,7 @@ export function getSearchDsl( registry, namespaces, type, + typeToNamespacesMap, search, searchFields, rootSearchFields, diff --git a/src/core/server/saved_objects/service/lib/utils.test.ts b/src/core/server/saved_objects/service/lib/utils.test.ts index ea4fa68242bea..ac06ca9275783 100644 --- a/src/core/server/saved_objects/service/lib/utils.test.ts +++ b/src/core/server/saved_objects/service/lib/utils.test.ts @@ -17,10 +17,11 @@ * under the License. */ +import { SavedObjectsFindOptions } from '../../types'; import { SavedObjectsUtils } from './utils'; describe('SavedObjectsUtils', () => { - const { namespaceIdToString, namespaceStringToId } = SavedObjectsUtils; + const { namespaceIdToString, namespaceStringToId, createEmptyFindResponse } = SavedObjectsUtils; describe('#namespaceIdToString', () => { it('converts `undefined` to default namespace string', () => { @@ -54,4 +55,26 @@ describe('SavedObjectsUtils', () => { test(''); }); }); + + describe('#createEmptyFindResponse', () => { + it('returns expected result', () => { + const options = {} as SavedObjectsFindOptions; + expect(createEmptyFindResponse(options)).toEqual({ + page: 1, + per_page: 20, + total: 0, + saved_objects: [], + }); + }); + + it('handles `page` field', () => { + const options = { page: 42 } as SavedObjectsFindOptions; + expect(createEmptyFindResponse(options).page).toEqual(42); + }); + + it('handles `perPage` field', () => { + const options = { perPage: 42 } as SavedObjectsFindOptions; + expect(createEmptyFindResponse(options).per_page).toEqual(42); + }); + }); }); diff --git a/src/core/server/saved_objects/service/lib/utils.ts b/src/core/server/saved_objects/service/lib/utils.ts index 6101ad57cc401..69abc37089218 100644 --- a/src/core/server/saved_objects/service/lib/utils.ts +++ b/src/core/server/saved_objects/service/lib/utils.ts @@ -17,7 +17,13 @@ * under the License. */ +import { SavedObjectsFindOptions } from '../../types'; +import { SavedObjectsFindResponse } from '..'; + export const DEFAULT_NAMESPACE_STRING = 'default'; +export const ALL_NAMESPACES_STRING = '*'; +export const FIND_DEFAULT_PAGE = 1; +export const FIND_DEFAULT_PER_PAGE = 20; /** * @public @@ -50,4 +56,17 @@ export class SavedObjectsUtils { return namespace !== DEFAULT_NAMESPACE_STRING ? namespace : undefined; }; + + /** + * Creates an empty response for a find operation. This is only intended to be used by saved objects client wrappers. + */ + public static createEmptyFindResponse = ({ + page = FIND_DEFAULT_PAGE, + perPage = FIND_DEFAULT_PER_PAGE, + }: SavedObjectsFindOptions): SavedObjectsFindResponse => ({ + page, + per_page: perPage, + total: 0, + saved_objects: [], + }); } diff --git a/src/core/server/saved_objects/service/saved_objects_client.ts b/src/core/server/saved_objects/service/saved_objects_client.ts index 8c96116de49cb..6782998d1bf1e 100644 --- a/src/core/server/saved_objects/service/saved_objects_client.ts +++ b/src/core/server/saved_objects/service/saved_objects_client.ts @@ -50,6 +50,13 @@ export interface SavedObjectsCreateOptions extends SavedObjectsBaseOptions { refresh?: MutatingOperationRefreshSetting; /** Optional ID of the original saved object, if this object's `id` was regenerated */ originId?: string; + /** + * Optional initial namespaces for the object to be created in. If this is defined, it will supersede the namespace ID that is in + * {@link SavedObjectsCreateOptions}. + * + * Note: this can only be used for multi-namespace object types. + */ + initialNamespaces?: string[]; } /** @@ -66,6 +73,13 @@ export interface SavedObjectsBulkCreateObject { migrationVersion?: SavedObjectsMigrationVersion; /** Optional ID of the original saved object, if this object's `id` was regenerated */ originId?: string; + /** + * Optional initial namespaces for the object to be created in. If this is defined, it will supersede the namespace ID that is in + * {@link SavedObjectsCreateOptions}. + * + * Note: this can only be used for multi-namespace object types. + */ + initialNamespaces?: string[]; } /** @@ -211,6 +225,8 @@ export interface SavedObjectsBulkUpdateOptions extends SavedObjectsBaseOptions { export interface SavedObjectsDeleteOptions extends SavedObjectsBaseOptions { /** The Elasticsearch Refresh setting for this operation */ refresh?: MutatingOperationRefreshSetting; + /** Force deletion of an object that exists in multiple namespaces */ + force?: boolean; } /** diff --git a/src/core/server/saved_objects/types.ts b/src/core/server/saved_objects/types.ts index 1885f5ec50139..01128e4f8cf51 100644 --- a/src/core/server/saved_objects/types.ts +++ b/src/core/server/saved_objects/types.ts @@ -89,6 +89,14 @@ export interface SavedObjectsFindOptions { defaultSearchOperator?: 'AND' | 'OR'; filter?: string | KueryNode; namespaces?: string[]; + /** + * This map defines each type to search for, and the namespace(s) to search for the type in; this is only intended to be used by a saved + * object client wrapper. + * If this is defined, it supersedes the `type` and `namespaces` fields when building the Elasticsearch query. + * Any types that are not included in this map will be excluded entirely. + * If a type is included but its value is undefined, the operation will search for that type in the Default namespace. + */ + typeToNamespacesMap?: Map; /** An optional ES preference value to be used for the query **/ preference?: string; } diff --git a/src/core/server/server.api.md b/src/core/server/server.api.md index 11a14457784fd..20bd102e6f507 100644 --- a/src/core/server/server.api.md +++ b/src/core/server/server.api.md @@ -348,7 +348,6 @@ export const config: { sniffInterval: Type; sniffOnConnectionFault: Type; hosts: Type; - preserveHost: Type; username: Type; password: Type; requestHeadersWhitelist: Type; @@ -356,7 +355,6 @@ export const config: { shardTimeout: Type; requestTimeout: Type; pingTimeout: Type; - startupTimeout: Type; logQueries: Type; ssl: import("@kbn/config-schema").ObjectType<{ verificationMode: Type<"none" | "certificate" | "full">; @@ -403,9 +401,102 @@ export interface ContextSetup { createContextContainer>(): IContextContainer; } +// @internal +export interface CoreConfigUsageData { + // (undocumented) + elasticsearch: { + sniffOnStart: boolean; + sniffIntervalMs?: number; + sniffOnConnectionFault: boolean; + numberOfHostsConfigured: number; + requestHeadersWhitelistConfigured: boolean; + customHeadersConfigured: boolean; + shardTimeoutMs: number; + requestTimeoutMs: number; + pingTimeoutMs: number; + logQueries: boolean; + ssl: { + verificationMode: 'none' | 'certificate' | 'full'; + certificateAuthoritiesConfigured: boolean; + certificateConfigured: boolean; + keyConfigured: boolean; + keystoreConfigured: boolean; + truststoreConfigured: boolean; + alwaysPresentCertificate: boolean; + }; + apiVersion: string; + healthCheckDelayMs: number; + }; + // (undocumented) + http: { + basePathConfigured: boolean; + maxPayloadInBytes: number; + rewriteBasePath: boolean; + keepaliveTimeout: number; + socketTimeout: number; + compression: { + enabled: boolean; + referrerWhitelistConfigured: boolean; + }; + xsrf: { + disableProtection: boolean; + whitelistConfigured: boolean; + }; + requestId: { + allowFromAnyIp: boolean; + ipAllowlistConfigured: boolean; + }; + ssl: { + certificateAuthoritiesConfigured: boolean; + certificateConfigured: boolean; + cipherSuites: string[]; + keyConfigured: boolean; + keystoreConfigured: boolean; + truststoreConfigured: boolean; + redirectHttpFromPortConfigured: boolean; + supportedProtocols: string[]; + clientAuthentication: 'none' | 'optional' | 'required'; + }; + }; + // (undocumented) + logging: { + appendersTypesUsed: string[]; + loggersConfiguredCount: number; + }; + // (undocumented) + savedObjects: { + maxImportPayloadBytes: number; + maxImportExportSizeBytes: number; + }; +} + +// @internal +export interface CoreEnvironmentUsageData { + // (undocumented) + memory: { + heapTotalBytes: number; + heapUsedBytes: number; + heapSizeLimit: number; + }; +} + // @internal (undocumented) export type CoreId = symbol; +// @internal +export interface CoreServicesUsageData { + // (undocumented) + savedObjects: { + indices: { + alias: string; + docsCount: number; + docsDeleted: number; + storeSizeBytes: number; + primaryStoreSizeBytes: number; + }[]; + }; +} + // @public export interface CoreSetup { // (undocumented) @@ -440,6 +531,8 @@ export interface CoreStart { auditTrail: AuditTrailStart; // (undocumented) capabilities: CapabilitiesStart; + // @internal (undocumented) + coreUsageData: CoreUsageDataStart; // (undocumented) elasticsearch: ElasticsearchServiceStart; // (undocumented) @@ -460,6 +553,21 @@ export interface CoreStatus { savedObjects: ServiceStatus; } +// @internal +export interface CoreUsageData { + // (undocumented) + config: CoreConfigUsageData; + // (undocumented) + environment: CoreEnvironmentUsageData; + // (undocumented) + services: CoreServicesUsageData; +} + +// @internal +export interface CoreUsageDataStart { + getCoreUsageData(): Promise; +} + // @public (undocumented) export interface CountResponse { // (undocumented) @@ -864,10 +972,6 @@ export interface IndexSettingsDeprecationInfo { // @public (undocumented) export interface IRenderOptions { - // @internal @deprecated - app?: { - getId(): string; - }; includeUserSettings?: boolean; // @internal @deprecated vars?: Record; @@ -943,6 +1047,7 @@ export class KibanaRequest>; - // (undocumented) - getVars(id: string, request: KibanaRequest | LegacyRequest, injected?: LegacyVars): Promise>; - // Warning: (ae-forgotten-export) The symbol "VarsInjector" needs to be exported by the entry point index.d.ts - // - // (undocumented) - injectUiAppVars(id: string, injector: VarsInjector): void; - } - // @public @deprecated (undocumented) export interface LegacyRequest extends Request { } @@ -1311,16 +1401,6 @@ export class LegacyScopedClusterClient implements ILegacyScopedClusterClient { callAsInternalUser(endpoint: string, clientParams?: Record, options?: LegacyCallAPIOptions): Promise; } -// Warning: (ae-forgotten-export) The symbol "LegacyPlugins" needs to be exported by the entry point index.d.ts -// -// @internal @deprecated (undocumented) -export interface LegacyServiceDiscoverPlugins extends LegacyPlugins { - // (undocumented) - pluginExtendedConfig: LegacyConfig; - // (undocumented) - settings: LegacyVars; -} - // @public @deprecated (undocumented) export interface LegacyServiceSetupDeps { // Warning: (ae-forgotten-export) The symbol "LegacyCoreSetup" needs to be exported by the entry point index.d.ts @@ -1345,31 +1425,6 @@ export interface LegacyServiceStartDeps { plugins: Record; } -// @internal @deprecated (undocumented) -export interface LegacyUiExports { - // Warning: (ae-forgotten-export) The symbol "VarsProvider" needs to be exported by the entry point index.d.ts - // - // (undocumented) - defaultInjectedVarProviders?: VarsProvider[]; - // Warning: (ae-forgotten-export) The symbol "VarsReplacer" needs to be exported by the entry point index.d.ts - // - // (undocumented) - injectedVarsReplacers?: VarsReplacer[]; - // Warning: (ae-forgotten-export) The symbol "LegacyNavLinkSpec" needs to be exported by the entry point index.d.ts - // - // (undocumented) - navLinkSpecs?: LegacyNavLinkSpec[] | null; - // Warning: (ae-forgotten-export) The symbol "LegacyAppSpec" needs to be exported by the entry point index.d.ts - // - // (undocumented) - uiAppSpecs?: Array; - // (undocumented) - unknown?: [{ - pluginSpec: LegacyPluginSpec; - type: unknown; - }]; -} - // Warning: (ae-forgotten-export) The symbol "lifecycleResponseFactory" needs to be exported by the entry point index.d.ts // // @public @@ -1475,9 +1530,16 @@ export interface OnPreResponseInfo { statusCode: number; } +// @public +export interface OnPreResponseRender { + body: string; + headers?: ResponseHeaders; +} + // @public export interface OnPreResponseToolkit { next: (responseExtensions?: OnPreResponseExtensions) => OnPreResponseResult; + render: (responseRender: OnPreResponseRender) => OnPreResponseResult; } // Warning: (ae-forgotten-export) The symbol "OnPreRoutingResult" needs to be exported by the entry point index.d.ts @@ -1874,6 +1936,7 @@ export interface SavedObjectsBulkCreateObject { attributes: T; // (undocumented) id?: string; + initialNamespaces?: string[]; migrationVersion?: SavedObjectsMigrationVersion; originId?: string; // (undocumented) @@ -2031,6 +2094,7 @@ export interface SavedObjectsCoreFieldMapping { // @public (undocumented) export interface SavedObjectsCreateOptions extends SavedObjectsBaseOptions { id?: string; + initialNamespaces?: string[]; migrationVersion?: SavedObjectsMigrationVersion; originId?: string; overwrite?: boolean; @@ -2057,6 +2121,7 @@ export interface SavedObjectsDeleteFromNamespacesResponse { // @public (undocumented) export interface SavedObjectsDeleteOptions extends SavedObjectsBaseOptions { + force?: boolean; refresh?: MutatingOperationRefreshSetting; } @@ -2176,6 +2241,7 @@ export interface SavedObjectsFindOptions { sortOrder?: string; // (undocumented) type: string | string[]; + typeToNamespacesMap?: Map; } // @public @@ -2387,7 +2453,7 @@ export class SavedObjectsRepository { deleteByNamespace(namespace: string, options?: SavedObjectsDeleteByNamespaceOptions): Promise; deleteFromNamespaces(type: string, id: string, namespaces: string[], options?: SavedObjectsDeleteFromNamespacesOptions): Promise; // (undocumented) - find({ search, defaultSearchOperator, searchFields, rootSearchFields, hasReference, page, perPage, sortField, sortOrder, fields, namespaces, type, filter, preference, }: SavedObjectsFindOptions): Promise>; + find(options: SavedObjectsFindOptions): Promise>; get(type: string, id: string, options?: SavedObjectsBaseOptions): Promise>; incrementCounter(type: string, id: string, counterFieldName: string, options?: SavedObjectsIncrementCounterOptions): Promise; update(type: string, id: string, attributes: Partial, options?: SavedObjectsUpdateOptions): Promise>; @@ -2495,6 +2561,7 @@ export interface SavedObjectsUpdateResponse extends Omit({ page, perPage, }: SavedObjectsFindOptions) => SavedObjectsFindResponse; static namespaceIdToString: (namespace?: string | undefined) => string; static namespaceStringToId: (namespace: string) => string | undefined; } @@ -2731,7 +2798,6 @@ export const validBodyOutput: readonly ["data", "stream"]; // Warnings were encountered during analysis: // // src/core/server/http/router/response.ts:316:3 - (ae-forgotten-export) The symbol "KibanaResponse" needs to be exported by the entry point index.d.ts -// src/core/server/legacy/types.ts:135:16 - (ae-forgotten-export) The symbol "LegacyPluginSpec" needs to be exported by the entry point index.d.ts // src/core/server/plugins/types.ts:274:3 - (ae-forgotten-export) The symbol "KibanaConfigType" needs to be exported by the entry point index.d.ts // src/core/server/plugins/types.ts:274:3 - (ae-forgotten-export) The symbol "SharedGlobalConfigKeys" needs to be exported by the entry point index.d.ts // src/core/server/plugins/types.ts:277:3 - (ae-forgotten-export) The symbol "SavedObjectsConfigType" needs to be exported by the entry point index.d.ts diff --git a/src/core/server/server.test.ts b/src/core/server/server.test.ts index 3258840d09df2..51defb7d0392e 100644 --- a/src/core/server/server.test.ts +++ b/src/core/server/server.test.ts @@ -215,3 +215,20 @@ test(`doesn't setup core services if legacy config validation fails`, async () = expect(mockStatusService.setup).not.toHaveBeenCalled(); expect(mockLoggingService.setup).not.toHaveBeenCalled(); }); + +test(`doesn't validate config if env.isDevClusterMaster is true`, async () => { + const devParentEnv = Env.createDefault(REPO_ROOT, { + ...getEnvOptions(), + isDevClusterMaster: true, + }); + + const server = new Server(rawConfigService, devParentEnv, logger); + await server.setup(); + + expect(mockEnsureValidConfiguration).not.toHaveBeenCalled(); + expect(mockContextService.setup).toHaveBeenCalled(); + expect(mockAuditTrailService.setup).toHaveBeenCalled(); + expect(mockHttpService.setup).toHaveBeenCalled(); + expect(mockElasticsearchService.setup).toHaveBeenCalled(); + expect(mockSavedObjectsService.setup).toHaveBeenCalled(); +}); diff --git a/src/core/server/server.ts b/src/core/server/server.ts index 8502f563cb0c2..f38cac4f43768 100644 --- a/src/core/server/server.ts +++ b/src/core/server/server.ts @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ - +import apm from 'elastic-apm-node'; import { config as pathConfig } from '@kbn/utils'; import { mapToObject } from '@kbn/std'; import { ConfigService, Env, RawConfigurationProvider, coreDeprecationProvider } from './config'; @@ -48,6 +48,8 @@ import { config as statusConfig } from './status'; import { ContextService } from './context'; import { RequestHandlerContext } from '.'; import { InternalCoreSetup, InternalCoreStart, ServiceConfigDescriptor } from './internal_types'; +import { CoreUsageDataService } from './core_usage_data'; +import { CoreRouteHandlerContext } from './core_route_handler_context'; const coreId = Symbol('core'); const rootConfigPath = ''; @@ -71,6 +73,7 @@ export class Server { private readonly logging: LoggingService; private readonly coreApp: CoreApp; private readonly auditTrail: AuditTrailService; + private readonly coreUsageData: CoreUsageDataService; #pluginsInitialized?: boolean; private coreStart?: InternalCoreStart; @@ -102,10 +105,12 @@ export class Server { this.httpResources = new HttpResourcesService(core); this.auditTrail = new AuditTrailService(core); this.logging = new LoggingService(core); + this.coreUsageData = new CoreUsageDataService(core); } public async setup() { this.log.debug('setting up server'); + const setupTransaction = apm.startTransaction('server_setup', 'kibana_platform'); const environmentSetup = await this.environment.setup(); @@ -113,11 +118,15 @@ export class Server { const { pluginTree, uiPlugins } = await this.plugins.discover({ environment: environmentSetup, }); - const legacyPlugins = await this.legacy.discoverPlugins(); - - // Immediately terminate in case of invalid configuration - await this.configService.validate(); - await ensureValidConfiguration(this.configService, legacyPlugins); + const legacyConfigSetup = await this.legacy.setupLegacyConfig(); + + // rely on dev server to validate config, don't validate in the parent process + if (!this.env.isDevClusterMaster) { + // Immediately terminate in case of invalid configuration + // This needs to be done after plugin discovery + await this.configService.validate(); + await ensureValidConfiguration(this.configService, legacyConfigSetup); + } const contextServiceSetup = this.context.setup({ // We inject a fake "legacy plugin" with dependencies on every plugin so that legacy plugins: @@ -166,7 +175,6 @@ export class Server { const renderingSetup = await this.rendering.setup({ http: httpSetup, status: statusSetup, - legacyPlugins, uiPlugins, }); @@ -179,6 +187,8 @@ export class Server { loggingSystem: this.loggingSystem, }); + this.coreUsageData.setup({ metrics: metricsSetup }); + const coreSetup: InternalCoreSetup = { capabilities: capabilitiesSetup, context: contextServiceSetup, @@ -207,24 +217,33 @@ export class Server { this.registerCoreContext(coreSetup); this.coreApp.setup(coreSetup); + setupTransaction?.end(); return coreSetup; } public async start() { this.log.debug('starting server'); + const startTransaction = apm.startTransaction('server_start', 'kibana_platform'); + const auditTrailStart = this.auditTrail.start(); const elasticsearchStart = await this.elasticsearch.start({ auditTrail: auditTrailStart, }); + const soStartSpan = startTransaction?.startSpan('saved_objects.migration', 'migration'); const savedObjectsStart = await this.savedObjects.start({ elasticsearch: elasticsearchStart, pluginsInitialized: this.#pluginsInitialized, }); + soStartSpan?.end(); const capabilitiesStart = this.capabilities.start(); const uiSettingsStart = await this.uiSettings.start(); const metricsStart = await this.metrics.start(); const httpStart = this.http.getStartContract(); + const coreUsageDataStart = this.coreUsageData.start({ + elasticsearch: elasticsearchStart, + savedObjects: savedObjectsStart, + }); this.coreStart = { capabilities: capabilitiesStart, @@ -234,6 +253,7 @@ export class Server { savedObjects: savedObjectsStart, uiSettings: uiSettingsStart, auditTrail: auditTrailStart, + coreUsageData: coreUsageDataStart, }; const pluginsStart = await this.plugins.start(this.coreStart); @@ -248,10 +268,7 @@ export class Server { await this.http.start(); - await this.rendering.start({ - legacy: this.legacy, - }); - + startTransaction?.end(); return this.coreStart; } @@ -276,25 +293,7 @@ export class Server { coreId, 'core', async (context, req, res): Promise => { - const coreStart = this.coreStart!; - const savedObjectsClient = coreStart.savedObjects.getScopedClient(req); - - return { - savedObjects: { - client: savedObjectsClient, - typeRegistry: coreStart.savedObjects.getTypeRegistry(), - }, - elasticsearch: { - client: coreStart.elasticsearch.client.asScoped(req), - legacy: { - client: coreStart.elasticsearch.legacy.client.asScoped(req), - }, - }, - uiSettings: { - client: coreStart.uiSettings.asScopedToClient(savedObjectsClient), - }, - auditor: coreStart.auditTrail.asScoped(req), - }; + return new CoreRouteHandlerContext(this.coreStart!, req); } ); } diff --git a/src/core/server/status/plugins_status.test.ts b/src/core/server/status/plugins_status.test.ts index a75dc8c283698..176e2414a8d04 100644 --- a/src/core/server/status/plugins_status.test.ts +++ b/src/core/server/status/plugins_status.test.ts @@ -161,13 +161,13 @@ describe('PluginStatusService', () => { }, b: { level: ServiceStatusLevels.degraded, - summary: '[2] services are degraded', + summary: '[savedObjects]: savedObjects degraded', detail: 'See the status page for more information', meta: expect.any(Object), }, c: { level: ServiceStatusLevels.degraded, - summary: '[3] services are degraded', + summary: '[savedObjects]: savedObjects degraded', detail: 'See the status page for more information', meta: expect.any(Object), }, @@ -186,13 +186,13 @@ describe('PluginStatusService', () => { }, b: { level: ServiceStatusLevels.critical, - summary: '[2] services are critical', + summary: '[elasticsearch]: elasticsearch critical', detail: 'See the status page for more information', meta: expect.any(Object), }, c: { level: ServiceStatusLevels.critical, - summary: '[3] services are critical', + summary: '[elasticsearch]: elasticsearch critical', detail: 'See the status page for more information', meta: expect.any(Object), }, diff --git a/src/core/server/status/plugins_status.ts b/src/core/server/status/plugins_status.ts index 113d59b327c11..988f2d9969ccb 100644 --- a/src/core/server/status/plugins_status.ts +++ b/src/core/server/status/plugins_status.ts @@ -33,7 +33,17 @@ interface Deps { export class PluginsStatusService { private readonly pluginStatuses = new Map>(); private readonly update$ = new BehaviorSubject(true); - constructor(private readonly deps: Deps) {} + private readonly defaultInheritedStatus$: Observable; + + constructor(private readonly deps: Deps) { + this.defaultInheritedStatus$ = this.deps.core$.pipe( + map((coreStatus) => { + return getSummaryStatus(Object.entries(coreStatus), { + allAvailableSummary: `All dependencies are available`, + }); + }) + ); + } public set(plugin: PluginName, status$: Observable) { this.pluginStatuses.set(plugin, status$); @@ -57,14 +67,24 @@ export class PluginsStatusService { } public getDerivedStatus$(plugin: PluginName): Observable { - return combineLatest([this.deps.core$, this.getDependenciesStatus$(plugin)]).pipe( - map(([coreStatus, pluginStatuses]) => { - return getSummaryStatus( - [...Object.entries(coreStatus), ...Object.entries(pluginStatuses)], - { - allAvailableSummary: `All dependencies are available`, - } - ); + return this.update$.pipe( + switchMap(() => { + // Only go up the dependency tree if any of this plugin's dependencies have a custom status + // Helps eliminate memory overhead of creating thousands of Observables unnecessarily. + if (this.anyCustomStatuses(plugin)) { + return combineLatest([this.deps.core$, this.getDependenciesStatus$(plugin)]).pipe( + map(([coreStatus, pluginStatuses]) => { + return getSummaryStatus( + [...Object.entries(coreStatus), ...Object.entries(pluginStatuses)], + { + allAvailableSummary: `All dependencies are available`, + } + ); + }) + ); + } else { + return this.defaultInheritedStatus$; + } }) ); } @@ -95,4 +115,17 @@ export class PluginsStatusService { }) ); } + + /** + * Determines whether or not this plugin or any plugin in it's dependency tree have a custom status registered. + */ + private anyCustomStatuses(plugin: PluginName): boolean { + if (this.pluginStatuses.get(plugin)) { + return true; + } + + return this.deps.pluginDependencies + .get(plugin)! + .reduce((acc, depName) => acc || this.anyCustomStatuses(depName), false as boolean); + } } diff --git a/src/core/server/status/status_service.ts b/src/core/server/status/status_service.ts index 9acf93f2f8197..62f226405e81a 100644 --- a/src/core/server/status/status_service.ts +++ b/src/core/server/status/status_service.ts @@ -70,10 +70,10 @@ export class StatusService implements CoreService { const core$ = this.setupCoreStatus({ elasticsearch, savedObjects }); this.pluginsStatus = new PluginsStatusService({ core$, pluginDependencies }); - const overall$: Observable = combineLatest( + const overall$: Observable = combineLatest([ core$, - this.pluginsStatus.getAll$() - ).pipe( + this.pluginsStatus.getAll$(), + ]).pipe( // Prevent many emissions at once from dependency status resolution from making this too noisy debounceTime(500), map(([coreStatus, pluginsStatus]) => { diff --git a/src/core/tsconfig.json b/src/core/tsconfig.json index b8780321e11dd..a3531057767d4 100644 --- a/src/core/tsconfig.json +++ b/src/core/tsconfig.json @@ -2,7 +2,7 @@ "extends": "../../tsconfig.base.json", "compilerOptions": { "composite": true, - "outDir": "./target", + "outDir": "./target/types", "emitDeclarationOnly": true, "declaration": true, "declarationMap": true diff --git a/src/core/typings.ts b/src/core/typings.ts index a84e1c01d2bd2..f271d0b03e0d3 100644 --- a/src/core/typings.ts +++ b/src/core/typings.ts @@ -17,34 +17,6 @@ * under the License. */ -declare module 'query-string' { - type ArrayFormat = 'bracket' | 'index' | 'none'; - - export interface ParseOptions { - arrayFormat?: ArrayFormat; - sort: ((itemLeft: string, itemRight: string) => number) | false; - } - - export interface ParsedQuery { - [key: string]: T | T[] | null | undefined; - } - - export function parse(str: string, options?: ParseOptions): ParsedQuery; - - export function parseUrl(str: string, options?: ParseOptions): { url: string; query: any }; - - export interface StringifyOptions { - strict?: boolean; - encode?: boolean; - arrayFormat?: ArrayFormat; - sort: ((itemLeft: string, itemRight: string) => number) | false; - } - - export function stringify(obj: object, options?: StringifyOptions): string; - - export function extract(str: string): string; -} - type DeeplyMockedKeys = { [P in keyof T]: T[P] extends (...args: any[]) => any ? jest.MockInstance, Parameters> diff --git a/src/dev/build/tasks/bin/scripts/kibana b/src/dev/build/tasks/bin/scripts/kibana index 3283e17008e7c..c606436c7b83f 100755 --- a/src/dev/build/tasks/bin/scripts/kibana +++ b/src/dev/build/tasks/bin/scripts/kibana @@ -26,4 +26,4 @@ if [ -f "${CONFIG_DIR}/node.options" ]; then KBN_NODE_OPTS="$(grep -v ^# < ${CONFIG_DIR}/node.options | xargs)" fi -NODE_OPTIONS="--no-warnings --max-http-header-size=65536 $KBN_NODE_OPTS $NODE_OPTIONS" NODE_ENV=production exec "${NODE}" "${DIR}/src/cli" ${@} +NODE_OPTIONS="--no-warnings --max-http-header-size=65536 $KBN_NODE_OPTS $NODE_OPTIONS" NODE_ENV=production exec "${NODE}" "${DIR}/src/cli/dist" ${@} diff --git a/src/dev/build/tasks/bin/scripts/kibana-keystore b/src/dev/build/tasks/bin/scripts/kibana-keystore index d811e70095548..9d2fd64c1c4eb 100755 --- a/src/dev/build/tasks/bin/scripts/kibana-keystore +++ b/src/dev/build/tasks/bin/scripts/kibana-keystore @@ -26,4 +26,4 @@ if [ -f "${CONFIG_DIR}/node.options" ]; then KBN_NODE_OPTS="$(grep -v ^# < ${CONFIG_DIR}/node.options | xargs)" fi -NODE_OPTIONS="$KBN_NODE_OPTS $NODE_OPTIONS" "${NODE}" "${DIR}/src/cli_keystore" "$@" +NODE_OPTIONS="$KBN_NODE_OPTS $NODE_OPTIONS" "${NODE}" "${DIR}/src/cli_keystore/dist" "$@" diff --git a/src/dev/build/tasks/bin/scripts/kibana-keystore.bat b/src/dev/build/tasks/bin/scripts/kibana-keystore.bat index 7e227141c8ba3..2214769efc410 100755 --- a/src/dev/build/tasks/bin/scripts/kibana-keystore.bat +++ b/src/dev/build/tasks/bin/scripts/kibana-keystore.bat @@ -28,7 +28,7 @@ IF EXIST "%CONFIG_DIR%\node.options" ( ) TITLE Kibana Keystore -"%NODE%" "%DIR%\src\cli_keystore" %* +"%NODE%" "%DIR%\src\cli_keystore\dist" %* :finally diff --git a/src/dev/build/tasks/bin/scripts/kibana-plugin b/src/dev/build/tasks/bin/scripts/kibana-plugin index f4486e9cf85fb..78fdb7702643f 100755 --- a/src/dev/build/tasks/bin/scripts/kibana-plugin +++ b/src/dev/build/tasks/bin/scripts/kibana-plugin @@ -26,4 +26,4 @@ if [ -f "${CONFIG_DIR}/node.options" ]; then KBN_NODE_OPTS="$(grep -v ^# < ${CONFIG_DIR}/node.options | xargs)" fi -NODE_OPTIONS="--no-warnings $KBN_NODE_OPTS $NODE_OPTIONS" NODE_ENV=production exec "${NODE}" "${DIR}/src/cli_plugin" "$@" +NODE_OPTIONS="--no-warnings $KBN_NODE_OPTS $NODE_OPTIONS" NODE_ENV=production exec "${NODE}" "${DIR}/src/cli_plugin/dist" "$@" diff --git a/src/dev/build/tasks/bin/scripts/kibana-plugin.bat b/src/dev/build/tasks/bin/scripts/kibana-plugin.bat index 4fb30977fda06..0a6d135565e50 100755 --- a/src/dev/build/tasks/bin/scripts/kibana-plugin.bat +++ b/src/dev/build/tasks/bin/scripts/kibana-plugin.bat @@ -32,7 +32,7 @@ IF EXIST "%CONFIG_DIR%\node.options" ( set "NODE_OPTIONS=--no-warnings %NODE_OPTIONS%" TITLE Kibana Server -"%NODE%" "%DIR%\src\cli_plugin" %* +"%NODE%" "%DIR%\src\cli_plugin\dist" %* :finally diff --git a/src/dev/build/tasks/bin/scripts/kibana.bat b/src/dev/build/tasks/bin/scripts/kibana.bat index 98dd9ec05a48c..19bf8157ed7c8 100755 --- a/src/dev/build/tasks/bin/scripts/kibana.bat +++ b/src/dev/build/tasks/bin/scripts/kibana.bat @@ -34,7 +34,7 @@ set "NODE_OPTIONS=--no-warnings --max-http-header-size=65536 %NODE_OPTIONS%" :: This should run independently as the last instruction :: as we need NODE_OPTIONS previously set to expand -"%NODE%" "%DIR%\src\cli" %* +"%NODE%" "%DIR%\src\cli\dist" %* :finally diff --git a/src/dev/build/tasks/copy_source_task.ts b/src/dev/build/tasks/copy_source_task.ts index 948e2357effb0..b0ace3c63d82e 100644 --- a/src/dev/build/tasks/copy_source_task.ts +++ b/src/dev/build/tasks/copy_source_task.ts @@ -35,9 +35,12 @@ export const CopySource: Task = { '!src/fixtures/**', '!src/cli/cluster/**', '!src/cli/repl/**', + '!src/cli/dev.js', '!src/functional_test_runner/**', '!src/dev/**', - '!**/public/**', + // this is the dev-only entry + '!src/setup_node_env/index.js', + '!**/public/**/*.{js,ts,tsx,json}', 'typings/**', 'config/kibana.yml', 'config/node.options', diff --git a/src/dev/build/tasks/create_empty_dirs_and_files_task.ts b/src/dev/build/tasks/create_empty_dirs_and_files_task.ts index a72c6a4598338..48745572def78 100644 --- a/src/dev/build/tasks/create_empty_dirs_and_files_task.ts +++ b/src/dev/build/tasks/create_empty_dirs_and_files_task.ts @@ -17,7 +17,7 @@ * under the License. */ -import { mkdirp, write, Task } from '../lib'; +import { mkdirp, Task } from '../lib'; export const CreateEmptyDirsAndFiles: Task = { description: 'Creating some empty directories and files to prevent file-permission issues', @@ -26,7 +26,6 @@ export const CreateEmptyDirsAndFiles: Task = { await Promise.all([ mkdirp(build.resolvePath('plugins')), mkdirp(build.resolvePath('data/optimize')), - write(build.resolvePath('data/optimize/.babel_register_cache.json'), '{}'), ]); }, }; diff --git a/src/dev/build/tasks/os_packages/docker_generator/resources/bin/kibana-docker b/src/dev/build/tasks/os_packages/docker_generator/resources/bin/kibana-docker index b02b7cc16ec4a..0039debe383bd 100755 --- a/src/dev/build/tasks/os_packages/docker_generator/resources/bin/kibana-docker +++ b/src/dev/build/tasks/os_packages/docker_generator/resources/bin/kibana-docker @@ -8,11 +8,11 @@ # # eg. Setting the environment variable: # -# ELASTICSEARCH_STARTUPTIMEOUT=60 +# ELASTICSEARCH_LOGQUERIES=true # # will cause Kibana to be invoked with: # -# --elasticsearch.startupTimeout=60 +# --elasticsearch.logQueries=true kibana_vars=( console.enabled @@ -30,7 +30,6 @@ kibana_vars=( elasticsearch.logQueries elasticsearch.password elasticsearch.pingTimeout - elasticsearch.preserveHost elasticsearch.requestHeadersWhitelist elasticsearch.requestTimeout elasticsearch.shardTimeout @@ -47,7 +46,6 @@ kibana_vars=( elasticsearch.ssl.truststore.path elasticsearch.ssl.truststore.password elasticsearch.ssl.verificationMode - elasticsearch.startupTimeout elasticsearch.username i18n.locale interpreter.enableInVisualize @@ -95,6 +93,7 @@ kibana_vars=( path.data pid.file regionmap + security.showInsecureClusterWarning server.basePath server.customResponseHeaders server.compression.enabled @@ -161,6 +160,7 @@ kibana_vars=( xpack.code.security.gitHostWhitelist xpack.code.security.gitProtocolWhitelist xpack.encryptedSavedObjects.encryptionKey + xpack.encryptedSavedObjects.keyRotation.decryptionOnlyKeys xpack.graph.enabled xpack.graph.canEditDrillDownUrls xpack.graph.savePolicy @@ -235,6 +235,7 @@ kibana_vars=( xpack.security.cookieName xpack.security.enabled xpack.security.encryptionKey + xpack.security.sameSiteCookies xpack.security.secureCookies xpack.security.sessionTimeout xpack.security.session.idleTimeout diff --git a/src/dev/build/tasks/os_packages/docker_generator/templates/Dockerfile b/src/dev/build/tasks/os_packages/docker_generator/templates/Dockerfile index 24649a52b729b..e7523c1bf6032 100644 --- a/src/dev/build/tasks/os_packages/docker_generator/templates/Dockerfile +++ b/src/dev/build/tasks/os_packages/docker_generator/templates/Dockerfile @@ -58,6 +58,11 @@ RUN curl -L -o /usr/local/bin/dumb-init https://github.com/Yelp/dumb-init/releas RUN echo "37f2c1f0372a45554f1b89924fbb134fc24c3756efaedf11e07f599494e0eff9 /usr/local/bin/dumb-init" | sha256sum -c - RUN chmod +x /usr/local/bin/dumb-init +RUN mkdir /usr/share/fonts/local +RUN curl -L -o /usr/share/fonts/local/NotoSansCJK-Regular.ttc https://github.com/googlefonts/noto-cjk/raw/NotoSansV2.001/NotoSansCJK-Regular.ttc +RUN echo "5dcd1c336cc9344cb77c03a0cd8982ca8a7dc97d620fd6c9c434e02dcb1ceeb3 /usr/share/fonts/local/NotoSansCJK-Regular.ttc" | sha256sum -c - +RUN fc-cache -v + # Bring in Kibana from the initial stage. COPY --from=builder --chown=1000:0 /usr/share/kibana /usr/share/kibana WORKDIR /usr/share/kibana diff --git a/src/dev/build/tasks/os_packages/service_templates/sysv/etc/default/kibana b/src/dev/build/tasks/os_packages/service_templates/sysv/etc/default/kibana index ee019d348ed97..9c9f58ded350b 100644 --- a/src/dev/build/tasks/os_packages/service_templates/sysv/etc/default/kibana +++ b/src/dev/build/tasks/os_packages/service_templates/sysv/etc/default/kibana @@ -10,6 +10,4 @@ nice="" # The default behavior is to simply log a message "program stop failed; still running" KILL_ON_STOP_TIMEOUT=0 -BABEL_CACHE_PATH="/var/lib/kibana/optimize/.babel_register_cache.json" - KBN_PATH_CONF="/etc/kibana" diff --git a/src/dev/ci_setup/setup_env.sh b/src/dev/ci_setup/setup_env.sh index 72ec73ad810e6..8ec80ac295c73 100644 --- a/src/dev/ci_setup/setup_env.sh +++ b/src/dev/ci_setup/setup_env.sh @@ -24,15 +24,6 @@ export NODE_OPTIONS="$NODE_OPTIONS --max-old-space-size=4096" ### export FORCE_COLOR=1 -### -### The @babel/register cache collects the build output from each file in -### a map, in memory, and then when the process exits it writes that to the -### babel cache file as a JSON encoded object. Stringifying that object -### causes OOMs on CI regularly enough that we need to find another solution, -### and until we do we need to disable the cache -### -export BABEL_DISABLE_CACHE=true - ### ### check that we seem to be in a kibana project ### diff --git a/src/dev/code_coverage/docs/team_assignment/README.md b/src/dev/code_coverage/docs/team_assignment/README.md index 3509fb5c2a4fc..f2884fb42b8d7 100644 --- a/src/dev/code_coverage/docs/team_assignment/README.md +++ b/src/dev/code_coverage/docs/team_assignment/README.md @@ -1,8 +1,41 @@ -# Team Assignment Ingestion Pipeline +# Code Coverage Team Assignments -Team assignment will occur once per ci run. -Team assignment uses an ingest pipeline. +Team assignment occurs once per ci run. -The coverage user has the coverage admin role. +The "orchestration" entry point is a [Jenkinsfile Scripted Pipeline](https://github.com/elastic/kibana/blob/f73bc48b3bbbb5ad2042c1aa267aea2150b7b742/.ci/Jenkinsfile_coverage#L21) +This Jenkinsfile runs a [shell script](https://github.com/elastic/kibana/blob/master/src/dev/code_coverage/shell_scripts/generate_team_assignments_and_ingest_coverage.sh#L33) that kicks everything off. +The end result is the data is ingested to our [Kibana Stats Cluster](https://kibana-stats.elastic.dev/app/dashboards#/view/58b8db70-62f9-11ea-8312-7f2d69b79843?_g=(filters%3A!()%2CrefreshInterval%3A(pause%3A!t%2Cvalue%3A0)%2Ctime%3A(from%3Anow-7d%2Cto%3Anow))) -This role must have the rights depicted below ![Cluster Rights](./security_privleges.png) +## Team Assignment Parsing (from .github/CODEOWNERS) +We add additional metadata to the CODEOWNERS file. +This metadata allows users to assign teams to paths, in a friendly location. +Example CODEOWNERS Block: +_notice the coverage delimiter `#CC# ...`_ +``` +/x-pack/test/functional/es_archives/endpoint/ @elastic/endpoint-app-team @elastic/siem +/x-pack/test/plugin_functional/plugins/resolver_test/ @elastic/endpoint-app-team @elastic/siem +/x-pack/test/plugin_functional/test_suites/resolver/ @elastic/endpoint-app-team @elastic/siem +#CC# /x-pack/legacy/plugins/siem/ @elastic/siem +#CC# /x-pack/plugins/siem/ @elastic/siem +#CC# /x-pack/plugins/security_solution/ @elastic/siem +``` +The first 3 lines above fill the usual purpose of the CODEOWNERS file and cause PRs modifying files in these paths to require approval by the listed team(s). +They also attribute files in those paths for purpose of code coverage reporting. +The last 3 lines above ONLY attribute files in those paths for purpose of code coverage reporting. + +## Team Assignment Data File Creation (Before Ingestion) +We create a data file containing all paths in the repo, with a team assigned. +Example Team Assignments Block: +``` +x-pack/plugins/security_solution/common/constants.ts siem +x-pack/plugins/security_solution/common/detection_engine/build_exceptions_query.test.ts siem +x-pack/plugins/security_solution/common/detection_engine/build_exceptions_query.ts siem +... +``` + +## Team Assignment Data File Usage (During Code Coverage Ingestion) +Subsequently, we use the data file during ingestion. +We search the data file, for any given "coveredFilePath" + - Given the above assignments block, and lets say the "coveredFilePath" during ingestion is + - `x-pack/plugins/security_solution/common/constants.ts` + - The team assignment would be `siem` in our [Kibana Stats Cluster](https://kibana-stats.elastic.dev/app/dashboards#/view/58b8db70-62f9-11ea-8312-7f2d69b79843?_g=(filters%3A!()%2CrefreshInterval%3A(pause%3A!t%2Cvalue%3A0)%2Ctime%3A(from%3Anow-7d%2Cto%3Anow))) diff --git a/src/dev/code_coverage/docs/team_assignment/security_privleges.png b/src/dev/code_coverage/docs/team_assignment/security_privleges.png deleted file mode 100644 index 002774f3ecefa..0000000000000 Binary files a/src/dev/code_coverage/docs/team_assignment/security_privleges.png and /dev/null differ diff --git a/src/dev/code_coverage/ingest_coverage/__tests__/either.test.js b/src/dev/code_coverage/ingest_coverage/__tests__/either.test.js index 3a493539f6743..0ae55508e8434 100644 --- a/src/dev/code_coverage/ingest_coverage/__tests__/either.test.js +++ b/src/dev/code_coverage/ingest_coverage/__tests__/either.test.js @@ -53,7 +53,7 @@ describe(`either datatype functions`, () => { expect(sut.inspect()).to.be('Right(undefined)'); }); }); - describe(`'fromNullable`, () => { + describe(`fromNullable`, () => { it(`should continue processing if a truthy is calculated`, () => { attempt({ detail: 'x' }).fold( () => {}, @@ -64,4 +64,18 @@ describe(`either datatype functions`, () => { attempt(false).fold(expectNull, () => {}); }); }); + describe(`predicate fns`, () => { + it(`right.isRight() is true`, () => { + expect(Either.right('a').isRight()).to.be(true); + }); + it(`right.isLeft() is false`, () => { + expect(Either.right('a').isLeft()).to.be(false); + }); + it(`left.isLeft() is true`, () => { + expect(Either.left().isLeft()).to.be(true); + }); + it(`left.isRight() is true`, () => { + expect(Either.left().isRight()).to.be(false); + }); + }); }); diff --git a/src/dev/code_coverage/ingest_coverage/__tests__/enumerate_patterns.test.js b/src/dev/code_coverage/ingest_coverage/__tests__/enumerate_patterns.test.js new file mode 100644 index 0000000000000..371695337ed56 --- /dev/null +++ b/src/dev/code_coverage/ingest_coverage/__tests__/enumerate_patterns.test.js @@ -0,0 +1,60 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import expect from '@kbn/expect'; +import { enumeratePatterns } from '../team_assignment/enumerate_patterns'; +import { ToolingLog, REPO_ROOT } from '@kbn/dev-utils'; + +const log = new ToolingLog({ + level: 'info', + writeTo: process.stdout, +}); + +describe(`enumeratePatterns`, () => { + it(`should resolve x-pack/plugins/reporting/server/browsers/extract/unzip.js to kibana-reporting`, () => { + const actual = enumeratePatterns(REPO_ROOT)(log)( + new Map([['x-pack/plugins/reporting', ['kibana-reporting']]]) + ); + + expect( + actual[0].includes( + 'x-pack/plugins/reporting/server/browsers/extract/unzip.js kibana-reporting' + ) + ).to.be(true); + }); + it(`should resolve src/plugins/charts/public/static/color_maps/color_maps.ts to kibana-app`, () => { + const actual = enumeratePatterns(REPO_ROOT)(log)( + new Map([['src/plugins/charts/public/static/color_maps', ['kibana-app']]]) + ); + + expect(actual[0][0]).to.be( + 'src/plugins/charts/public/static/color_maps/color_maps.ts kibana-app' + ); + }); + it(`should resolve x-pack/plugins/security_solution/public/common/components/exceptions/builder/translations.ts to kibana-security`, () => { + const short = 'x-pack/plugins/security_solution'; + const actual = enumeratePatterns(REPO_ROOT)(log)(new Map([[short, ['kibana-security']]])); + + expect( + actual[0].includes( + `${short}/public/common/components/exceptions/builder/translations.ts kibana-security` + ) + ).to.be(true); + }); +}); diff --git a/src/dev/code_coverage/ingest_coverage/__tests__/enumeration_helpers.test.js b/src/dev/code_coverage/ingest_coverage/__tests__/enumeration_helpers.test.js new file mode 100644 index 0000000000000..f480135b45ac6 --- /dev/null +++ b/src/dev/code_coverage/ingest_coverage/__tests__/enumeration_helpers.test.js @@ -0,0 +1,50 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import expect from '@kbn/expect'; +import { tryPath } from '../team_assignment/enumeration_helpers'; + +describe(`enumeration helper fns`, () => { + describe(`tryPath`, () => { + describe(`w/o glob file paths`, () => { + it(`should return a right on an existing path`, () => { + const aPath = 'src/dev/code_coverage/ingest_coverage/ingest.js'; + const actual = tryPath(aPath); + expect(actual.isRight()).to.be(true); + }); + it(`should return a left on a non existing path`, () => { + const aPath = 'src/dev/code_coverage/ingest_coverage/does_not_exist.js'; + const actual = tryPath(aPath); + expect(actual.isLeft()).to.be(true); + }); + }); + describe(`with glob file paths`, () => { + it(`should not error when the glob expands to nothing, but instead return a Left`, () => { + const aPath = 'src/legacy/core_plugins/kibana/public/home/*.ts'; + const actual = tryPath(aPath); + expect(actual.isLeft()).to.be(true); + }); + it(`should return a right on a glob that does indeed expand`, () => { + const aPath = 'src/dev/code_coverage/ingest_coverage/*.js'; + const actual = tryPath(aPath); + expect(actual.isRight()).to.be(true); + }); + }); + }); +}); diff --git a/src/dev/code_coverage/ingest_coverage/__tests__/ingest_helpers.test.js b/src/dev/code_coverage/ingest_coverage/__tests__/ingest_helpers.test.js index 7ca7279e0d64c..f668c1f86f5b0 100644 --- a/src/dev/code_coverage/ingest_coverage/__tests__/ingest_helpers.test.js +++ b/src/dev/code_coverage/ingest_coverage/__tests__/ingest_helpers.test.js @@ -18,13 +18,8 @@ */ import expect from '@kbn/expect'; -import { maybeTeamAssign, whichIndex } from '../ingest_helpers'; -import { - TOTALS_INDEX, - RESEARCH_TOTALS_INDEX, - RESEARCH_COVERAGE_INDEX, - // COVERAGE_INDEX, -} from '../constants'; +import { whichIndex } from '../ingest_helpers'; +import { TOTALS_INDEX, RESEARCH_TOTALS_INDEX, RESEARCH_COVERAGE_INDEX } from '../constants'; describe(`Ingest Helper fns`, () => { describe(`whichIndex`, () => { @@ -56,20 +51,4 @@ describe(`Ingest Helper fns`, () => { }); }); }); - describe(`maybeTeamAssign`, () => { - describe(`against a coverage index`, () => { - it(`should have the pipeline prop`, () => { - const actual = maybeTeamAssign(true, { a: 'blah' }); - expect(actual).to.have.property('pipeline'); - }); - }); - describe(`against a totals index`, () => { - describe(`for "prod"`, () => { - it(`should not have the pipeline prop`, () => { - const actual = maybeTeamAssign(false, { b: 'blah' }); - expect(actual).not.to.have.property('pipeline'); - }); - }); - }); - }); }); diff --git a/src/dev/code_coverage/ingest_coverage/__tests__/mocks/team_assign_mock.json b/src/dev/code_coverage/ingest_coverage/__tests__/mocks/team_assign_mock.json deleted file mode 100644 index 355c484a84fa3..0000000000000 --- a/src/dev/code_coverage/ingest_coverage/__tests__/mocks/team_assign_mock.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "abc": "123" -} diff --git a/src/dev/code_coverage/ingest_coverage/__tests__/mocks/team_assign_mock.txt b/src/dev/code_coverage/ingest_coverage/__tests__/mocks/team_assign_mock.txt new file mode 100644 index 0000000000000..d8924bd563f30 --- /dev/null +++ b/src/dev/code_coverage/ingest_coverage/__tests__/mocks/team_assign_mock.txt @@ -0,0 +1,194 @@ +x-pack/plugins/dashboard_enhanced/public/index.ts kibana-app +x-pack/plugins/dashboard_enhanced/public/mocks.ts kibana-app +x-pack/plugins/dashboard_enhanced/public/plugin.ts kibana-app +x-pack/plugins/dashboard_enhanced/public/services/drilldowns/actions/drilldown_shared.ts kibana-app +x-pack/plugins/dashboard_enhanced/public/services/drilldowns/actions/flyout_create_drilldown/flyout_create_drilldown.test.tsx kibana-app +x-pack/plugins/dashboard_enhanced/public/services/drilldowns/actions/flyout_create_drilldown/flyout_create_drilldown.tsx kibana-app +x-pack/plugins/dashboard_enhanced/public/services/drilldowns/actions/flyout_create_drilldown/index.ts kibana-app +x-pack/plugins/dashboard_enhanced/public/services/drilldowns/actions/flyout_edit_drilldown/flyout_edit_drilldown.test.tsx kibana-app +x-pack/plugins/dashboard_enhanced/public/services/drilldowns/actions/flyout_edit_drilldown/flyout_edit_drilldown.tsx kibana-app +x-pack/plugins/dashboard_enhanced/public/services/drilldowns/actions/flyout_edit_drilldown/i18n.ts kibana-app +x-pack/plugins/dashboard_enhanced/public/services/drilldowns/actions/flyout_edit_drilldown/index.tsx kibana-app +x-pack/plugins/dashboard_enhanced/public/services/drilldowns/actions/flyout_edit_drilldown/menu_item.test.tsx kibana-app +x-pack/plugins/dashboard_enhanced/public/services/drilldowns/actions/flyout_edit_drilldown/menu_item.tsx kibana-app +x-pack/plugins/dashboard_enhanced/public/services/drilldowns/actions/index.ts kibana-app +x-pack/plugins/dashboard_enhanced/public/services/drilldowns/actions/test_helpers.ts kibana-app +x-pack/plugins/dashboard_enhanced/public/services/drilldowns/dashboard_drilldowns_services.ts kibana-app +x-pack/plugins/dashboard_enhanced/public/services/drilldowns/dashboard_to_dashboard_drilldown/components/collect_config_container.tsx kibana-app +x-pack/plugins/dashboard_enhanced/public/services/drilldowns/dashboard_to_dashboard_drilldown/components/dashboard_drilldown_config/dashboard_drilldown_config.story.tsx kibana-app +x-pack/plugins/dashboard_enhanced/public/services/drilldowns/dashboard_to_dashboard_drilldown/components/dashboard_drilldown_config/dashboard_drilldown_config.test.tsx kibana-app +x-pack/plugins/dashboard_enhanced/public/services/drilldowns/dashboard_to_dashboard_drilldown/components/dashboard_drilldown_config/dashboard_drilldown_config.tsx kibana-app +x-pack/plugins/dashboard_enhanced/public/services/drilldowns/dashboard_to_dashboard_drilldown/components/dashboard_drilldown_config/i18n.ts kibana-app +x-pack/plugins/dashboard_enhanced/public/services/drilldowns/dashboard_to_dashboard_drilldown/components/dashboard_drilldown_config/index.ts kibana-app +x-pack/plugins/dashboard_enhanced/public/services/drilldowns/dashboard_to_dashboard_drilldown/components/i18n.ts kibana-app +x-pack/plugins/dashboard_enhanced/public/services/drilldowns/dashboard_to_dashboard_drilldown/components/index.ts kibana-app +x-pack/plugins/dashboard_enhanced/public/services/drilldowns/dashboard_to_dashboard_drilldown/constants.ts kibana-app +x-pack/plugins/dashboard_enhanced/public/services/drilldowns/dashboard_to_dashboard_drilldown/drilldown.test.tsx kibana-app +x-pack/plugins/dashboard_enhanced/public/services/drilldowns/dashboard_to_dashboard_drilldown/drilldown.tsx kibana-app +x-pack/plugins/dashboard_enhanced/public/services/drilldowns/dashboard_to_dashboard_drilldown/i18n.ts kibana-app +x-pack/plugins/dashboard_enhanced/public/services/drilldowns/dashboard_to_dashboard_drilldown/index.ts kibana-app +x-pack/plugins/dashboard_enhanced/public/services/drilldowns/dashboard_to_dashboard_drilldown/types.ts kibana-app +x-pack/plugins/dashboard_enhanced/public/services/drilldowns/index.ts kibana-app +x-pack/plugins/dashboard_enhanced/public/services/index.ts kibana-app +x-pack/plugins/dashboard_enhanced/scripts/storybook.js kibana-app +x-pack/plugins/discover_enhanced/common/config.ts kibana-app +x-pack/plugins/discover_enhanced/common/index.ts kibana-app +x-pack/plugins/discover_enhanced/public/actions/explore_data/abstract_explore_data_action.ts kibana-app +x-pack/plugins/discover_enhanced/public/actions/explore_data/explore_data_chart_action.test.ts kibana-app +x-pack/plugins/discover_enhanced/public/actions/explore_data/explore_data_chart_action.ts kibana-app +x-pack/plugins/discover_enhanced/public/actions/explore_data/explore_data_context_menu_action.test.ts kibana-app +x-pack/plugins/discover_enhanced/public/actions/explore_data/explore_data_context_menu_action.ts kibana-app +x-pack/plugins/discover_enhanced/public/actions/explore_data/index.ts kibana-app +x-pack/plugins/discover_enhanced/public/actions/explore_data/kibana_url.ts kibana-app +x-pack/plugins/discover_enhanced/public/actions/explore_data/shared.ts kibana-app +x-pack/plugins/discover_enhanced/public/actions/index.ts kibana-app +x-pack/plugins/discover_enhanced/public/index.ts kibana-app +x-pack/plugins/discover_enhanced/public/plugin.ts kibana-app +x-pack/plugins/discover_enhanced/server/config.ts kibana-app +x-pack/plugins/discover_enhanced/server/index.ts kibana-app +x-pack/plugins/discover_enhanced/server/plugin.ts kibana-app +x-pack/plugins/lens/common/api.ts kibana-app +x-pack/plugins/lens/common/constants.ts kibana-app +x-pack/plugins/lens/common/index.ts kibana-app +x-pack/plugins/lens/common/types.ts kibana-app +x-pack/plugins/lens/config.ts kibana-app +x-pack/plugins/lens/public/app_plugin/app.test.tsx kibana-app +x-pack/plugins/lens/public/app_plugin/app.tsx kibana-app +x-pack/plugins/lens/public/app_plugin/index.ts kibana-app +x-pack/plugins/lens/public/app_plugin/mounter.tsx kibana-app +x-pack/plugins/lens/public/datatable_visualization/expression.test.tsx kibana-app +x-pack/plugins/lens/public/datatable_visualization/expression.tsx kibana-app +x-pack/plugins/lens/public/datatable_visualization/index.ts kibana-app +x-pack/plugins/lens/public/datatable_visualization/visualization.test.tsx kibana-app +x-pack/plugins/lens/public/datatable_visualization/visualization.tsx kibana-app +x-pack/plugins/lens/public/debounced_component/debounced_component.test.tsx kibana-app +x-pack/plugins/lens/public/debounced_component/debounced_component.tsx kibana-app +x-pack/plugins/lens/public/debounced_component/index.ts kibana-app +x-pack/plugins/lens/public/drag_drop/drag_drop.test.tsx kibana-app +x-pack/plugins/lens/public/drag_drop/drag_drop.tsx kibana-app +x-pack/plugins/lens/public/drag_drop/index.ts kibana-app +x-pack/plugins/lens/public/drag_drop/providers.test.tsx kibana-app +x-pack/plugins/lens/public/drag_drop/providers.tsx kibana-app +x-pack/plugins/lens/public/editor_frame_service/editor_frame/__mocks__/expression_helpers.ts kibana-app +x-pack/plugins/lens/public/editor_frame_service/editor_frame/__mocks__/suggestion_helpers.ts kibana-app +x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/config_panel.tsx kibana-app +x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/dimension_popover.tsx kibana-app +x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/index.ts kibana-app +x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/layer_actions.test.ts kibana-app +x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/layer_actions.ts kibana-app +x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/layer_panel.test.tsx kibana-app +x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/layer_panel.tsx kibana-app +x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/layer_settings.tsx kibana-app +x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/types.ts kibana-app +x-pack/plugins/lens/public/editor_frame_service/editor_frame/data_panel_wrapper.tsx kibana-app +x-pack/plugins/lens/public/editor_frame_service/editor_frame/editor_frame.test.tsx kibana-app +x-pack/plugins/lens/public/editor_frame_service/editor_frame/editor_frame.tsx kibana-app +x-pack/plugins/lens/public/editor_frame_service/editor_frame/expression_helpers.ts kibana-app +x-pack/plugins/lens/public/editor_frame_service/editor_frame/frame_layout.tsx kibana-app +x-pack/plugins/lens/public/editor_frame_service/editor_frame/index.ts kibana-app +x-pack/plugins/lens/public/editor_frame_service/editor_frame/save.test.ts kibana-app +x-pack/plugins/lens/public/editor_frame_service/editor_frame/save.ts kibana-app +x-pack/plugins/lens/public/editor_frame_service/editor_frame/state_helpers.ts kibana-app +x-pack/plugins/lens/public/editor_frame_service/editor_frame/state_management.test.ts kibana-app +x-pack/plugins/lens/public/editor_frame_service/editor_frame/state_management.ts kibana-app +x-pack/plugins/lens/public/editor_frame_service/editor_frame/suggestion_helpers.test.ts kibana-app +x-pack/plugins/lens/public/editor_frame_service/editor_frame/suggestion_helpers.ts kibana-app +x-pack/plugins/lens/public/editor_frame_service/editor_frame/suggestion_panel.test.tsx kibana-app +x-pack/plugins/lens/public/editor_frame_service/editor_frame/suggestion_panel.tsx kibana-app +x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/chart_switch.test.tsx kibana-app +x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/chart_switch.tsx kibana-app +x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/index.ts kibana-app +x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/workspace_panel.test.tsx kibana-app +x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/workspace_panel.tsx kibana-app +x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/workspace_panel_wrapper.test.tsx kibana-app +x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/workspace_panel_wrapper.tsx kibana-app +x-pack/plugins/lens/public/editor_frame_service/embeddable/embeddable.test.tsx kibana-app +x-pack/plugins/lens/public/editor_frame_service/embeddable/embeddable.tsx kibana-app +x-pack/plugins/lens/public/editor_frame_service/embeddable/embeddable_factory.ts kibana-app +x-pack/plugins/lens/public/editor_frame_service/embeddable/expression_wrapper.tsx kibana-app +x-pack/plugins/lens/public/editor_frame_service/format_column.ts kibana-app +x-pack/plugins/lens/public/editor_frame_service/index.ts kibana-app +x-pack/plugins/lens/public/editor_frame_service/merge_tables.test.ts kibana-app +x-pack/plugins/lens/public/editor_frame_service/merge_tables.ts kibana-app +x-pack/plugins/lens/public/editor_frame_service/mocks.tsx kibana-app +x-pack/plugins/lens/public/editor_frame_service/service.test.tsx kibana-app +x-pack/plugins/lens/public/editor_frame_service/service.tsx kibana-app +x-pack/plugins/lens/public/help_menu_util.tsx kibana-app +x-pack/plugins/lens/public/id_generator/id_generator.test.ts kibana-app +x-pack/plugins/lens/public/id_generator/id_generator.ts kibana-app +x-pack/plugins/lens/public/id_generator/index.ts kibana-app +x-pack/plugins/lens/public/index.ts kibana-app +x-pack/plugins/lens/public/indexpattern_datasource/__mocks__/loader.ts kibana-app +x-pack/plugins/lens/public/indexpattern_datasource/__mocks__/state_helpers.ts kibana-app +x-pack/plugins/lens/public/indexpattern_datasource/change_indexpattern.tsx kibana-app +x-pack/plugins/lens/public/indexpattern_datasource/datapanel.test.tsx kibana-app +x-pack/plugins/lens/public/indexpattern_datasource/datapanel.tsx kibana-app +x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/bucket_nesting_editor.test.tsx kibana-app +x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/bucket_nesting_editor.tsx kibana-app +x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/dimension_panel.test.tsx kibana-app +x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/dimension_panel.tsx kibana-app +x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/field_select.tsx kibana-app +x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/format_selector.tsx kibana-app +x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/index.ts kibana-app +x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/popover_editor.tsx kibana-app +x-pack/plugins/lens/public/indexpattern_datasource/document_field.ts kibana-app +x-pack/plugins/lens/public/indexpattern_datasource/field_item.test.tsx kibana-app +x-pack/plugins/lens/public/indexpattern_datasource/field_item.tsx kibana-app +x-pack/plugins/lens/public/indexpattern_datasource/fields_accordion.test.tsx kibana-app +x-pack/plugins/lens/public/indexpattern_datasource/fields_accordion.tsx kibana-app +x-pack/plugins/lens/public/indexpattern_datasource/index.ts kibana-app +x-pack/plugins/lens/public/indexpattern_datasource/indexpattern.test.ts kibana-app +x-pack/plugins/lens/public/indexpattern_datasource/indexpattern.tsx kibana-app +x-pack/plugins/lens/public/indexpattern_datasource/indexpattern_suggestions.test.tsx kibana-app +x-pack/plugins/lens/public/indexpattern_datasource/indexpattern_suggestions.ts kibana-app +x-pack/plugins/lens/public/indexpattern_datasource/layerpanel.test.tsx kibana-app +x-pack/plugins/reporting/server/browsers/download/clean.ts kibana-reporting +x-pack/plugins/reporting/server/browsers/download/download.test.ts kibana-reporting +x-pack/plugins/reporting/server/browsers/download/download.ts kibana-reporting +x-pack/plugins/reporting/server/browsers/download/ensure_downloaded.ts kibana-reporting +x-pack/plugins/reporting/server/browsers/download/index.ts kibana-reporting +x-pack/plugins/reporting/server/browsers/download/util.ts kibana-reporting +x-pack/plugins/reporting/server/browsers/extract/extract.js kibana-reporting +x-pack/plugins/reporting/server/browsers/extract/extract_error.js kibana-reporting +x-pack/plugins/reporting/server/browsers/extract/index.js kibana-reporting +x-pack/plugins/reporting/server/browsers/extract/unzip.js kibana-reporting +x-pack/plugins/reporting/server/browsers/index.ts kibana-reporting +x-pack/plugins/reporting/server/browsers/install.ts kibana-reporting +x-pack/plugins/reporting/server/browsers/network_policy.test.ts kibana-reporting +x-pack/plugins/reporting/server/browsers/network_policy.ts kibana-reporting +x-pack/plugins/reporting/server/browsers/safe_child_process.ts kibana-reporting +x-pack/plugins/reporting/server/config/config.ts kibana-reporting +x-pack/plugins/reporting/server/config/create_config.test.ts kibana-reporting +x-pack/plugins/reporting/server/config/create_config.ts kibana-reporting +x-pack/plugins/reporting/server/config/default_chromium_sandbox_disabled.test.ts kibana-reporting +x-pack/plugins/lens/public/indexpattern_datasource/layerpanel.tsx kibana-app +x-pack/plugins/lens/public/indexpattern_datasource/lens_field_icon.test.tsx kibana-app +x-pack/plugins/lens/public/indexpattern_datasource/lens_field_icon.tsx kibana-app +x-pack/plugins/lens/public/indexpattern_datasource/loader.test.ts kibana-app +x-pack/plugins/lens/public/indexpattern_datasource/loader.ts kibana-app +x-pack/plugins/lens/public/indexpattern_datasource/mocks.ts kibana-app +x-pack/plugins/lens/public/indexpattern_datasource/no_fields_callout.test.tsx kibana-app +x-pack/plugins/lens/public/indexpattern_datasource/no_fields_callout.tsx kibana-app +x-pack/plugins/lens/public/indexpattern_datasource/operations/__mocks__/index.ts kibana-app +x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/cardinality.tsx kibana-app +x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/column_types.ts kibana-app +x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/count.tsx kibana-app +x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/date_histogram.test.tsx kibana-app +x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/date_histogram.tsx kibana-app +x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/index.ts kibana-app +x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/metrics.tsx kibana-app +x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/terms.test.tsx kibana-app +x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/terms.tsx kibana-app +x-pack/plugins/lens/public/indexpattern_datasource/operations/index.ts kibana-app +x-pack/plugins/lens/public/indexpattern_datasource/operations/operations.test.ts kibana-app +x-pack/plugins/lens/public/indexpattern_datasource/operations/operations.ts kibana-app +x-pack/plugins/lens/public/indexpattern_datasource/pure_helpers.test.ts kibana-app +x-pack/plugins/lens/public/indexpattern_datasource/pure_helpers.ts kibana-app +x-pack/plugins/lens/public/indexpattern_datasource/rename_columns.test.ts kibana-app +x-pack/plugins/lens/public/indexpattern_datasource/rename_columns.ts kibana-app +x-pack/plugins/lens/public/indexpattern_datasource/state_helpers.test.ts kibana-app +x-pack/plugins/lens/public/indexpattern_datasource/state_helpers.ts kibana-app +x-pack/plugins/lens/public/indexpattern_datasource/to_expression.ts kibana-app +x-pack/plugins/lens/public/indexpattern_datasource/types.ts kibana-app +x-pack/plugins/lens/public/indexpattern_datasource/utils.ts kibana-app +x-pack/plugins/lens/public/lens_ui_telemetry/factory.test.ts kibana-app diff --git a/src/dev/code_coverage/ingest_coverage/__tests__/team_assignment.test.js b/src/dev/code_coverage/ingest_coverage/__tests__/team_assignment.test.js deleted file mode 100644 index e597ffb5d2f4b..0000000000000 --- a/src/dev/code_coverage/ingest_coverage/__tests__/team_assignment.test.js +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import expect from '@kbn/expect'; -import { fetch } from '../team_assignment/get_data'; -import { noop } from '../utils'; - -describe(`Team Assignment`, () => { - const mockPath = 'src/dev/code_coverage/ingest_coverage/__tests__/mocks/team_assign_mock.json'; - describe(`fetch fn`, () => { - it(`should be a fn`, () => { - expect(typeof fetch).to.be('function'); - }); - describe(`applied to a path that exists`, () => { - it(`should return the contents of the path`, () => { - const sut = fetch(mockPath); - expect(sut.chain(JSON.parse)).to.have.property('abc'); - }); - }); - describe(`applied to an non-existing path`, () => { - it(`should return a Left with the error message within`, () => { - const expectLeft = (err) => - expect(err.message).to.contain('ENOENT: no such file or directory'); - - fetch('fake_path.json').fold(expectLeft, noop); - }); - }); - }); -}); diff --git a/src/dev/code_coverage/ingest_coverage/__tests__/transforms.test.js b/src/dev/code_coverage/ingest_coverage/__tests__/transforms.test.js index 746bccc3d718a..b6d17f83e327e 100644 --- a/src/dev/code_coverage/ingest_coverage/__tests__/transforms.test.js +++ b/src/dev/code_coverage/ingest_coverage/__tests__/transforms.test.js @@ -18,9 +18,17 @@ */ import expect from '@kbn/expect'; -import { ciRunUrl, coveredFilePath, itemizeVcs, prokPrevious } from '../transforms'; +import { + ciRunUrl, + coveredFilePath, + itemizeVcs, + prokPrevious, + teamAssignment, + last, +} from '../transforms'; +import { ToolingLog } from '@kbn/dev-utils'; -describe(`Transform fn`, () => { +describe(`Transform fns`, () => { describe(`ciRunUrl`, () => { it(`should add the url when present in the environment`, () => { process.env.CI_RUN_URL = 'blah'; @@ -83,4 +91,59 @@ describe(`Transform fn`, () => { ); }); }); + describe(`teamAssignment`, () => { + const teamAssignmentsPathMOCK = + 'src/dev/code_coverage/ingest_coverage/__tests__/mocks/team_assign_mock.txt'; + const coveredFilePath = 'x-pack/plugins/reporting/server/browsers/extract/unzip.js'; + const obj = { coveredFilePath }; + const log = new ToolingLog({ + level: 'info', + writeTo: process.stdout, + }); + + describe(`with a coveredFilePath of ${coveredFilePath}`, () => { + const expected = 'kibana-reporting'; + it(`should resolve to ${expected}`, async () => { + const actual = await teamAssignment(teamAssignmentsPathMOCK)(log)(obj); + const { team } = actual; + expect(team).to.eql(expected); + }); + }); + + describe(`with a coveredFilePath of src/plugins/charts/public/static/color_maps/color_maps.ts`, () => { + const expected = 'kibana-reporting'; + it(`should resolve to ${expected}`, async () => { + const actual = await teamAssignment(teamAssignmentsPathMOCK)(log)(obj); + const { team } = actual; + expect(team).to.eql(expected); + }); + }); + + describe(`last fn`, () => { + describe(`applied to n results`, () => { + it(`should pick the last one`, () => { + const nteams = `src/plugins/charts/public/static/color_maps/color_maps.ts kibana-app +src/plugins/charts/public/static/color_maps/color_maps.ts kibana-app-arch`; + + const actual = last(nteams); + + expect(actual).to.be( + 'src/plugins/charts/public/static/color_maps/color_maps.ts kibana-app-arch' + ); + }); + }); + describe(`applied to 1 result`, () => { + it(`should pick that 1 result`, () => { + const nteams = + 'src/plugins/charts/public/static/color_maps/color_maps.ts kibana-app-arch'; + + const actual = last(nteams); + + expect(actual).to.be( + 'src/plugins/charts/public/static/color_maps/color_maps.ts kibana-app-arch' + ); + }); + }); + }); + }); }); diff --git a/src/dev/code_coverage/ingest_coverage/constants.js b/src/dev/code_coverage/ingest_coverage/constants.js index f2f467e461ae5..8f850ac2f1f12 100644 --- a/src/dev/code_coverage/ingest_coverage/constants.js +++ b/src/dev/code_coverage/ingest_coverage/constants.js @@ -27,8 +27,6 @@ export const RESEARCH_COVERAGE_INDEX = export const RESEARCH_TOTALS_INDEX = process.env.RESEARCH_TOTALS_INDEX || `qa_research_total_code_coverage`; -export const TEAM_ASSIGNMENT_PIPELINE_NAME = process.env.PIPELINE_NAME || 'team_assignment'; - export const CODE_COVERAGE_CI_JOB_NAME = 'elastic+kibana+code-coverage'; export const RESEARCH_CI_JOB_NAME = 'elastic+kibana+qa-research'; export const CI_JOB_NAME = process.env.COVERAGE_JOB_NAME || RESEARCH_CI_JOB_NAME; diff --git a/src/dev/code_coverage/ingest_coverage/either.js b/src/dev/code_coverage/ingest_coverage/either.js index eeb48893f18d8..326f238074e30 100644 --- a/src/dev/code_coverage/ingest_coverage/either.js +++ b/src/dev/code_coverage/ingest_coverage/either.js @@ -20,11 +20,15 @@ /* eslint new-cap: 0 */ /* eslint no-unused-vars: 0 */ +import { always } from './utils'; + export const Right = (x) => ({ chain: (f) => f(x), map: (f) => Right(f(x)), fold: (leftFn, rightFn) => rightFn(x), inspect: () => `Right(${x})`, + isLeft: always(false), + isRight: always(true), }); Right.of = function of(x) { @@ -40,6 +44,8 @@ export const Left = (x) => ({ map: (f) => Left(x), fold: (leftFn, rightFn) => leftFn(x), inspect: () => `Left(${x})`, + isLeft: always(true), + isRight: always(false), }); Left.of = function of(x) { diff --git a/src/dev/code_coverage/ingest_coverage/index.js b/src/dev/code_coverage/ingest_coverage/index.js index 4047ee78ee6ec..f29739c4cf29c 100644 --- a/src/dev/code_coverage/ingest_coverage/index.js +++ b/src/dev/code_coverage/ingest_coverage/index.js @@ -20,13 +20,16 @@ import { resolve } from 'path'; import { prok } from './process'; import { run, createFlagError } from '@kbn/dev-utils'; +import { pathExists } from './team_assignment/enumeration_helpers'; +import { id, reThrow } from './utils'; const ROOT = resolve(__dirname, '../../../..'); const flags = { - string: ['path', 'verbose', 'vcsInfoPath'], + string: ['path', 'verbose', 'vcsInfoPath', 'teamAssignmentsPath'], help: ` --path Required, path to the file to extract coverage data --vcsInfoPath Required, path to the git info file (branch, sha, author, & commit msg) +--teamAssignmentsPath Required, path to the team assignments data file `, }; @@ -36,12 +39,18 @@ export function runCoverageIngestionCli() { if (flags.path === '') throw createFlagError('please provide a single --path flag'); if (flags.vcsInfoPath === '') throw createFlagError('please provide a single --vcsInfoPath flag'); + if (flags.teamAssignmentsPath === '') + throw createFlagError('please provide a single --teamAssignments flag'); if (flags.verbose) log.verbose(`Verbose logging enabled`); const resolveRoot = resolve.bind(null, ROOT); const jsonSummaryPath = resolveRoot(flags.path); const vcsInfoFilePath = resolveRoot(flags.vcsInfoPath); - prok({ jsonSummaryPath, vcsInfoFilePath }, log); + const { teamAssignmentsPath } = flags; + + pathExists(teamAssignmentsPath).fold(reThrow, id); + + prok({ jsonSummaryPath, vcsInfoFilePath, teamAssignmentsPath }, log); }, { description: ` diff --git a/src/dev/code_coverage/ingest_coverage/ingest.js b/src/dev/code_coverage/ingest_coverage/ingest.js index 31a94d161a3cc..24da7a9338a46 100644 --- a/src/dev/code_coverage/ingest_coverage/ingest.js +++ b/src/dev/code_coverage/ingest_coverage/ingest.js @@ -19,7 +19,7 @@ const { Client } = require('@elastic/elasticsearch'); import { createFailError } from '@kbn/dev-utils'; -import { RESEARCH_CI_JOB_NAME, TEAM_ASSIGNMENT_PIPELINE_NAME } from './constants'; +import { RESEARCH_CI_JOB_NAME } from './constants'; import { errMsg, redact, whichIndex } from './ingest_helpers'; import { pretty, green } from './utils'; import { right, left } from './either'; @@ -34,14 +34,10 @@ const isResearchJob = process.env.COVERAGE_JOB_NAME === RESEARCH_CI_JOB_NAME ? t export const ingest = (log) => async (body) => { const isTotal = !!body.isTotal; const index = whichIndex(isResearchJob)(isTotal); - const isACoverageIndex = isTotal ? false : true; const stringified = pretty(body); - const pipeline = TEAM_ASSIGNMENT_PIPELINE_NAME; - const finalPayload = isACoverageIndex - ? { index, body: stringified, pipeline } - : { index, body: stringified }; + const finalPayload = { index, body: stringified }; const justLog = dontSendButLog(log); const doSendToIndex = doSend(index); @@ -77,11 +73,11 @@ async function send(logF, idx, redactedEsHostUrl, client, requestBody) { const sendMsg = (actuallySent, redactedEsHostUrl, payload) => { const { index, body } = payload; return `### ${actuallySent ? 'Sent' : 'Fake Sent'}: -${payload.pipeline ? `\t### Team Assignment Pipeline: ${green(payload.pipeline)}` : ''} ${redactedEsHostUrl ? `\t### ES Host: ${redactedEsHostUrl}` : ''} + \t### Index: ${green(index)} + \t### payload.body: ${body} -${process.env.NODE_ENV === 'integration_test' ? `ingest-pipe=>${payload.pipeline}` : ''} `; }; diff --git a/src/dev/code_coverage/ingest_coverage/ingest_helpers.js b/src/dev/code_coverage/ingest_coverage/ingest_helpers.js index 86bcf03977082..a7822a671887b 100644 --- a/src/dev/code_coverage/ingest_coverage/ingest_helpers.js +++ b/src/dev/code_coverage/ingest_coverage/ingest_helpers.js @@ -24,7 +24,6 @@ import { COVERAGE_INDEX, RESEARCH_COVERAGE_INDEX, RESEARCH_TOTALS_INDEX, - TEAM_ASSIGNMENT_PIPELINE_NAME, TOTALS_INDEX, } from './constants'; @@ -70,12 +69,6 @@ function color(whichColor) { }; } -export function maybeTeamAssign(isACoverageIndex, body) { - const doAddTeam = isACoverageIndex ? true : false; - const payload = doAddTeam ? { ...body, pipeline: TEAM_ASSIGNMENT_PIPELINE_NAME } : body; - return payload; -} - export function whichIndex(isResearchJob) { return (isTotal) => isTotal ? whichTotalsIndex(isResearchJob) : whichCoverageIndex(isResearchJob); diff --git a/src/dev/code_coverage/ingest_coverage/integration_tests/ingest_coverage.test.js b/src/dev/code_coverage/ingest_coverage/integration_tests/ingest_coverage.test.js index ba73922ec508a..a4d07215efec1 100644 --- a/src/dev/code_coverage/ingest_coverage/integration_tests/ingest_coverage.test.js +++ b/src/dev/code_coverage/ingest_coverage/integration_tests/ingest_coverage.test.js @@ -20,6 +20,7 @@ import { resolve } from 'path'; import execa from 'execa'; import expect from '@kbn/expect'; +import shell from 'shelljs'; const ROOT_DIR = resolve(__dirname, '../../../../..'); const MOCKS_DIR = resolve(__dirname, './mocks'); @@ -35,9 +36,14 @@ const env = { }; describe('Ingesting coverage', () => { + const teamAssignmentsPath = + 'src/dev/code_coverage/ingest_coverage/team_assignment/team_assignments.txt'; + const verboseArgs = [ 'scripts/ingest_coverage.js', '--verbose', + '--teamAssignmentsPath', + teamAssignmentsPath, '--vcsInfoPath', 'src/dev/code_coverage/ingest_coverage/integration_tests/mocks/VCS_INFO.txt', '--path', @@ -46,6 +52,21 @@ describe('Ingesting coverage', () => { const summaryPath = 'jest-combined/coverage-summary-manual-mix.json'; const resolved = resolve(MOCKS_DIR, summaryPath); + beforeAll(async () => { + const params = [ + 'scripts/generate_team_assignments.js', + '--src', + '.github/CODEOWNERS', + '--dest', + teamAssignmentsPath, + ]; + await execa(process.execPath, params, { cwd: ROOT_DIR, env }); + }); + + afterAll(() => { + shell.rm(teamAssignmentsPath); + }); + describe(`staticSiteUrl`, () => { let actualUrl = ''; const siteUrlRegex = /"staticSiteUrl":\s*(.+,)/; diff --git a/src/dev/code_coverage/ingest_coverage/integration_tests/mocks/CODEOWNERS b/src/dev/code_coverage/ingest_coverage/integration_tests/mocks/CODEOWNERS new file mode 100644 index 0000000000000..1822c3fd95e34 --- /dev/null +++ b/src/dev/code_coverage/ingest_coverage/integration_tests/mocks/CODEOWNERS @@ -0,0 +1,6 @@ +# GitHub CODEOWNERS definition +# Identify which groups will be pinged by changes to different parts of the codebase. +# For more info, see https://help.github.com/articles/about-codeowners/ + +# App +/x-pack/plugins/code/ @elastic/kibana-tre diff --git a/src/dev/code_coverage/ingest_coverage/integration_tests/mocks/jest-combined/coverage-summary-possibly-n-teams.json b/src/dev/code_coverage/ingest_coverage/integration_tests/mocks/jest-combined/coverage-summary-possibly-n-teams.json new file mode 100644 index 0000000000000..9e66d8f5cb101 --- /dev/null +++ b/src/dev/code_coverage/ingest_coverage/integration_tests/mocks/jest-combined/coverage-summary-possibly-n-teams.json @@ -0,0 +1,28 @@ +{ + "/var/lib/jenkins/workspace/elastic+kibana+code-coverage/kibana/src/plugins/charts/public/static/color_maps/color_maps.ts": { + "lines": { + "total": 4, + "covered": 4, + "skipped": 0, + "pct": 100 + }, + "functions": { + "total": 1, + "covered": 1, + "skipped": 0, + "pct": 100 + }, + "statements": { + "total": 4, + "covered": 4, + "skipped": 0, + "pct": 100 + }, + "branches": { + "total": 0, + "covered": 0, + "skipped": 0, + "pct": 100 + } + } +} diff --git a/src/dev/code_coverage/ingest_coverage/integration_tests/mocks/jest-combined/coverage-summary-qa-research-job.json b/src/dev/code_coverage/ingest_coverage/integration_tests/mocks/jest-combined/coverage-summary-qa-research-job.json new file mode 100644 index 0000000000000..6e4d8ea954c2c --- /dev/null +++ b/src/dev/code_coverage/ingest_coverage/integration_tests/mocks/jest-combined/coverage-summary-qa-research-job.json @@ -0,0 +1,28 @@ +{ + "/var/lib/jenkins/workspace/elastic+kibana+qa-research/kibana/x-pack/plugins/reporting/server/browsers/extract/unzip.js": { + "lines": { + "total": 4, + "covered": 4, + "skipped": 0, + "pct": 100 + }, + "functions": { + "total": 1, + "covered": 1, + "skipped": 0, + "pct": 100 + }, + "statements": { + "total": 4, + "covered": 4, + "skipped": 0, + "pct": 100 + }, + "branches": { + "total": 0, + "covered": 0, + "skipped": 0, + "pct": 100 + } + } +} diff --git a/src/dev/code_coverage/ingest_coverage/integration_tests/team_assignment.test.js b/src/dev/code_coverage/ingest_coverage/integration_tests/team_assignment.test.js new file mode 100644 index 0000000000000..c666581ddb08c --- /dev/null +++ b/src/dev/code_coverage/ingest_coverage/integration_tests/team_assignment.test.js @@ -0,0 +1,58 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { resolve } from 'path'; +import execa from 'execa'; +import expect from '@kbn/expect'; +import shell from 'shelljs'; + +const ROOT_DIR = resolve(__dirname, '../../../../..'); +const MOCKS_DIR = resolve(__dirname, './mocks'); + +describe('Team Assignment', () => { + const teamAssignmentsPath = + 'src/dev/code_coverage/ingest_coverage/team_assignment/team_assignments.txt'; + const mockCodeOwners = 'CODEOWNERS'; + const resolved = resolve(MOCKS_DIR, mockCodeOwners); + + beforeAll(async () => { + const params = [ + 'scripts/generate_team_assignments.js', + '--src', + resolved, + '--dest', + teamAssignmentsPath, + ]; + await execa(process.execPath, params, { cwd: ROOT_DIR }); + }); + + afterAll(() => { + shell.rm(teamAssignmentsPath); + }); + + describe(`when the codeowners file contains #CC#`, () => { + it(`should strip the prefix and still drill down through the fs`, async () => { + const { stdout } = await execa('grep', ['tre', teamAssignmentsPath], { cwd: ROOT_DIR }); + expect(stdout).to.be(`x-pack/plugins/code/server/config.ts kibana-tre +x-pack/plugins/code/server/index.ts kibana-tre +x-pack/plugins/code/server/plugin.test.ts kibana-tre +x-pack/plugins/code/server/plugin.ts kibana-tre`); + }); + }); +}); diff --git a/src/dev/code_coverage/ingest_coverage/process.js b/src/dev/code_coverage/ingest_coverage/process.js index 85a42cfffa6e2..28a7c9ccd41b0 100644 --- a/src/dev/code_coverage/ingest_coverage/process.js +++ b/src/dev/code_coverage/ingest_coverage/process.js @@ -18,7 +18,7 @@ */ import { fromEventPattern, of, fromEvent } from 'rxjs'; -import { concatMap, delay, map, takeUntil } from 'rxjs/operators'; +import { concatMap, delay, map, mergeMap, takeUntil } from 'rxjs/operators'; import jsonStream from './json_stream'; import { pipe, noop, green, always } from './utils'; import { ingest } from './ingest'; @@ -32,6 +32,7 @@ import { coveredFilePath, ciRunUrl, itemizeVcs, + teamAssignment, } from './transforms'; import { resolve } from 'path'; import { createReadStream } from 'fs'; @@ -50,9 +51,10 @@ const addPrePopulatedTimeStamp = addTimeStamp(process.env.TIME_STAMP || formatte const preamble = pipe(statsAndstaticSiteUrl, rootDirAndOrigPath, buildId, addPrePopulatedTimeStamp); const addTestRunnerAndStaticSiteUrl = pipe(testRunner, staticSite(staticSiteUrlBase)); -const transform = (jsonSummaryPath) => (log) => (vcsInfo) => { +const transform = (jsonSummaryPath) => (log) => (vcsInfo) => (teamAssignmentsPath) => { const objStream = jsonStream(jsonSummaryPath).on('done', noop); const itemizeVcsInfo = itemizeVcs(vcsInfo); + const assignTeams = teamAssignment(teamAssignmentsPath)(log); const jsonSummary$ = (_) => objStream.on('node', '!.*', _); @@ -64,6 +66,7 @@ const transform = (jsonSummaryPath) => (log) => (vcsInfo) => { map(ciRunUrl), map(addJsonSummaryPath(jsonSummaryPath)), map(addTestRunnerAndStaticSiteUrl), + mergeMap(assignTeams), concatMap((x) => of(x).pipe(delay(ms))) ) .subscribe(ingest(log)); @@ -83,7 +86,7 @@ const vcsInfoLines$ = (vcsInfoFilePath) => { return fromEvent(rl, 'line').pipe(takeUntil(fromEvent(rl, 'close'))); }; -export const prok = ({ jsonSummaryPath, vcsInfoFilePath }, log) => { +export const prok = ({ jsonSummaryPath, vcsInfoFilePath, teamAssignmentsPath }, log) => { validateRoot(COVERAGE_INGESTION_KIBANA_ROOT, log); logAll(jsonSummaryPath, log); @@ -93,7 +96,7 @@ export const prok = ({ jsonSummaryPath, vcsInfoFilePath }, log) => { vcsInfoLines$(vcsInfoFilePath).subscribe( mutateVcsInfo(vcsInfo), (err) => log.error(err), - always(xformWithPath(vcsInfo)) + always(xformWithPath(vcsInfo)(teamAssignmentsPath)) ); }; diff --git a/src/dev/code_coverage/ingest_coverage/team_assignment/enumerate_patterns.js b/src/dev/code_coverage/ingest_coverage/team_assignment/enumerate_patterns.js new file mode 100644 index 0000000000000..dcdb32c91b8f8 --- /dev/null +++ b/src/dev/code_coverage/ingest_coverage/team_assignment/enumerate_patterns.js @@ -0,0 +1,78 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { readdirSync, statSync } from 'fs'; +import { join } from 'path'; +import { + push, + prokGlob, + trim, + isRejectedDir, + isFileAllowed, + isDir, + tryPath, + dropEmpty, + notFound, +} from './enumeration_helpers'; +import { stripLeading } from '../transforms'; + +export const enumeratePatterns = (rootPath) => (log) => (patterns) => { + const res = []; + const resPush = push(res); + const logNotFound = notFound(log); + + for (const entry of patterns) { + const [pathPattern, team] = entry; + const cleaned = stripLeading(pathPattern); + const existsWithOwner = pathExists(team); + + const collect = (x) => existsWithOwner(x).forEach(resPush); + tryPath(cleaned).fold(logNotFound, collect); + } + + return res; + + function pathExists(owner) { + const creeper = (x) => creepFsSync(x, [], rootPath, owner); + return function creepAllAsGlobs(pathPattern) { + return prokGlob(pathPattern).map(creeper).filter(dropEmpty); + }; + } +}; + +function creepFsSync(aPath, xs, rootPath, owner) { + xs = xs || []; + + const joinRoot = join.bind(null, rootPath); + const trimRoot = trim(rootPath); + const joined = joinRoot(aPath); + const isADir = isDir(joined); + + (isADir ? readdirSync(joined) : [aPath]).forEach(maybeRecurse); + + return xs; + + function maybeRecurse(entry) { + const full = isADir ? join(aPath, entry) : entry; + const fullIsDir = statSync(full).isDirectory(); + + if (fullIsDir && !isRejectedDir(full)) xs = creepFsSync(full, xs, rootPath, owner); + else if (isFileAllowed(full)) xs.push(`${trimRoot(full)} ${owner}`); + } +} diff --git a/src/dev/code_coverage/ingest_coverage/team_assignment/enumeration_helpers.js b/src/dev/code_coverage/ingest_coverage/team_assignment/enumeration_helpers.js new file mode 100644 index 0000000000000..b06141965d2b6 --- /dev/null +++ b/src/dev/code_coverage/ingest_coverage/team_assignment/enumeration_helpers.js @@ -0,0 +1,46 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { statSync } from 'fs'; +import isGlob from 'is-glob'; +import glob from 'glob'; +import { left, right, tryCatch } from '../either'; + +export const push = (xs) => (x) => xs.push(x); +export const pathExists = (x) => tryCatch(() => statSync(x)).fold(left, right); +export const isDir = (x) => statSync(x).isDirectory(); +export const prokGlob = (x) => glob.sync(x, { nonull: true }); +export const trim = (ROOT) => (x) => x.replace(`${ROOT}/`, ''); +export const isFileAllowed = (x) => { + const isJsOrTsOrTsxOrJsx = /.(j|t)(s|sx)$/gm; + return isJsOrTsOrTsxOrJsx.test(x); +}; +export const isRejectedDir = (x) => + /node_modules|__tests__|__fixture__|__fixtures__|build\//gm.test(x); +const isGlobFound = (x) => (xs) => (x === xs[0] ? false : true); +export const globExpands = (x) => isGlobFound(x)(prokGlob(x)); +export const tryPath = (x) => { + const isAGlob = isGlob(x); + + if (isAGlob) return globExpands(x) ? right(x) : left(x); + + if (!isAGlob) return pathExists(x).isRight() ? right(x) : left(x); +}; +export const dropEmpty = (x) => x.length > 0; +export const notFound = (log) => (err) => log.error(`\n!!! Not Found: \n${err}`); diff --git a/src/dev/code_coverage/ingest_coverage/team_assignment/flush.js b/src/dev/code_coverage/ingest_coverage/team_assignment/flush.js new file mode 100644 index 0000000000000..5150ac2e655f2 --- /dev/null +++ b/src/dev/code_coverage/ingest_coverage/team_assignment/flush.js @@ -0,0 +1,44 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { writeFileSync } from 'fs'; +import shell from 'shelljs'; +import { tryCatch } from '../either'; +import { id } from '../utils'; + +const encoding = 'utf8'; +const appendUtf8 = { flag: 'a', encoding }; + +export const flush = (dest) => (log) => (assignments) => { + log.verbose(`\n### Flushing assignments to: \n\t${dest}`); + + const writeToFile = writeFileSync.bind(null, dest); + + writeToFile('', { encoding }); + + for (const xs of assignments) xs.forEach((x) => writeToFile(`${x}\n`, appendUtf8)); + + tryCatch(() => maybeShowSize(dest)).fold(id, (x) => { + log.verbose(`\n### Flushed [${x}] lines`); + }); +}; +function maybeShowSize(x) { + const { output } = shell.exec(`wc -l ${x}`, { silent: true }); + return output.match(/\s*\d*\s*/)[0].trim(); +} diff --git a/src/dev/code_coverage/ingest_coverage/team_assignment/get_data.js b/src/dev/code_coverage/ingest_coverage/team_assignment/get_data.js deleted file mode 100644 index 34526a2f79302..0000000000000 --- a/src/dev/code_coverage/ingest_coverage/team_assignment/get_data.js +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { readFileSync } from 'fs'; -import { resolve } from 'path'; -import { tryCatch as tc } from '../either'; - -const ROOT = resolve(__dirname, '../../../../..'); - -const resolveFromRoot = resolve.bind(null, ROOT); - -const resolved = (path) => () => resolveFromRoot(path); - -const getContents = (path) => tc(() => readFileSync(path, 'utf8')); - -// fetch :: String -> Left | Right -export const fetch = (path) => tc(resolved(path)).chain(getContents); diff --git a/src/dev/code_coverage/ingest_coverage/team_assignment/index.js b/src/dev/code_coverage/ingest_coverage/team_assignment/index.js index 11f9748708283..30112df3b6ba4 100644 --- a/src/dev/code_coverage/ingest_coverage/team_assignment/index.js +++ b/src/dev/code_coverage/ingest_coverage/team_assignment/index.js @@ -17,42 +17,55 @@ * under the License. */ -import { run } from '@kbn/dev-utils'; -import { TEAM_ASSIGNMENT_PIPELINE_NAME } from '../constants'; -import { fetch } from './get_data'; -import { update } from './update_ingest_pipeline'; +import { run, createFlagError, REPO_ROOT } from '@kbn/dev-utils'; +import { parse } from './parse_owners'; +import { flush } from './flush'; +import { enumeratePatterns } from './enumerate_patterns'; +import { pipe } from '../utils'; +import { reduce } from 'rxjs/operators'; -const updatePipeline = update(TEAM_ASSIGNMENT_PIPELINE_NAME); - -const execute = ({ flags, log }) => { - if (flags.verbose) log.verbose(`### Verbose logging enabled`); - - const logLeft = handleErr(log); - const updateAndLog = updatePipeline(log); - - const { path } = flags; - - fetch(path).fold(logLeft, updateAndLog); +const flags = { + string: ['src', 'dest'], + help: ` +--src Required, path to CODEOWNERS file. +--dest Required, destination path of the assignments. + `, }; -function handleErr(log) { - return (msg) => log.error(msg); -} +export const generateTeamAssignments = () => { + run( + ({ flags, log }) => { + if (flags.src === '') throw createFlagError('please provide a single --src flag'); + if (flags.dest === '') throw createFlagError('please provide a single --dest flag'); -const description = ` + const logCreepAndFlush = pipe( + logSuccess(flags.src, log), + enumeratePatterns(REPO_ROOT)(log), + flush(flags.dest)(log) + ); -Upload the latest team assignment pipeline def from src, -to the cluster. + parse(flags.src).pipe(reduce(toMap, new Map())).subscribe(logCreepAndFlush); + }, + { + description: ` - `; +Create a file defining the team assignments, + parsed from .github/CODEOWNERS -const flags = { - string: ['path', 'verbose'], - help: ` ---path Required, path to painless definition for team assignment. - `, + `, + flags, + } + ); }; -const usage = 'node scripts/load_team_assignment.js --verbose --path PATH_TO_PAINLESS_SCRIPT.json'; +function toMap(acc, x) { + acc.set(x[0], x[1][0]); + return acc; +} -export const uploadTeamAssignmentJson = () => run(execute, { description, flags, usage }); +function logSuccess(src, log) { + return (dataObj) => { + log.verbose(`\n### Parsing [${src}] Complete`); + return dataObj; + }; +} diff --git a/src/dev/code_coverage/ingest_coverage/team_assignment/ingestion_pipeline_painless.json b/src/dev/code_coverage/ingest_coverage/team_assignment/ingestion_pipeline_painless.json deleted file mode 100644 index 017d208133cdc..0000000000000 --- a/src/dev/code_coverage/ingest_coverage/team_assignment/ingestion_pipeline_painless.json +++ /dev/null @@ -1 +0,0 @@ -{"description":"Kibana code coverage team assignments","processors":[{"script":{"lang":"painless","source":"\n String path = ctx.coveredFilePath; \n if (path.indexOf('src/legacy/core_plugins/kibana/') == 0) {\n\n if (path.indexOf('src/legacy/core_plugins/kibana/common/utils') == 0) ctx.team = 'kibana-app';\n else if (path.indexOf('src/legacy/core_plugins/kibana/migrations') == 0) ctx.team = 'kibana-app';\n else if (path.indexOf('src/legacy/core_plugins/kibana/public') == 0) ctx.team = 'kibana-app';\n else if (path.indexOf('src/legacy/core_plugins/kibana/public/dashboard/') == 0) ctx.team = 'kibana-app';\n else if (path.indexOf('src/legacy/core_plugins/kibana/public/dev_tools/') == 0) ctx.team = 'kibana-app';\n else if (path.indexOf('src/legacy/core_plugins/kibana/public/discover/') == 0) ctx.team = 'kibana-app';\n else if (path.indexOf('src/legacy/core_plugins/kibana/public/home') == 0) ctx.team = 'kibana-core-ui';\n else if (path.indexOf('src/legacy/core_plugins/kibana/public/home/np_ready/') == 0) ctx.team = 'kibana-core-ui';\n else if (path.indexOf('src/legacy/core_plugins/kibana/public/local_application_service/') == 0) ctx.team = 'kibana-app';\n else if (path.indexOf('src/legacy/core_plugins/kibana/public/management/') == 0) ctx.team = 'kibana-app-arch';\n else if (path.indexOf('src/legacy/core_plugins/kibana/server/lib') == 0) ctx.team = 'kibana-platform';\n else if (path.indexOf('src/legacy/core_plugins/kibana/server/lib/management/saved_objects') == 0) ctx.team = 'kibana-platform';\n else if (path.indexOf('src/legacy/core_plugins/kibana/server/routes/api/management/') == 0) ctx.team = 'kibana-app-arch';\n else if (path.indexOf('src/legacy/core_plugins/kibana/server/routes/api/import/') == 0) ctx.team = 'kibana-platform';\n else if (path.indexOf('src/legacy/core_plugins/kibana/server/routes/api/export/') == 0) ctx.team = 'kibana-platform';\n else ctx.team = 'unknown';\n\n } else if (path.indexOf('src/legacy/core_plugins/') == 0) {\n\n if (path.indexOf('src/legacy/core_plugins/apm_oss/') == 0) ctx.team = 'apm-ui';\n else if (path.indexOf('src/legacy/core_plugins/console_legacy') == 0) ctx.team = 'kibana-app';\n else if (path.indexOf('src/legacy/core_plugins/elasticsearch') == 0) ctx.team = 'kibana-platform';\n else if (path.indexOf('src/legacy/core_plugins/embeddable_api/') == 0) ctx.team = 'kibana-app-arch';\n else if (path.indexOf('src/legacy/core_plugins/input_control_vis') == 0) ctx.team = 'kibana-app';\n else if (path.indexOf('src/legacy/core_plugins/interpreter/') == 0) ctx.team = 'kibana-app-arch';\n else if (path.indexOf('src/legacy/core_plugins/kibana_react/') == 0) ctx.team = 'kibana-app-arch';\n else if (path.indexOf('src/legacy/core_plugins/newsfeed') == 0) ctx.team = 'kibana-core-ui';\n else if (path.indexOf('src/legacy/core_plugins/region_map') == 0) ctx.team = 'maps';\n else if (path.indexOf('src/legacy/core_plugins/status_page/public') == 0) ctx.team = 'kibana-app-arch';\n else if (path.indexOf('src/legacy/core_plugins/testbed') == 0) ctx.team = 'kibana-platform';\n // else if (path.indexOf('src/legacy/core_plugins/tests_bundle/') == 0) ctx.team = 'kibana-platform';\n \n else if (path.indexOf('src/legacy/core_plugins/tile_map') == 0) ctx.team = 'maps';\n else if (path.indexOf('src/legacy/core_plugins/timelion') == 0) ctx.team = 'kibana-app';\n else if (path.indexOf('src/legacy/core_plugins/ui_metric/') == 0) ctx.team = 'pulse';\n else if (path.indexOf('src/legacy/core_plugins/vis_type_tagcloud') == 0) ctx.team = 'kibana-app';\n else if (path.indexOf('src/legacy/core_plugins/vis_type_vega') == 0) ctx.team = 'kibana-app';\n else if (path.indexOf('src/legacy/core_plugins/vis_type_vislib/') == 0) ctx.team = 'kibana-app';\n else if (path.indexOf('src/legacy/core_plugins/visualizations/') == 0) ctx.team = 'kibana-app-arch';\n else ctx.team = 'unknown';\n\n } else if (path.indexOf('src/legacy/server/') == 0) {\n\n if (path.indexOf('src/legacy/server/config/') == 0) ctx.team = 'kibana-platform';\n else if (path.indexOf('src/legacy/server/http/') == 0) ctx.team = 'kibana-platform';\n else if (path.indexOf('src/legacy/server/i18n/') == 0) ctx.team = 'kibana-localization';\n else if (path.indexOf('src/legacy/server/index_patterns/') == 0) ctx.team = 'kibana-app-arch';\n else if (path.indexOf('src/legacy/server/keystore/') == 0) ctx.team = 'kibana-operations';\n else if (path.indexOf('src/legacy/server/logging/') == 0) ctx.team = 'kibana-platform';\n else if (path.indexOf('src/legacy/server/pid/') == 0) ctx.team = 'kibana-operations';\n else if (path.indexOf('src/legacy/server/sample_data/') == 0) ctx.team = 'kibana-app';\n else if (path.indexOf('src/legacy/server/sass/') == 0) ctx.team = 'kibana-operations';\n else if (path.indexOf('src/legacy/server/saved_objects/') == 0) ctx.team = 'kibana-platform';\n else if (path.indexOf('src/legacy/server/status/') == 0) ctx.team = 'kibana-platform';\n else if (path.indexOf('src/legacy/server/url_shortening/') == 0) ctx.team = 'kibana-app';\n else if (path.indexOf('src/legacy/server/utils/') == 0) ctx.team = 'kibana-operations';\n else if (path.indexOf('src/legacy/server/warnings/') == 0) ctx.team = 'kibana-operations';\n else ctx.team = 'unknown';\n\n } else if (path.indexOf('src/legacy/ui') == 0) {\n\n if (path.indexOf('src/legacy/ui/public/field_editor') == 0) ctx.team = 'kibana-app-arch';\n else if (path.indexOf('src/legacy/ui/public/timefilter') == 0) ctx.team = 'kibana-app-arch';\n else if (path.indexOf('src/legacy/ui/public/management') == 0) ctx.team = 'kibana-app-arch';\n else if (path.indexOf('src/legacy/ui/public/state_management') == 0) ctx.team = 'kibana-app';\n else if (path.indexOf('src/legacy/ui/public/new_platform') == 0) ctx.team = 'kibana-platform';\n else if (path.indexOf('src/legacy/ui/public/plugin_discovery') == 0) ctx.team = 'kibana-platform';\n else if (path.indexOf('src/legacy/ui/public/chrome') == 0) ctx.team = 'kibana-platform';\n else if (path.indexOf('src/legacy/ui/public/notify') == 0) ctx.team = 'kibana-platform';\n else if (path.indexOf('src/legacy/ui/public/documentation_links') == 0) ctx.team = 'kibana-platform';\n else if (path.indexOf('src/legacy/ui/public/autoload') == 0) ctx.team = 'kibana-platform';\n else if (path.indexOf('src/legacy/ui/public/capabilities') == 0) ctx.team = 'kibana-security';\n else if (path.indexOf('src/legacy/ui/public/apm') == 0) ctx.team = 'apm-ui';\n\n } else if (path.indexOf('src/plugins/') == 0) {\n\n if (path.indexOf('src/plugins/advanced_settings/') == 0) ctx.team = 'kibana-app-arch';\n else if (path.indexOf('src/plugins/apm_oss/') == 0) ctx.team = 'apm-ui';\n else if (path.indexOf('src/plugins/bfetch/') == 0) ctx.team = 'kibana-app-arch';\n else if (path.indexOf('src/plugins/charts/') == 0) ctx.team = 'kibana-app-arch';\n else if (path.indexOf('src/plugins/charts/public/static/color_maps') == 0) ctx.team = 'kibana-app';\n else if (path.indexOf('src/plugins/console/') == 0) ctx.team = 'es-ui';\n else if (path.indexOf('src/plugins/dashboard/') == 0) ctx.team = 'kibana-app';\n else if (path.indexOf('src/plugins/data/') == 0) ctx.team = 'kibana-app-arch';\n else if (path.indexOf('src/plugins/dev_tools/') == 0) ctx.team = 'es-ui';\n else if (path.indexOf('src/plugins/discover/') == 0) ctx.team = 'kibana-app';\n else if (path.indexOf('src/plugins/embeddable/') == 0) ctx.team = 'kibana-app-arch';\n else if (path.indexOf('src/plugins/es_ui_shared/') == 0) ctx.team = 'es-ui';\n else if (path.indexOf('src/plugins/expressions/') == 0) ctx.team = 'kibana-app-arch';\n else if (path.indexOf('src/plugins/home/public') == 0) ctx.team = 'kibana-core-ui';\n else if (path.indexOf('src/plugins/home/server/tutorials') == 0) ctx.team = 'observability';\n else if (path.indexOf('src/plugins/home/server/services/') == 0) ctx.team = 'kibana-core-ui';\n else if (path.indexOf('src/plugins/home/') == 0) ctx.team = 'kibana-core-ui';\n else if (path.indexOf('src/plugins/index_pattern_management/public/service') == 0) ctx.team = 'kibana-app-arch';\n else if (path.indexOf('src/plugins/index_pattern_management/public') == 0) ctx.team = 'kibana-app';\n else if (path.indexOf('src/plugins/input_control_vis/') == 0) ctx.team = 'kibana-app';\n else if (path.indexOf('src/plugins/inspector/') == 0) ctx.team = 'kibana-app-arch';\n else if (path.indexOf('src/plugins/kibana_legacy/') == 0) ctx.team = 'kibana-app';\n else if (path.indexOf('src/plugins/kibana_react/public/code_editor') == 0) ctx.team = 'kibana-canvas';\n else if (path.indexOf('src/plugins/kibana_react/') == 0) ctx.team = 'kibana-app-arch';\n else if (path.indexOf('src/plugins/kibana_utils/') == 0) ctx.team = 'kibana-app-arch';\n else if (path.indexOf('src/plugins/management/') == 0) ctx.team = 'kibana-app-arch';\n else if (path.indexOf('src/plugins/kibana_usage_collection/') == 0) ctx.team = 'pulse';\n else if (path.indexOf('src/plugins/legacy_export/') == 0) ctx.team = 'kibana-platform';\n else if (path.indexOf('src/plugins/maps_legacy/') == 0) ctx.team = 'maps';\n else if (path.indexOf('src/plugins/region_map/') == 0) ctx.team = 'maps';\n else if (path.indexOf('src/plugins/tile_map/') == 0) ctx.team = 'maps';\n else if (path.indexOf('src/plugins/timelion') == 0) ctx.team = 'kibana-app';\n else if (path.indexOf('src/plugins/navigation/') == 0) ctx.team = 'kibana-app-arch';\n else if (path.indexOf('src/plugins/newsfeed') == 0) ctx.team = 'kibana-core-ui';\n else if (path.indexOf('src/plugins/saved_objects_management/') == 0) ctx.team = 'kibana-platform';\n else if (path.indexOf('src/plugins/saved_objects/') == 0) ctx.team = 'kibana-app-arch';\n else if (path.indexOf('src/plugins/share/') == 0) ctx.team = 'kibana-app-arch';\n else if (path.indexOf('src/plugins/status_page/') == 0) ctx.team = 'kibana-platform';\n else if (path.indexOf('src/plugins/telemetry') == 0) ctx.team = 'pulse';\n else if (path.indexOf('src/plugins/testbed/server/') == 0) ctx.team = 'kibana-platform';\n else if (path.indexOf('src/plugins/ui_actions/') == 0) ctx.team = 'kibana-app-arch';\n else if (path.indexOf('src/plugins/usage_collection/') == 0) ctx.team = 'pulse';\n else if (path.indexOf('src/plugins/vis_default_editor') == 0) ctx.team = 'kibana-app-arch';\n else if (path.indexOf('src/plugins/vis_type') == 0) ctx.team = 'kibana-app';\n else if (path.indexOf('src/plugins/visualizations/') == 0) ctx.team = 'kibana-app-arch';\n else if (path.indexOf('src/plugins/visualize/') == 0) ctx.team = 'kibana-app';\n else ctx.team = 'unknown';\n\n } else if (path.indexOf('x-pack/legacy/') == 0) {\n\n if (path.indexOf('x-pack/legacy/plugins/actions/') == 0) ctx.team = 'kibana-alerting-services';\n else if (path.indexOf('x-pack/legacy/plugins/alerting/') == 0) ctx.team = 'kibana-alerting-services';\n else if (path.indexOf('x-pack/legacy/plugins/apm/') == 0) ctx.team = 'apm-ui';\n else if (path.indexOf('x-pack/legacy/plugins/beats_management/') == 0) ctx.team = 'beats';\n else if (path.indexOf('x-pack/legacy/plugins/canvas/') == 0) ctx.team = 'kibana-canvas';\n else if (path.indexOf('x-pack/legacy/plugins/cross_cluster_replication/') == 0) ctx.team = 'es-ui';\n else if (path.indexOf('x-pack/legacy/plugins/dashboard_mode/') == 0) ctx.team = 'kibana-app';\n else if (path.indexOf('x-pack/legacy/plugins/encrypted_saved_objects/') == 0) ctx.team = 'kibana-security';\n else if (path.indexOf('x-pack/legacy/plugins/index_management/') == 0) ctx.team = 'es-ui';\n else if (path.indexOf('x-pack/legacy/plugins/infra/') == 0) ctx.team = 'logs-metrics-ui';\n else if (path.indexOf('x-pack/legacy/plugins/ingest_manager/') == 0) ctx.team = 'ingest-management';\n else if (path.indexOf('x-pack/legacy/plugins/license_management/') == 0) ctx.team = 'es-ui';\n else if (path.indexOf('x-pack/legacy/plugins/maps/') == 0) ctx.team = 'kibana-gis';\n else if (path.indexOf('x-pack/legacy/plugins/ml/') == 0) ctx.team = 'ml-ui';\n else if (path.indexOf('x-pack/legacy/plugins/monitoring/') == 0) ctx.team = 'stack-monitoring-ui';\n else if (path.indexOf('x-pack/legacy/plugins/reporting') == 0) ctx.team = 'kibana-reporting';\n else if (path.indexOf('x-pack/legacy/plugins/rollup/') == 0) ctx.team = 'es-ui';\n else if (path.indexOf('x-pack/legacy/plugins/security/') == 0) ctx.team = 'kibana-security';\n else if (path.indexOf('x-pack/legacy/plugins/siem/') == 0) ctx.team = 'siem';\n else if (path.indexOf('x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules') == 0) ctx.team = 'security-intelligence-analytics';\n else if (path.indexOf('x-pack/legacy/plugins/snapshot_restore/') == 0) ctx.team = 'es-ui';\n else if (path.indexOf('x-pack/legacy/plugins/task_manager') == 0) ctx.team = 'kibana-alerting-services';\n else if (path.indexOf('x-pack/legacy/plugins/triggers_actions_ui/') == 0) ctx.team = 'kibana-alerting-services';\n else if (path.indexOf('x-pack/legacy/plugins/upgrade_assistant/') == 0) ctx.team = 'es-ui';\n else if (path.indexOf('x-pack/legacy/plugins/uptime') == 0) ctx.team = 'uptime';\n else if (path.indexOf('x-pack/legacy/plugins/xpack_main/server/') == 0) ctx.team = 'kibana-platform';\n\n else if (path.indexOf('x-pack/legacy/server/lib/create_router/') == 0) ctx.team = 'es-ui';\n else if (path.indexOf('x-pack/legacy/server/lib/check_license/') == 0) ctx.team = 'es-ui'; \n else if (path.indexOf('x-pack/legacy/server/lib/') == 0) ctx.team = 'kibana-platform'; \n else ctx.team = 'unknown';\n\n } else if (path.indexOf('x-pack/plugins/') == 0) {\n\n if (path.indexOf('x-pack/plugins/actions/') == 0) ctx.team = 'kibana-alerting-services';\n else if (path.indexOf('x-pack/plugins/advanced_ui_actions/') == 0) ctx.team = 'kibana-app-arch';\n else if (path.indexOf('x-pack/plugins/alerts') == 0) ctx.team = 'kibana-alerting-services';\n else if (path.indexOf('x-pack/plugins/alerting_builtins') == 0) ctx.team = 'kibana-alerting-services';\n else if (path.indexOf('x-pack/plugins/apm/') == 0) ctx.team = 'apm-ui';\n else if (path.indexOf('x-pack/plugins/beats_management/') == 0) ctx.team = 'beats';\n else if (path.indexOf('x-pack/plugins/canvas/') == 0) ctx.team = 'kibana-canvas';\n else if (path.indexOf('x-pack/plugins/case') == 0) ctx.team = 'siem';\n else if (path.indexOf('x-pack/plugins/cloud/') == 0) ctx.team = 'kibana-platform';\n else if (path.indexOf('x-pack/plugins/code/') == 0) ctx.team = 'code';\n else if (path.indexOf('x-pack/plugins/console_extensions/') == 0) ctx.team = 'es-ui';\n else if (path.indexOf('x-pack/plugins/cross_cluster_replication/') == 0) ctx.team = 'es-ui';\n else if (path.indexOf('x-pack/plugins/dashboard_enhanced') == 0) ctx.team = 'kibana-app';\n else if (path.indexOf('x-pack/plugins/dashboard_mode') == 0) ctx.team = 'kibana-app';\n else if (path.indexOf('x-pack/plugins/discover_enhanced') == 0) ctx.team = 'kibana-app';\n else if (path.indexOf('x-pack/plugins/embeddable_enhanced') == 0) ctx.team = 'kibana-app-arch';\n else if (path.indexOf('x-pack/plugins/data_enhanced/') == 0) ctx.team = 'kibana-app-arch';\n else if (path.indexOf('x-pack/plugins/drilldowns/') == 0) ctx.team = 'kibana-app-arch';\n else if (path.indexOf('x-pack/plugins/encrypted_saved_objects/') == 0) ctx.team = 'kibana-security';\n else if (path.indexOf('x-pack/plugins/endpoint/') == 0) ctx.team = 'endpoint-app-team';\n else if (path.indexOf('x-pack/plugins/es_ui_shared/') == 0) ctx.team = 'es-ui';\n else if (path.indexOf('x-pack/plugins/event_log/') == 0) ctx.team = 'kibana-alerting-services';\n else if (path.indexOf('x-pack/plugins/features/') == 0) ctx.team = 'kibana-platform';\n else if (path.indexOf('x-pack/plugins/file_upload') == 0) ctx.team = 'kibana-gis';\n else if (path.indexOf('x-pack/plugins/global_search') == 0) ctx.team = 'kibana-platform';\n \n else if (path.indexOf('x-pack/plugins/graph/') == 0) ctx.team = 'kibana-app';\n else if (path.indexOf('x-pack/plugins/grokdebugger/') == 0) ctx.team = 'es-ui';\n else if (path.indexOf('x-pack/plugins/index_lifecycle_management/') == 0) ctx.team = 'es-ui';\n else if (path.indexOf('x-pack/plugins/index_management/') == 0) ctx.team = 'es-ui';\n else if (path.indexOf('x-pack/plugins/infra/') == 0) ctx.team = 'logs-metrics-ui';\n else if (path.indexOf('x-pack/plugins/ingest_manager/') == 0) ctx.team = 'ingest-management';\n else if (path.indexOf('x-pack/plugins/ingest_pipelines/') == 0) ctx.team = 'es-ui';\n \n else if (path.indexOf('x-pack/plugins/lens/') == 0) ctx.team = 'kibana-app';\n else if (path.indexOf('x-pack/plugins/license_management/') == 0) ctx.team = 'es-ui';\n else if (path.indexOf('x-pack/plugins/licensing/') == 0) ctx.team = 'kibana-platform';\n else if (path.indexOf('x-pack/plugins/lists/') == 0) ctx.team = 'siem';\n else if (path.indexOf('x-pack/plugins/logstash') == 0) ctx.team = 'logstash';\n else if (path.indexOf('x-pack/plugins/maps/') == 0) ctx.team = 'kibana-gis';\n else if (path.indexOf('x-pack/plugins/maps_legacy_licensing') == 0) ctx.team = 'maps';\n else if (path.indexOf('x-pack/plugins/ml/') == 0) ctx.team = 'ml-ui';\n else if (path.indexOf('x-pack/plugins/monitoring') == 0) ctx.team = 'stack-monitoring-ui';\n else if (path.indexOf('x-pack/plugins/observability/') == 0) ctx.team = 'apm-ui';\n else if (path.indexOf('x-pack/plugins/oss_telemetry/') == 0) ctx.team = 'pulse';\n else if (path.indexOf('x-pack/plugins/painless_lab/') == 0) ctx.team = 'es-ui';\n else if (path.indexOf('x-pack/plugins/remote_clusters/') == 0) ctx.team = 'es-ui';\n else if (path.indexOf('x-pack/plugins/reporting') == 0) ctx.team = 'kibana-reporting';\n else if (path.indexOf('x-pack/plugins/rollup/') == 0) ctx.team = 'es-ui';\n else if (path.indexOf('x-pack/plugins/searchprofiler/') == 0) ctx.team = 'es-ui';\n else if (path.indexOf('x-pack/plugins/security/') == 0) ctx.team = 'kibana-security';\n else if (path.indexOf('x-pack/plugins/security_solution/') == 0) ctx.team = 'siem';\n \n else if (path.indexOf('x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules') == 0) ctx.team = 'security-intelligence-analytics';\n else if (path.indexOf('x-pack/plugins/siem/') == 0) ctx.team = 'siem';\n else if (path.indexOf('x-pack/plugins/snapshot_restore/') == 0) ctx.team = 'es-ui';\n else if (path.indexOf('x-pack/plugins/spaces/') == 0) ctx.team = 'kibana-security';\n else if (path.indexOf('x-pack/plugins/task_manager/') == 0) ctx.team = 'kibana-alerting-services';\n else if (path.indexOf('x-pack/plugins/telemetry_collection_xpack/') == 0) ctx.team = 'pulse';\n else if (path.indexOf('x-pack/plugins/transform/') == 0) ctx.team = 'ml-ui';\n else if (path.indexOf('x-pack/plugins/translations/') == 0) ctx.team = 'kibana-localization';\n else if (path.indexOf('x-pack/plugins/triggers_actions_ui/') == 0) ctx.team = 'kibana-alerting-services';\n else if (path.indexOf('x-pack/plugins/upgrade_assistant/') == 0) ctx.team = 'es-ui';\n else if (path.indexOf('x-pack/plugins/ui_actions_enhanced') == 0) ctx.team = 'kibana-app-arch';\n else if (path.indexOf('x-pack/plugins/uptime') == 0) ctx.team = 'uptime';\n \n else if (path.indexOf('x-pack/plugins/watcher/') == 0) ctx.team = 'es-ui';\n else ctx.team = 'unknown';\n\n } else if (path.indexOf('packages') == 0) {\n\n if (path.indexOf('packages/kbn-analytics/') == 0) ctx.team = 'pulse';\n else if (path.indexOf('packages/kbn-babel') == 0) ctx.team = 'kibana-operations';\n else if (path.indexOf('packages/kbn-config-schema/') == 0) ctx.team = 'kibana-platform';\n else if (path.indexOf('packages/elastic-datemath') == 0) ctx.team = 'kibana-app-arch';\n else if (path.indexOf('packages/kbn-dev-utils') == 0) ctx.team = 'kibana-operations';\n else if (path.indexOf('packages/kbn-es/') == 0) ctx.team = 'kibana-operations';\n else if (path.indexOf('packages/kbn-eslint') == 0) ctx.team = 'kibana-operations';\n else if (path.indexOf('packages/kbn-expect') == 0) ctx.team = 'kibana-operations';\n else if (path.indexOf('packages/kbn-i18n/') == 0) ctx.team = 'kibana-localization';\n else if (path.indexOf('packages/kbn-interpreter/') == 0) ctx.team = 'kibana-app-arch';\n else if (path.indexOf('packages/kbn-optimizer/') == 0) ctx.team = 'kibana-operations';\n else if (path.indexOf('packages/kbn-pm/') == 0) ctx.team = 'kibana-operations';\n else if (path.indexOf('packages/kbn-test/') == 0) ctx.team = 'kibana-operations';\n else if (path.indexOf('packages/kbn-test-subj-selector/') == 0) ctx.team = 'kibana-operations';\n else if (path.indexOf('packages/kbn-ui-framework/') == 0) ctx.team = 'kibana-design';\n else if (path.indexOf('packages/kbn-ui-shared-deps/') == 0) ctx.team = 'kibana-operations';\n else ctx.team = 'unknown';\n\n } else {\n\n if (path.indexOf('config/kibana.yml') == 0) ctx.team = 'kibana-platform';\n else if (path.indexOf('src/apm.js') == 0) ctx.team = 'apm-ui';\n else if (path.indexOf('src/core/') == 0) ctx.team = 'kibana-platform';\n else if (path.indexOf('src/core/public/i18n/') == 0) ctx.team = 'kibana-localization';\n else if (path.indexOf('src/core/server/csp/') == 0) ctx.team = 'kibana-security';\n else if (path.indexOf('src/dev/') == 0) ctx.team = 'kibana-operations';\n else if (path.indexOf('src/dev/i18n/') == 0) ctx.team = 'kibana-localization';\n else if (path.indexOf('src/dev/run_check_published_api_changes.ts') == 0) ctx.team = 'kibana-platform';\n else if (path.indexOf('packages/kbn-es-archiver/') == 0) ctx.team = 'kibana-operations';\n else if (path.indexOf('src/optimize/') == 0) ctx.team = 'kibana-operations';\n else if (path.indexOf('src/setup_node_env/') == 0) ctx.team = 'kibana-operations';\n else if (path.indexOf('src/test_utils/') == 0) ctx.team = 'kibana-operations'; \n else ctx.team = 'unknown';\n }"}}]} diff --git a/src/dev/code_coverage/ingest_coverage/team_assignment/parse_owners.js b/src/dev/code_coverage/ingest_coverage/team_assignment/parse_owners.js new file mode 100644 index 0000000000000..a07d556c9b403 --- /dev/null +++ b/src/dev/code_coverage/ingest_coverage/team_assignment/parse_owners.js @@ -0,0 +1,35 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { fromEvent } from 'rxjs'; +import { map, filter, takeUntil } from 'rxjs/operators'; +import { lineRead, pathAndTeams, empties, comments, dropCCDelim } from './parse_owners_helpers'; +import { pipe } from '../utils'; + +const cleanAndParse = pipe(dropCCDelim, pathAndTeams); + +const allLines$ = (lineReader) => + fromEvent(lineReader, 'line').pipe( + filter(empties), + filter(comments), + map(cleanAndParse), + takeUntil(fromEvent(lineReader, 'close')) + ); + +export const parse = (codeOwnersPath) => allLines$(lineRead(codeOwnersPath)); diff --git a/src/dev/code_coverage/ingest_coverage/team_assignment/parse_owners_helpers.js b/src/dev/code_coverage/ingest_coverage/team_assignment/parse_owners_helpers.js new file mode 100644 index 0000000000000..454accb00a7b6 --- /dev/null +++ b/src/dev/code_coverage/ingest_coverage/team_assignment/parse_owners_helpers.js @@ -0,0 +1,48 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { always, id, pipe } from '../utils'; +import * as Either from '../either'; +import readline from 'readline'; +import { createReadStream } from 'fs'; +import { pluckIndex } from '../transforms'; + +const coverageDelimRe = /^#CC#\s/; + +export const empties = (x) => x !== ''; +export const comments = (x) => !/^#\s{1,3}/.test(x); +const dropDelim = (x) => () => x.replace(coverageDelimRe, ''); + +export const dropCCDelim = (x) => + Either.fromNullable(coverageDelimRe.test(x)).fold(always(x), id(dropDelim(x))); + +const splitFilter = (splitter) => (x) => x.split(splitter).filter(empties); +const spaceSplit = splitFilter(' '); +const esSplit = splitFilter('@elastic/'); +const getFirst = pluckIndex(0); +const trimEsGrabFirst = pipe(esSplit, getFirst); + +export const pathAndTeams = (x) => { + const [path, ...teamEntries] = spaceSplit(x); + const teams = teamEntries.map(trimEsGrabFirst); + + return [path, teams]; +}; + +export const lineRead = (x) => readline.createInterface({ input: createReadStream(x) }); diff --git a/src/dev/code_coverage/ingest_coverage/team_assignment/parsing_helpers.js b/src/dev/code_coverage/ingest_coverage/team_assignment/parsing_helpers.js new file mode 100644 index 0000000000000..50dd6f719f34e --- /dev/null +++ b/src/dev/code_coverage/ingest_coverage/team_assignment/parsing_helpers.js @@ -0,0 +1,30 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { always } from '../utils'; +import * as Either from '../either'; + +const coverageDelimRe = /^#CC#\s/; + +export const empties = (x) => x !== ''; +export const comments = (x) => !/^#\s{1,3}/.test(x); +const dropDelim = (x) => x.replace(coverageDelimRe, ''); + +export const dropCCDelim = (x) => + Either.fromNullable(coverageDelimRe.test(x)).fold(always(x), always(dropDelim(x))); diff --git a/src/dev/code_coverage/ingest_coverage/team_assignment/update_ingest_pipeline.js b/src/dev/code_coverage/ingest_coverage/team_assignment/update_ingest_pipeline.js deleted file mode 100644 index 22a9d0a461ebf..0000000000000 --- a/src/dev/code_coverage/ingest_coverage/team_assignment/update_ingest_pipeline.js +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { createFailError } from '@kbn/dev-utils'; -import { ES_HOST } from '../constants'; -import { pretty, green } from '../utils'; - -const { Client } = require('@elastic/elasticsearch'); - -const node = ES_HOST; -const client = new Client({ node }); - -export const update = (id) => (log) => async (body) => { - try { - await client.ingest.putPipeline({ id, body }); - log.verbose(`### Ingestion Pipeline ID: ${green(id)}`); - log.verbose(`### Payload Partial: \n${body.slice(0, 600)}...`); - } catch (e) { - throw createFailError(`${pretty(e.meta)}`); - } -}; diff --git a/src/dev/code_coverage/ingest_coverage/transforms.js b/src/dev/code_coverage/ingest_coverage/transforms.js index b8c9acd6fc49d..ff6ffd46462ed 100644 --- a/src/dev/code_coverage/ingest_coverage/transforms.js +++ b/src/dev/code_coverage/ingest_coverage/transforms.js @@ -18,8 +18,12 @@ */ import * as Either from './either'; -import { fromNullable } from './maybe'; -import { always, id, noop } from './utils'; +import * as Maybe from './maybe'; +import { always, id, noop, pink } from './utils'; +import execa from 'execa'; +import { resolve } from 'path'; + +const ROOT_DIR = resolve(__dirname, '../../../..'); const maybeTotal = (x) => (x === 'total' ? Either.left(x) : Either.right(x)); @@ -83,20 +87,60 @@ export const staticSite = (urlBase) => (obj) => { return { ...obj, staticSiteUrl: prokForBoth() }; }; +const leadingSlashRe = /^\//; +export const maybeDropLeadingSlash = (x) => + leadingSlashRe.test(x) ? Either.right(x) : Either.left(x); +export const dropLeadingSlash = (x) => x.replace(leadingSlashRe, ''); +export const stripLeading = (x) => maybeDropLeadingSlash(x).fold(id, dropLeadingSlash); + export const coveredFilePath = (obj) => { const { staticSiteUrl, COVERAGE_INGESTION_KIBANA_ROOT } = obj; const withoutCoveredFilePath = always(obj); - const leadingSlashRe = /^\//; - const maybeDropLeadingSlash = (x) => (leadingSlashRe.test(x) ? Either.right(x) : Either.left(x)); - const dropLeadingSlash = (x) => x.replace(leadingSlashRe, ''); - const dropRoot = (root) => (x) => - maybeDropLeadingSlash(x.replace(root, '')).fold(id, dropLeadingSlash); + const dropRoot = (root) => (x) => stripLeading(x.replace(root, '')); return maybeTotal(staticSiteUrl) .map(dropRoot(COVERAGE_INGESTION_KIBANA_ROOT)) .fold(withoutCoveredFilePath, (coveredFilePath) => ({ ...obj, coveredFilePath })); }; +const findTeam = (x) => x.match(/.+\s{1,3}(.+)$/, 'gm'); +export const pluckIndex = (idx) => (xs) => xs[idx]; +const pluckTeam = pluckIndex(1); + +export const teamAssignment = (teamAssignmentsPath) => (log) => async (obj) => { + const { coveredFilePath } = obj; + const isTotal = Either.fromNullable(obj.isTotal); + + return isTotal.isRight() ? obj : await assignTeam(teamAssignmentsPath, coveredFilePath, log, obj); +}; +export const last = (x) => { + const xs = x.split('\n'); + const len = xs.length; + + return len === 1 ? xs[0] : xs[len - 1]; +}; +async function assignTeam(teamAssignmentsPath, coveredFilePath, log, obj) { + const params = [coveredFilePath, teamAssignmentsPath]; + + let grepResponse; + + try { + const { stdout } = await execa('grep', params, { cwd: ROOT_DIR }); + grepResponse = stdout; + } catch (e) { + log.error(`\n!!! Unknown Team for path: \n\t\t${pink(coveredFilePath)}\n`); + } + + return Either.fromNullable(grepResponse) + .map(last) + .map(findTeam) + .map(pluckTeam) + .fold( + () => ({ team: 'unknown', ...obj }), + (team) => ({ team, ...obj }) + ); +} + export const ciRunUrl = (obj) => Either.fromNullable(process.env.CI_RUN_URL).fold(always(obj), (ciRunUrl) => ({ ...obj, @@ -126,13 +170,12 @@ export const itemizeVcs = (vcsInfo) => (obj) => { }; const mutateVcs = (x) => (vcs.commitMsg = truncateMsg(x)); - fromNullable(commitMsg).map(mutateVcs); + Maybe.fromNullable(commitMsg).map(mutateVcs); const vcsCompareUrl = process.env.FETCHED_PREVIOUS ? `${comparePrefix()}/${process.env.FETCHED_PREVIOUS}...${sha}` : 'PREVIOUS SHA NOT PROVIDED'; - // const withoutPreviousL = always({ ...obj, vcs }); const withPreviousR = () => ({ ...obj, vcs: { diff --git a/src/dev/code_coverage/ingest_coverage/utils.js b/src/dev/code_coverage/ingest_coverage/utils.js index 7d817bdf7a6f3..e854e3d3b7248 100644 --- a/src/dev/code_coverage/ingest_coverage/utils.js +++ b/src/dev/code_coverage/ingest_coverage/utils.js @@ -22,6 +22,10 @@ import chalk from 'chalk'; export const pipe = (...fns) => fns.reduce((f, g) => (...args) => g(f(...args))); export const noop = () => {}; export const green = (x) => chalk.greenBright.bold(x); +export const pink = (x) => chalk.bgMagenta.bold.cyan.bold(x); export const id = (x) => x; -export const always = (x) => () => x; +export const always = (x) => () => x; // Wraps a value in a fn. Eager evaluation if passed a fn. export const pretty = (x) => JSON.stringify(x, null, 2); +export const reThrow = (e) => { + throw e; +}; diff --git a/src/dev/code_coverage/shell_scripts/assign_teams.sh b/src/dev/code_coverage/shell_scripts/assign_teams.sh deleted file mode 100644 index aaa14655a9a26..0000000000000 --- a/src/dev/code_coverage/shell_scripts/assign_teams.sh +++ /dev/null @@ -1,15 +0,0 @@ -#!/bin/bash - -echo "### Code Coverage Team Assignment" -echo "" - -PIPELINE_NAME=$1 -export PIPELINE_NAME - -ES_HOST="https://${USER_FROM_VAULT}:${PASS_FROM_VAULT}@${HOST_FROM_VAULT}" -export ES_HOST - -node scripts/load_team_assignment.js --verbose --path src/dev/code_coverage/ingest_coverage/team_assignment/ingestion_pipeline_painless.json - -echo "### Code Coverage Team Assignment - Complete" -echo "" diff --git a/src/dev/code_coverage/shell_scripts/generate_team_assignments_and_ingest_coverage.sh b/src/dev/code_coverage/shell_scripts/generate_team_assignments_and_ingest_coverage.sh new file mode 100644 index 0000000000000..62b81929ae79b --- /dev/null +++ b/src/dev/code_coverage/shell_scripts/generate_team_assignments_and_ingest_coverage.sh @@ -0,0 +1,50 @@ +#!/bin/bash + +echo "### Ingesting Code Coverage" +echo "" + +COVERAGE_JOB_NAME=$1 +export COVERAGE_JOB_NAME +echo "### debug COVERAGE_JOB_NAME: ${COVERAGE_JOB_NAME}" + +BUILD_ID=$2 +export BUILD_ID + +CI_RUN_URL=$3 +export CI_RUN_URL +echo "### debug CI_RUN_URL: ${CI_RUN_URL}" + +FETCHED_PREVIOUS=$4 +export FETCHED_PREVIOUS +echo "### debug FETCHED_PREVIOUS: ${FETCHED_PREVIOUS}" + +ES_HOST="https://${USER_FROM_VAULT}:${PASS_FROM_VAULT}@${HOST_FROM_VAULT}" +export ES_HOST + +STATIC_SITE_URL_BASE='https://kibana-coverage.elastic.dev' +export STATIC_SITE_URL_BASE + +DELAY=100 +export DELAY + +TEAM_ASSIGN_PATH=$5 + +# Build team assignments dat file +node scripts/generate_team_assignments.js --verbose --src .github/CODEOWNERS --dest $TEAM_ASSIGN_PATH + +for x in jest functional; do + echo "### Ingesting coverage for ${x}" + + COVERAGE_SUMMARY_FILE=target/kibana-coverage/${x}-combined/coverage-summary.json + + node scripts/ingest_coverage.js --verbose --path ${COVERAGE_SUMMARY_FILE} --vcsInfoPath ./VCS_INFO.txt --teamAssignmentsPath $TEAM_ASSIGN_PATH +done + +# Need to override COVERAGE_INGESTION_KIBANA_ROOT since mocha json file has original intake worker path +COVERAGE_SUMMARY_FILE=target/kibana-coverage/mocha-combined/coverage-summary.json +export COVERAGE_INGESTION_KIBANA_ROOT=/dev/shm/workspace/kibana + +node scripts/ingest_coverage.js --verbose --path ${COVERAGE_SUMMARY_FILE} --vcsInfoPath ./VCS_INFO.txt --teamAssignmentsPath $TEAM_ASSIGN_PATH + +echo "### Ingesting Code Coverage - Complete" +echo "" diff --git a/src/dev/code_coverage/shell_scripts/ingest_coverage.sh b/src/dev/code_coverage/shell_scripts/ingest_coverage.sh deleted file mode 100644 index 0b67dac307473..0000000000000 --- a/src/dev/code_coverage/shell_scripts/ingest_coverage.sh +++ /dev/null @@ -1,45 +0,0 @@ -#!/bin/bash - -echo "### Ingesting Code Coverage" -echo "" - -COVERAGE_JOB_NAME=$1 -export COVERAGE_JOB_NAME -echo "### debug COVERAGE_JOB_NAME: ${COVERAGE_JOB_NAME}" - -BUILD_ID=$2 -export BUILD_ID - -CI_RUN_URL=$3 -export CI_RUN_URL -echo "### debug CI_RUN_URL: ${CI_RUN_URL}" - -FETCHED_PREVIOUS=$4 -export FETCHED_PREVIOUS -echo "### debug FETCHED_PREVIOUS: ${FETCHED_PREVIOUS}" - -ES_HOST="https://${USER_FROM_VAULT}:${PASS_FROM_VAULT}@${HOST_FROM_VAULT}" -export ES_HOST - -STATIC_SITE_URL_BASE='https://kibana-coverage.elastic.dev' -export STATIC_SITE_URL_BASE - -DELAY=100 -export DELAY - -for x in jest functional; do - echo "### Ingesting coverage for ${x}" - - COVERAGE_SUMMARY_FILE=target/kibana-coverage/${x}-combined/coverage-summary.json - - node scripts/ingest_coverage.js --verbose --path ${COVERAGE_SUMMARY_FILE} --vcsInfoPath ./VCS_INFO.txt -done - -# Need to override COVERAGE_INGESTION_KIBANA_ROOT since mocha json file has original intake worker path -COVERAGE_SUMMARY_FILE=target/kibana-coverage/mocha-combined/coverage-summary.json -export COVERAGE_INGESTION_KIBANA_ROOT=/dev/shm/workspace/kibana - -node scripts/ingest_coverage.js --verbose --path ${COVERAGE_SUMMARY_FILE} --vcsInfoPath ./VCS_INFO.txt - -echo "### Ingesting Code Coverage - Complete" -echo "" diff --git a/src/dev/jest/config.integration.js b/src/dev/jest/config.integration.js index 2fd6bd120d553..970c00bb68b98 100644 --- a/src/dev/jest/config.integration.js +++ b/src/dev/jest/config.integration.js @@ -31,7 +31,10 @@ export default { ), reporters: [ 'default', - ['/src/dev/jest/junit_reporter.js', { reportName: 'Jest Integration Tests' }], + [ + '/packages/kbn-test/target/jest/junit_reporter', + { reportName: 'Jest Integration Tests' }, + ], ], setupFilesAfterEnv: ['/src/dev/jest/setup/after_env.integration.js'], }; diff --git a/src/dev/jest/config.js b/src/dev/jest/config.js index 5d31db63773fa..f582a8f3d4410 100644 --- a/src/dev/jest/config.js +++ b/src/dev/jest/config.js @@ -55,7 +55,6 @@ export default { '@elastic/eui$': '/node_modules/@elastic/eui/test-env', '@elastic/eui/lib/(.*)?': '/node_modules/@elastic/eui/test-env/$1', '^src/plugins/(.*)': '/src/plugins/$1', - '^uiExports/(.*)': '/src/dev/jest/mocks/file_mock.js', '^test_utils/(.*)': '/src/test_utils/public/$1', '^fixtures/(.*)': '/src/fixtures/$1', '\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$': @@ -100,5 +99,5 @@ export default { '/src/plugins/kibana_react/public/util/test_helpers/react_mount_serializer.ts', '/node_modules/enzyme-to-json/serializer', ], - reporters: ['default', '/src/dev/jest/junit_reporter.js'], + reporters: ['default', '/packages/kbn-test/target/jest/junit_reporter'], }; diff --git a/src/dev/jest/integration_tests/__fixtures__/package.json b/src/dev/jest/integration_tests/__fixtures__/package.json deleted file mode 100644 index 1a9a446d524bc..0000000000000 --- a/src/dev/jest/integration_tests/__fixtures__/package.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "name": "fixture", - "jest": { - "testMatch": [ - "**/test.js" - ], - "transform": { - "^.+\\.js$": "/../../babel_transform.js" - }, - "reporters": [ - ["/../../junit_reporter.js", {"rootDirectory": "."}] - ] - } -} diff --git a/src/dev/jest/integration_tests/junit_reporter.test.js b/src/dev/jest/integration_tests/junit_reporter.test.js deleted file mode 100644 index 3280482a54203..0000000000000 --- a/src/dev/jest/integration_tests/junit_reporter.test.js +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { resolve } from 'path'; -import { promisify } from 'util'; -import { readFileSync } from 'fs'; - -import del from 'del'; -import execa from 'execa'; -import xml2js from 'xml2js'; -import { makeJunitReportPath } from '@kbn/test'; - -const MINUTE = 1000 * 60; -const ROOT_DIR = resolve(__dirname, '../../../../'); -const FIXTURE_DIR = resolve(__dirname, '__fixtures__'); -const TARGET_DIR = resolve(FIXTURE_DIR, 'target'); -const XML_PATH = makeJunitReportPath(FIXTURE_DIR, 'Jest Tests'); - -afterAll(async () => { - await del(TARGET_DIR); -}); - -const parseXml = promisify(xml2js.parseString); - -it( - 'produces a valid junit report for failures', - async () => { - const result = await execa( - process.execPath, - ['-r', require.resolve('../../../setup_node_env'), require.resolve('jest/bin/jest')], - { - cwd: FIXTURE_DIR, - env: { - CI: 'true', - }, - reject: false, - } - ); - - expect(result.exitCode).toBe(1); - await expect(parseXml(readFileSync(XML_PATH, 'utf8'))).resolves.toEqual({ - testsuites: { - $: { - name: 'jest', - skipped: '0', - tests: '1', - time: expect.anything(), - timestamp: expect.anything(), - }, - testsuite: [ - { - $: { - failures: '1', - file: resolve(ROOT_DIR, 'src/dev/jest/integration_tests/__fixtures__/test.js'), - name: 'test.js', - skipped: '0', - tests: '1', - time: expect.anything(), - timestamp: expect.anything(), - }, - testcase: [ - { - $: { - classname: 'Jest Tests.·', - name: 'fails', - time: expect.anything(), - }, - failure: [expect.stringMatching(/Error: failure\s+at /m)], - }, - ], - }, - ], - }, - }); - }, - 3 * MINUTE -); diff --git a/src/dev/jest/junit_reporter.js b/src/dev/jest/junit_reporter.js deleted file mode 100644 index f33358c081a06..0000000000000 --- a/src/dev/jest/junit_reporter.js +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { resolve, dirname, relative } from 'path'; -import { writeFileSync, mkdirSync } from 'fs'; - -import xmlBuilder from 'xmlbuilder'; - -import { escapeCdata, makeJunitReportPath } from '@kbn/test'; - -const ROOT_DIR = dirname(require.resolve('../../../package.json')); - -/** - * Jest reporter that produces JUnit report when running on CI - * @class JestJUnitReporter - */ -export default class JestJUnitReporter { - constructor(globalConfig, options = {}) { - const { reportName = 'Jest Tests', rootDirectory = ROOT_DIR } = options; - - this._reportName = reportName; - this._rootDirectory = resolve(rootDirectory); - } - - /** - * Called by jest when all tests complete - * @param {Object} contexts - * @param {JestResults} results see https://facebook.github.io/jest/docs/en/configuration.html#testresultsprocessor-string - * @return {undefined} - */ - onRunComplete(contexts, results) { - if (!process.env.CI || process.env.DISABLE_JUNIT_REPORTER || !results.testResults.length) { - return; - } - - const reportName = this._reportName; - const rootDirectory = this._rootDirectory; - const root = xmlBuilder.create( - 'testsuites', - { encoding: 'utf-8' }, - {}, - { skipNullAttributes: true } - ); - - const msToIso = (ms) => (ms ? new Date(ms).toISOString().slice(0, -5) : undefined); - const msToSec = (ms) => (ms ? (ms / 1000).toFixed(3) : undefined); - - root.att({ - name: 'jest', - timestamp: msToIso(results.startTime), - time: msToSec(Date.now() - results.startTime), - tests: results.numTotalTests, - failures: results.numFailingTests, - skipped: results.numPendingTests, - }); - - // top level test results are the files/suites - results.testResults.forEach((suite) => { - const suiteEl = root.ele('testsuite', { - name: relative(rootDirectory, suite.testFilePath), - timestamp: msToIso(suite.perfStats.start), - time: msToSec(suite.perfStats.end - suite.perfStats.start), - tests: suite.testResults.length, - failures: suite.numFailingTests, - skipped: suite.numPendingTests, - file: suite.testFilePath, - }); - - // nested in there are the tests in that file - const relativePath = dirname(relative(rootDirectory, suite.testFilePath)); - const classname = `${reportName}.${relativePath.replace(/\./g, '·')}`; - suite.testResults.forEach((test) => { - const testEl = suiteEl.ele('testcase', { - classname, - name: [...test.ancestorTitles, test.title].join(' '), - time: msToSec(test.duration), - }); - - test.failureMessages.forEach((message) => { - testEl.ele('failure').dat(escapeCdata(message)); - }); - - if (test.status === 'pending') { - testEl.ele('skipped'); - } - }); - }); - - const reportPath = makeJunitReportPath(rootDirectory, reportName); - const reportXML = root.end(); - mkdirSync(dirname(reportPath), { recursive: true }); - writeFileSync(reportPath, reportXML, 'utf8'); - } -} diff --git a/src/dev/jest/setup/babel_polyfill.js b/src/dev/jest/setup/babel_polyfill.js index 58325c1a67f94..085c8e2a25eef 100644 --- a/src/dev/jest/setup/babel_polyfill.js +++ b/src/dev/jest/setup/babel_polyfill.js @@ -20,4 +20,4 @@ // Note: In theory importing the polyfill should not be needed, as Babel should // include the necessary polyfills when using `@babel/preset-env`, but for some // reason it did not work. See https://github.com/elastic/kibana/issues/14506 -import '../../../setup_node_env/babel_register/polyfill'; +import '@kbn/optimizer/src/node/polyfill'; diff --git a/src/dev/jest/setup/react_testing_library.js b/src/dev/jest/setup/react_testing_library.js index 41f58354844a3..90f73b04dc210 100644 --- a/src/dev/jest/setup/react_testing_library.js +++ b/src/dev/jest/setup/react_testing_library.js @@ -19,14 +19,13 @@ import '@testing-library/jest-dom'; /** - * Have to import "/pure" here to not register afterEach() hook clean up - * in the very beginning. There are couple tests which fail with clean up hook. - * On CI they run before first test which imports '@testing-library/react' - * and registers afterEach hook so the whole suite is passing. - * This have to be fixed as we depend on test order execution + * PLEASE NOTE: + * Importing '@testing-library/react' registers an `afterEach(cleanup)` side effect. + * It has tricky code that flushes pending promises, that previously led to unpredictable test failures * https://github.com/elastic/kibana/issues/59469 + * But since newer versions it has stabilised itself */ -import { configure } from '@testing-library/react/pure'; +import { configure } from '@testing-library/react'; // instead of default 'data-testid', use kibana's 'data-test-subj' -configure({ testIdAttribute: 'data-test-subj' }); +configure({ testIdAttribute: 'data-test-subj', asyncUtilTimeout: 4500 }); diff --git a/src/dev/notice/generate_notice_from_source.ts b/src/dev/notice/generate_notice_from_source.ts index 9f7eb9d9e1aa4..e362427682ec0 100644 --- a/src/dev/notice/generate_notice_from_source.ts +++ b/src/dev/notice/generate_notice_from_source.ts @@ -52,7 +52,7 @@ export async function generateNoticeFromSource({ productName, directory, log }: 'src/plugins/*/{node_modules,build,dist}/**', 'x-pack/{node_modules,build,dist,data}/**', 'x-pack/packages/*/{node_modules,build,dist}/**', - 'x-pack/plugins/*/{node_modules,build,dist}/**', + 'x-pack/plugins/**/{node_modules,build,dist}/**', '**/target/**', ], }; diff --git a/src/dev/precommit_hook/casing_check_config.js b/src/dev/precommit_hook/casing_check_config.js index ba58dcdfa4d58..9cd6ca6801bc3 100644 --- a/src/dev/precommit_hook/casing_check_config.js +++ b/src/dev/precommit_hook/casing_check_config.js @@ -50,14 +50,12 @@ export const IGNORE_FILE_GLOBS = [ 'vars/*', '.ci/pipeline-library/**/*', - // Files in this directory must match a pre-determined name in some cases. - 'x-pack/plugins/canvas/storybook/*', - // filename must match language code which requires capital letters '**/translations/*.json', - // filename is required by storybook - 'packages/kbn-storybook/storybook_config/preview-head.html', + // Storybook has predetermined filesnames + '**/preview-body.html', + '**/preview-head.html', // filename required by api-extractor 'api-documenter.json', diff --git a/src/dev/run_check_published_api_changes.ts b/src/dev/run_check_published_api_changes.ts index 28e8570812915..984e013114c9e 100644 --- a/src/dev/run_check_published_api_changes.ts +++ b/src/dev/run_check_published_api_changes.ts @@ -230,6 +230,11 @@ async function run(folder: string, { opts }: { opts: Options }): Promise`, diff --git a/src/dev/typescript/build_refs.ts b/src/dev/typescript/build_refs.ts index cbb596c185f8b..fdc1dfbfffa0b 100644 --- a/src/dev/typescript/build_refs.ts +++ b/src/dev/typescript/build_refs.ts @@ -18,12 +18,18 @@ */ import execa from 'execa'; +import Path from 'path'; import { run, ToolingLog } from '@kbn/dev-utils'; -export async function buildRefs(log: ToolingLog) { +export async function buildAllRefs(log: ToolingLog) { + await buildRefs(log, 'tsconfig.refs.json'); + await buildRefs(log, Path.join('x-pack', 'tsconfig.refs.json')); +} + +async function buildRefs(log: ToolingLog, projectPath: string) { try { - log.info('Building TypeScript projects refs...'); - await execa(require.resolve('typescript/bin/tsc'), ['-b', 'tsconfig.refs.json']); + log.debug(`Building TypeScript projects refs for ${projectPath}...`); + await execa(require.resolve('typescript/bin/tsc'), ['-b', projectPath, '--pretty']); } catch (e) { log.error(e); process.exit(1); @@ -31,7 +37,12 @@ export async function buildRefs(log: ToolingLog) { } export async function runBuildRefs() { - run(async ({ log }) => { - await buildRefs(log); - }); + run( + async ({ log }) => { + await buildAllRefs(log); + }, + { + description: 'Build TypeScript projects', + } + ); } diff --git a/src/dev/typescript/projects.ts b/src/dev/typescript/projects.ts index 4d1e549e192b6..9891e9fa02c82 100644 --- a/src/dev/typescript/projects.ts +++ b/src/dev/typescript/projects.ts @@ -24,11 +24,11 @@ import { Project } from './project'; export const PROJECTS = [ new Project(resolve(REPO_ROOT, 'tsconfig.json')), - new Project(resolve(REPO_ROOT, 'src/test_utils/tsconfig.json')), - new Project(resolve(REPO_ROOT, 'src/core/tsconfig.json')), new Project(resolve(REPO_ROOT, 'test/tsconfig.json'), { name: 'kibana/test' }), new Project(resolve(REPO_ROOT, 'x-pack/tsconfig.json')), new Project(resolve(REPO_ROOT, 'x-pack/test/tsconfig.json'), { name: 'x-pack/test' }), + new Project(resolve(REPO_ROOT, 'src/test_utils/tsconfig.json')), + new Project(resolve(REPO_ROOT, 'src/core/tsconfig.json')), new Project(resolve(REPO_ROOT, 'x-pack/plugins/security_solution/cypress/tsconfig.json'), { name: 'security_solution/cypress', }), @@ -47,6 +47,12 @@ export const PROJECTS = [ ...glob .sync('packages/*/tsconfig.json', { cwd: REPO_ROOT }) .map((path) => new Project(resolve(REPO_ROOT, path))), + ...glob + .sync('src/plugins/*/tsconfig.json', { cwd: REPO_ROOT }) + .map((path) => new Project(resolve(REPO_ROOT, path))), + ...glob + .sync('x-pack/plugins/*/tsconfig.json', { cwd: REPO_ROOT }) + .map((path) => new Project(resolve(REPO_ROOT, path))), ...glob .sync('examples/*/tsconfig.json', { cwd: REPO_ROOT }) .map((path) => new Project(resolve(REPO_ROOT, path))), diff --git a/src/dev/typescript/run_type_check_cli.ts b/src/dev/typescript/run_type_check_cli.ts index 00968b7259a30..c52b9454c28be 100644 --- a/src/dev/typescript/run_type_check_cli.ts +++ b/src/dev/typescript/run_type_check_cli.ts @@ -24,7 +24,7 @@ import getopts from 'getopts'; import { execInProjects } from './exec_in_projects'; import { filterProjectsByFlag } from './projects'; -import { buildRefs } from './build_refs'; +import { buildAllRefs } from './build_refs'; export async function runTypeCheckCli() { const extraFlags: string[] = []; @@ -80,7 +80,7 @@ export async function runTypeCheckCli() { process.exit(); } - await buildRefs(log); + await buildAllRefs(log); const tscArgs = [ // composite project cannot be used with --noEmit diff --git a/src/fixtures/stubbed_logstash_index_pattern.js b/src/fixtures/stubbed_logstash_index_pattern.js index 5735b01eb3db4..5d6d254b9a000 100644 --- a/src/fixtures/stubbed_logstash_index_pattern.js +++ b/src/fixtures/stubbed_logstash_index_pattern.js @@ -17,10 +17,10 @@ * under the License. */ -import StubIndexPattern from 'test_utils/stub_index_pattern'; import stubbedLogstashFields from 'fixtures/logstash_fields'; import { getKbnFieldType } from '../plugins/data/common'; +import { getStubIndexPattern } from '../plugins/data/public/test_utils'; import { uiSettingsServiceMock } from '../core/public/ui_settings/ui_settings_service.mock'; const uiSettingSetupMock = uiSettingsServiceMock.createSetupContract(); @@ -46,7 +46,7 @@ export default function stubbedLogstashIndexPatternService() { }; }); - const indexPattern = new StubIndexPattern('logstash-*', (cfg) => cfg, 'time', fields, { + const indexPattern = getStubIndexPattern('logstash-*', (cfg) => cfg, 'time', fields, { uiSettings: uiSettingSetupMock, }); diff --git a/src/fixtures/stubbed_saved_object_index_pattern.ts b/src/fixtures/stubbed_saved_object_index_pattern.ts index 44b391f14cf9c..261e451db5452 100644 --- a/src/fixtures/stubbed_saved_object_index_pattern.ts +++ b/src/fixtures/stubbed_saved_object_index_pattern.ts @@ -28,10 +28,10 @@ export function stubbedSavedObjectIndexPattern(id: string | null = null) { type: 'index-pattern', attributes: { timeFieldName: 'timestamp', - customFormats: '{}', + customFormats: {}, fields: mockLogstashFields, title: 'title', }, - version: 2, + version: '2', }; } diff --git a/src/fixtures/telemetry_collectors/.telemetryrc.json b/src/fixtures/telemetry_collectors/.telemetryrc.json index 31203149c9b57..c25d31eb182c7 100644 --- a/src/fixtures/telemetry_collectors/.telemetryrc.json +++ b/src/fixtures/telemetry_collectors/.telemetryrc.json @@ -2,6 +2,7 @@ "root": ".", "output": ".", "exclude": [ - "./unmapped_collector.ts" + "./unmapped_collector.ts", + "./externally_defined_usage_collector/index.ts" ] } diff --git a/src/fixtures/telemetry_collectors/constants.ts b/src/fixtures/telemetry_collectors/constants.ts index 4aac9e66cdbdb..5b66161d07101 100644 --- a/src/fixtures/telemetry_collectors/constants.ts +++ b/src/fixtures/telemetry_collectors/constants.ts @@ -51,3 +51,27 @@ export const externallyDefinedSchema: MakeSchemaFrom<{ locale: string }> = { type: 'keyword', }, }; + +export type TypeAliasWithUnion = Usage & WithUnion; + +export type TypeAliasWithRecord = Usage & Record; + +export type MappedTypeProps = 'prop1' | 'prop2'; + +export type MappedTypeExtraProps = 'prop3' | 'prop4'; + +export type MappedTypeAllProps = MappedTypeProps | MappedTypeExtraProps; + +export interface MappedTypes { + mappedTypeWithExternallyDefinedProps: { + [key in MappedTypeProps]: number; + }; + mappedTypeWithOneInlineProp: { + [key in 'prop3']: number; + }; +} + +export type RecordWithKnownProps = Record; +export type RecordWithKnownAllProps = Record; + +export type IndexedAccessType = Pick; diff --git a/src/fixtures/telemetry_collectors/externally_defined_usage_collector/get_usage_collector.ts b/src/fixtures/telemetry_collectors/externally_defined_usage_collector/get_usage_collector.ts new file mode 100644 index 0000000000000..d158afe271ff4 --- /dev/null +++ b/src/fixtures/telemetry_collectors/externally_defined_usage_collector/get_usage_collector.ts @@ -0,0 +1,39 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export interface Usage { + collectorName: string; +} + +export function getUsageCollector(collectorName: string) { + return { + type: 'externally_defined_usage_collector', + isReady: () => true, + schema: { + collectorName: { + type: 'keyword' as 'keyword', + }, + }, + fetch(): Usage { + return { + collectorName, + }; + }, + }; +} diff --git a/src/fixtures/telemetry_collectors/externally_defined_usage_collector/index.ts b/src/fixtures/telemetry_collectors/externally_defined_usage_collector/index.ts new file mode 100644 index 0000000000000..b88ecfced7e8a --- /dev/null +++ b/src/fixtures/telemetry_collectors/externally_defined_usage_collector/index.ts @@ -0,0 +1,28 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { UsageCollectionSetup } from 'src/plugins/usage_collection/server'; +import { getUsageCollector } from './get_usage_collector'; + +export function registerCollector(collectorSet: UsageCollectionSetup) { + const collectorName = 'some_configs'; + const collector = collectorSet.makeUsageCollector(getUsageCollector(collectorName)); + + collectorSet.registerCollector(collector); +} diff --git a/src/fixtures/telemetry_collectors/indexed_interface_with_not_matching_schema.ts b/src/fixtures/telemetry_collectors/indexed_interface_with_not_matching_schema.ts index 0ec8d2e15c34a..b925696c96563 100644 --- a/src/fixtures/telemetry_collectors/indexed_interface_with_not_matching_schema.ts +++ b/src/fixtures/telemetry_collectors/indexed_interface_with_not_matching_schema.ts @@ -41,8 +41,9 @@ export const myCollector = makeUsageCollector({ return { something: { count_2: 2 } }; }, schema: { + // @ts-expect-error Intentionally missing count_2 something: { - count_1: { type: 'long' }, // Intentionally missing count_2 + count_1: { type: 'long' }, }, }, }); diff --git a/src/fixtures/telemetry_collectors/schema_defined_with_spreads_collector.ts b/src/fixtures/telemetry_collectors/schema_defined_with_spreads_collector.ts new file mode 100644 index 0000000000000..af9fef0bbd297 --- /dev/null +++ b/src/fixtures/telemetry_collectors/schema_defined_with_spreads_collector.ts @@ -0,0 +1,77 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +import { CollectorSet, MakeSchemaFrom } from '../../plugins/usage_collection/server/collector'; +import { loggerMock } from '../../core/server/logging/logger.mock'; + +const { makeUsageCollector } = new CollectorSet({ + logger: loggerMock.create(), + maximumWaitTimeForAllCollectorsInS: 0, +}); + +interface MyObject { + total: number; + type: boolean; +} + +interface Usage { + flat?: string; + my_str?: string; + my_objects: MyObject; +} + +const SOME_NUMBER: number = 123; + +const someSchema: MakeSchemaFrom> = { + flat: { + type: 'keyword', + }, + my_str: { + type: 'text', + }, +}; + +const someOtherSchema: MakeSchemaFrom> = { + my_objects: { + total: { + type: 'number', + }, + type: { type: 'boolean' }, + }, +}; + +export const myCollector = makeUsageCollector({ + type: 'schema_defined_with_spreads', + isReady: () => true, + fetch() { + const testString = '123'; + + return { + flat: 'hello', + my_str: testString, + my_objects: { + total: SOME_NUMBER, + type: true, + }, + }; + }, + schema: { + ...someSchema, + ...someOtherSchema, + }, +}); diff --git a/src/fixtures/telemetry_collectors/working_collector.ts b/src/fixtures/telemetry_collectors/working_collector.ts index bdf10b5e54919..0a3bf49638a7b 100644 --- a/src/fixtures/telemetry_collectors/working_collector.ts +++ b/src/fixtures/telemetry_collectors/working_collector.ts @@ -90,12 +90,15 @@ export const myCollector = makeUsageCollector({ type: { type: 'boolean' }, }, my_array: { - total: { - type: 'number', + type: 'array', + items: { + total: { + type: 'number', + }, + type: { type: 'boolean' }, }, - type: { type: 'boolean' }, }, - my_str_array: { type: 'keyword' }, + my_str_array: { type: 'array', items: { type: 'keyword' } }, my_index_signature_prop: { count: { type: 'number' }, avg: { type: 'number' }, diff --git a/src/legacy/plugin_discovery/README.md b/src/legacy/plugin_discovery/README.md deleted file mode 100644 index 83e7c10d16fff..0000000000000 --- a/src/legacy/plugin_discovery/README.md +++ /dev/null @@ -1,148 +0,0 @@ -# Plugin Discovery - -The plugin discovery module defines the core plugin loading logic used by the Kibana server. It exports functions for - - -## `findPluginSpecs(settings, [config])` - -Finds [`PluginSpec`][PluginSpec] objects - -### params - - `settings`: the same settings object accepted by [`KbnServer`][KbnServer] - - `[config]`: Optional - a [`Config`][Config] service. Using this param causes `findPluginSpecs()` to modify `config`'s schema to support the configuration for each discovered [`PluginSpec`][PluginSpec]. If you can, please use the [`Config`][Config] service produced by `extendedConfig$` rather than passing in an existing service so that `findPluginSpecs()` is side-effect free. - -### return value - -`findPluginSpecs()` returns an object of Observables which produce values at different parts of the process. Since the Observables are all aware of their own dependencies you can subscribe to any combination (within the same tick) and only the necessary plugin logic will be executed. - -If you *never* subscribe to any of the Observables then plugin discovery won't actually run. - - - `pack$`: emits every [`PluginPack`][PluginPack] found - - `invalidDirectoryError$: Observable`: emits [`InvalidDirectoryError`][Errors]s caused by `settings.plugins.scanDirs` values that don't point to actual directories. `findPluginSpecs()` will not abort when this error is encountered. - - `invalidPackError$: Observable`: emits [`InvalidPackError`][Errors]s caused by children of `settings.plugins.scanDirs` or `settings.plugins.paths` values which don't meet the requirements of a [`PluginPack`][PluginPack] (probably missing a `package.json`). `findPluginSpecs()` will not abort when this error is encountered. - - `deprecation$: Observable`: emits deprecation warnings that are produces when reading each [`PluginPack`][PluginPack]'s configuration - - `extendedConfig$: Observable`: emits the [`Config`][Config] service that was passed to `findPluginSpecs()` (or created internally if none was passed) after it has been extended with the configuration from each plugin - - `spec$: Observable`: emits every *enabled* [`PluginSpec`][PluginSpec] defined by the discovered [`PluginPack`][PluginPack]s - - `disabledSpec$: Observable`: emits every *disabled* [`PluginSpec`][PluginSpec] defined by the discovered [`PluginPack`][PluginPack]s - - `invalidVersionSpec$: Observable`: emits every [`PluginSpec`][PluginSpec] who's required kibana version does not match the version exposed by `config.get('pkg.version')` - -### example - -Just get the plugin specs, only fail if there is an uncaught error of some sort: -```js -const { pack$ } = findPluginSpecs(settings); -const packs = await pack$.pipe(toArray()).toPromise() -``` - -Just log the deprecation messages: -```js -const { deprecation$ } = findPluginSpecs(settings); -for (const warning of await deprecation$.pipe(toArray()).toPromise()) { - console.log('DEPRECATION:', warning) -} -``` - -Get the packs but fail if any packs are invalid: -```js -const { pack$, invalidDirectoryError$ } = findPluginSpecs(settings); -const packs = await Rx.merge( - pack$.pipe(toArray()), - - // if we ever get an InvalidDirectoryError, throw it - // into the stream so that all streams are unsubscribed, - // the discovery process is aborted, and the promise rejects - invalidDirectoryError$.pipe( - map(error => { throw error }) - ), -).toPromise() -``` - -Handle everything -```js -const { - pack$, - invalidDirectoryError$, - invalidPackError$, - deprecation$, - extendedConfig$, - spec$, - disabledSpecs$, - invalidVersionSpec$, -} = findPluginSpecs(settings); - -Rx.merge( - pack$.pipe( - tap(pluginPack => console.log('Found plugin pack', pluginPack)) - ), - - invalidDirectoryError$.pipe( - tap(error => console.log('Invalid directory error', error)) - ), - - invalidPackError$.pipe( - tap(error => console.log('Invalid plugin pack error', error)) - ), - - deprecation$.pipe( - tap(msg => console.log('DEPRECATION:', msg)) - ), - - extendedConfig$.pipe( - tap(config => console.log('config service extended by plugins', config)) - ), - - spec$.pipe( - tap(pluginSpec => console.log('enabled plugin spec found', spec)) - ), - - disabledSpec$.pipe( - tap(pluginSpec => console.log('disabled plugin spec found', spec)) - ), - - invalidVersionSpec$.pipe( - tap(pluginSpec => console.log('plugin spec with invalid version found', spec)) - ), -) -.toPromise() -.then(() => { - console.log('plugin discovery complete') -}) -.catch((error) => { - console.log('plugin discovery failed', error) -}) - -``` - -## `reduceExportSpecs(pluginSpecs, reducers, [defaults={}])` - -Reduces every value exported by the [`PluginSpec`][PluginSpec]s to produce a single value. If an exported value is an array each item in the array will be reduced individually. If the exported value is `undefined` it will be ignored. The reducer is called with the signature: - -```js -reducer( - // the result of the previous reducer call, or `defaults` - acc: any, - // the exported value, found at `uiExports[type]` or `uiExports[type][i]` - // in the PluginSpec config. - spec: any, - // the key in `uiExports` where this export was found - type: string, - // the PluginSpec which exported this spec - pluginSpec: PluginSpec -) -``` - -## `new PluginPack(options)` class - -Only exported so that `PluginPack` instances can be created in tests and used in place of on-disk plugin fixtures. Use `findPluginSpecs()`, or the cached result of a call to `findPluginSpecs()` (like `kbnServer.pluginSpecs`) any time you might need access to `PluginPack` objects in distributed code. - -### params - - - `options.path`: absolute path to where this plugin pack was found, this is normally a direct child of `./src/legacy/core_plugins` or `./plugins` - - `options.pkg`: the parsed `package.json` for this pack, used for defaults in `PluginSpec` objects defined by this pack - - `options.provider`: the default export of the pack, a function which is called with the `PluginSpec` class which should return one or more `PluginSpec` objects. - -[PluginPack]: ./plugin_pack/plugin_pack.js "PluginPath class definition" -[PluginSpec]: ./plugin_spec/plugin_spec.js "PluginSpec class definition" -[Errors]: ./errors.js "PluginDiscover specific error types" -[KbnServer]: ../server/kbn_server.js "KbnServer class definition" -[Config]: ../server/config/config.js "KbnServer/Config class definition" diff --git a/src/legacy/plugin_discovery/__tests__/find_plugin_specs.js b/src/legacy/plugin_discovery/__tests__/find_plugin_specs.js deleted file mode 100644 index e6af23d69c549..0000000000000 --- a/src/legacy/plugin_discovery/__tests__/find_plugin_specs.js +++ /dev/null @@ -1,219 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { resolve } from 'path'; -import { toArray } from 'rxjs/operators'; - -import expect from '@kbn/expect'; -import { isEqual } from 'lodash'; -import { findPluginSpecs } from '../find_plugin_specs'; -import { PluginSpec } from '../plugin_spec'; - -const PLUGIN_FIXTURES = resolve(__dirname, 'fixtures/plugins'); -const CONFLICT_FIXTURES = resolve(__dirname, 'fixtures/conflicts'); - -describe('plugin discovery', () => { - describe('findPluginSpecs()', function () { - this.timeout(10000); - - describe('spec$', () => { - it('finds specs for specified plugin paths', async () => { - const { spec$ } = findPluginSpecs({ - plugins: { - paths: [ - resolve(PLUGIN_FIXTURES, 'foo'), - resolve(PLUGIN_FIXTURES, 'bar'), - resolve(PLUGIN_FIXTURES, 'broken'), - ], - }, - }); - - const specs = await spec$.pipe(toArray()).toPromise(); - expect(specs).to.have.length(3); - specs.forEach((spec) => { - expect(spec).to.be.a(PluginSpec); - }); - expect(specs.map((s) => s.getId()).sort()).to.eql(['bar:one', 'bar:two', 'foo']); - }); - - it('finds all specs in scanDirs', async () => { - const { spec$ } = findPluginSpecs({ - // used to ensure the dev_mode plugin is enabled - env: 'development', - - plugins: { - scanDirs: [PLUGIN_FIXTURES], - }, - }); - - const specs = await spec$.pipe(toArray()).toPromise(); - expect(specs).to.have.length(3); - specs.forEach((spec) => { - expect(spec).to.be.a(PluginSpec); - }); - expect(specs.map((s) => s.getId()).sort()).to.eql(['bar:one', 'bar:two', 'foo']); - }); - - it('does not find disabled plugins', async () => { - const { spec$ } = findPluginSpecs({ - 'bar:one': { - enabled: false, - }, - - plugins: { - paths: [ - resolve(PLUGIN_FIXTURES, 'foo'), - resolve(PLUGIN_FIXTURES, 'bar'), - resolve(PLUGIN_FIXTURES, 'broken'), - ], - }, - }); - - const specs = await spec$.pipe(toArray()).toPromise(); - expect(specs).to.have.length(2); - specs.forEach((spec) => { - expect(spec).to.be.a(PluginSpec); - }); - expect(specs.map((s) => s.getId()).sort()).to.eql(['bar:two', 'foo']); - }); - - it('dedupes duplicate packs', async () => { - const { spec$ } = findPluginSpecs({ - plugins: { - scanDirs: [PLUGIN_FIXTURES], - paths: [ - resolve(PLUGIN_FIXTURES, 'foo'), - resolve(PLUGIN_FIXTURES, 'foo'), - resolve(PLUGIN_FIXTURES, 'bar'), - resolve(PLUGIN_FIXTURES, 'bar'), - resolve(PLUGIN_FIXTURES, 'broken'), - resolve(PLUGIN_FIXTURES, 'broken'), - ], - }, - }); - - const specs = await spec$.pipe(toArray()).toPromise(); - expect(specs).to.have.length(3); - specs.forEach((spec) => { - expect(spec).to.be.a(PluginSpec); - }); - expect(specs.map((s) => s.getId()).sort()).to.eql(['bar:one', 'bar:two', 'foo']); - }); - - describe('conflicting plugin spec ids', () => { - it('fails with informative message', async () => { - const { spec$ } = findPluginSpecs({ - plugins: { - scanDirs: [], - paths: [resolve(CONFLICT_FIXTURES, 'foo')], - }, - }); - - try { - await spec$.pipe(toArray()).toPromise(); - throw new Error('expected spec$ to throw an error'); - } catch (error) { - expect(error.message).to.contain('Multiple plugins found with the id "foo"'); - expect(error.message).to.contain(CONFLICT_FIXTURES); - } - }); - }); - }); - - describe('packageJson$', () => { - const checkPackageJsons = (packageJsons) => { - expect(packageJsons).to.have.length(2); - const package1 = packageJsons.find((packageJson) => - isEqual( - { - directoryPath: resolve(PLUGIN_FIXTURES, 'foo'), - contents: { - name: 'foo', - version: 'kibana', - }, - }, - packageJson - ) - ); - expect(package1).to.be.an(Object); - const package2 = packageJsons.find((packageJson) => - isEqual( - { - directoryPath: resolve(PLUGIN_FIXTURES, 'bar'), - contents: { - name: 'foo', - version: 'kibana', - }, - }, - packageJson - ) - ); - expect(package2).to.be.an(Object); - }; - - it('finds packageJson for specified plugin paths', async () => { - const { packageJson$ } = findPluginSpecs({ - plugins: { - paths: [ - resolve(PLUGIN_FIXTURES, 'foo'), - resolve(PLUGIN_FIXTURES, 'bar'), - resolve(PLUGIN_FIXTURES, 'broken'), - ], - }, - }); - - const packageJsons = await packageJson$.pipe(toArray()).toPromise(); - checkPackageJsons(packageJsons); - }); - - it('finds all packageJsons in scanDirs', async () => { - const { packageJson$ } = findPluginSpecs({ - // used to ensure the dev_mode plugin is enabled - env: 'development', - - plugins: { - scanDirs: [PLUGIN_FIXTURES], - }, - }); - - const packageJsons = await packageJson$.pipe(toArray()).toPromise(); - checkPackageJsons(packageJsons); - }); - - it('dedupes duplicate packageJson', async () => { - const { packageJson$ } = findPluginSpecs({ - plugins: { - scanDirs: [PLUGIN_FIXTURES], - paths: [ - resolve(PLUGIN_FIXTURES, 'foo'), - resolve(PLUGIN_FIXTURES, 'foo'), - resolve(PLUGIN_FIXTURES, 'bar'), - resolve(PLUGIN_FIXTURES, 'bar'), - resolve(PLUGIN_FIXTURES, 'broken'), - resolve(PLUGIN_FIXTURES, 'broken'), - ], - }, - }); - - const packageJsons = await packageJson$.pipe(toArray()).toPromise(); - checkPackageJsons(packageJsons); - }); - }); - }); -}); diff --git a/src/legacy/plugin_discovery/__tests__/fixtures/conflicts/foo/index.js b/src/legacy/plugin_discovery/__tests__/fixtures/conflicts/foo/index.js deleted file mode 100644 index fcbe3487463b7..0000000000000 --- a/src/legacy/plugin_discovery/__tests__/fixtures/conflicts/foo/index.js +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -export default function (kibana) { - return [ - // two plugins exported without ids will both inherit - // the id of the pack and conflict - new kibana.Plugin({}), - new kibana.Plugin({}), - ]; -} diff --git a/src/legacy/plugin_discovery/__tests__/fixtures/conflicts/foo/package.json b/src/legacy/plugin_discovery/__tests__/fixtures/conflicts/foo/package.json deleted file mode 100644 index e43c2f0bc984c..0000000000000 --- a/src/legacy/plugin_discovery/__tests__/fixtures/conflicts/foo/package.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "name": "foo", - "version": "kibana" -} diff --git a/src/legacy/plugin_discovery/__tests__/fixtures/plugins/bar/index.js b/src/legacy/plugin_discovery/__tests__/fixtures/plugins/bar/index.js deleted file mode 100644 index 0eef126f2255a..0000000000000 --- a/src/legacy/plugin_discovery/__tests__/fixtures/plugins/bar/index.js +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -export default function (kibana) { - return [ - new kibana.Plugin({ - id: 'bar:one', - }), - new kibana.Plugin({ - id: 'bar:two', - }), - ]; -} diff --git a/src/legacy/plugin_discovery/__tests__/fixtures/plugins/bar/package.json b/src/legacy/plugin_discovery/__tests__/fixtures/plugins/bar/package.json deleted file mode 100644 index e43c2f0bc984c..0000000000000 --- a/src/legacy/plugin_discovery/__tests__/fixtures/plugins/bar/package.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "name": "foo", - "version": "kibana" -} diff --git a/src/legacy/plugin_discovery/__tests__/fixtures/plugins/broken/index.js b/src/legacy/plugin_discovery/__tests__/fixtures/plugins/broken/index.js deleted file mode 100644 index 59f4a2649f019..0000000000000 --- a/src/legacy/plugin_discovery/__tests__/fixtures/plugins/broken/index.js +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -export default { - foo: 'bar', -}; diff --git a/src/legacy/plugin_discovery/__tests__/fixtures/plugins/broken/package1.json b/src/legacy/plugin_discovery/__tests__/fixtures/plugins/broken/package1.json deleted file mode 100644 index 81ddb6221d515..0000000000000 --- a/src/legacy/plugin_discovery/__tests__/fixtures/plugins/broken/package1.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "name": "baz", - "version": "kibana" -} diff --git a/src/legacy/plugin_discovery/__tests__/fixtures/plugins/foo/index.js b/src/legacy/plugin_discovery/__tests__/fixtures/plugins/foo/index.js deleted file mode 100644 index e43a1dcedb372..0000000000000 --- a/src/legacy/plugin_discovery/__tests__/fixtures/plugins/foo/index.js +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -module.exports = function (kibana) { - return new kibana.Plugin({ - id: 'foo', - }); -}; diff --git a/src/legacy/plugin_discovery/__tests__/fixtures/plugins/foo/package.json b/src/legacy/plugin_discovery/__tests__/fixtures/plugins/foo/package.json deleted file mode 100644 index e43c2f0bc984c..0000000000000 --- a/src/legacy/plugin_discovery/__tests__/fixtures/plugins/foo/package.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "name": "foo", - "version": "kibana" -} diff --git a/src/legacy/plugin_discovery/errors.js b/src/legacy/plugin_discovery/errors.js deleted file mode 100644 index 02d81b32d1fd1..0000000000000 --- a/src/legacy/plugin_discovery/errors.js +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -const errorCodeProperty = Symbol('pluginDiscovery/errorCode'); - -/** - * Thrown when reading a plugin directory fails, wraps failure - * @type {String} - */ -const ERROR_INVALID_DIRECTORY = 'ERROR_INVALID_DIRECTORY'; -export function createInvalidDirectoryError(sourceError, path) { - sourceError[errorCodeProperty] = ERROR_INVALID_DIRECTORY; - sourceError.path = path; - return sourceError; -} -export function isInvalidDirectoryError(error) { - return error && error[errorCodeProperty] === ERROR_INVALID_DIRECTORY; -} - -/** - * Thrown when trying to create a PluginPack for a path that - * is not a valid plugin definition - * @type {String} - */ -const ERROR_INVALID_PACK = 'ERROR_INVALID_PACK'; -export function createInvalidPackError(path, reason) { - const error = new Error(`PluginPack${path ? ` at "${path}"` : ''} ${reason}`); - error[errorCodeProperty] = ERROR_INVALID_PACK; - error.path = path; - return error; -} -export function isInvalidPackError(error) { - return error && error[errorCodeProperty] === ERROR_INVALID_PACK; -} - -/** - * Thrown when trying to load a PluginSpec that is invalid for some reason - * @type {String} - */ -const ERROR_INVALID_PLUGIN = 'ERROR_INVALID_PLUGIN'; -export function createInvalidPluginError(spec, reason) { - const error = new Error( - `Plugin from ${spec.getId()} at ${spec.getPack().getPath()} is invalid because ${reason}` - ); - error[errorCodeProperty] = ERROR_INVALID_PLUGIN; - error.spec = spec; - return error; -} -export function isInvalidPluginError(error) { - return error && error[errorCodeProperty] === ERROR_INVALID_PLUGIN; -} - -/** - * Thrown when trying to load a PluginSpec whose version is incompatible - * @type {String} - */ -const ERROR_INCOMPATIBLE_PLUGIN_VERSION = 'ERROR_INCOMPATIBLE_PLUGIN_VERSION'; -export function createIncompatiblePluginVersionError(spec) { - const error = new Error( - `Plugin ${spec.getId()} is only compatible with Kibana version ${spec.getExpectedKibanaVersion()}` - ); - error[errorCodeProperty] = ERROR_INCOMPATIBLE_PLUGIN_VERSION; - error.spec = spec; - return error; -} -export function isIncompatiblePluginVersionError(error) { - return error && error[errorCodeProperty] === ERROR_INCOMPATIBLE_PLUGIN_VERSION; -} diff --git a/src/legacy/plugin_discovery/find_plugin_specs.js b/src/legacy/plugin_discovery/find_plugin_specs.js deleted file mode 100644 index b97476bb456a5..0000000000000 --- a/src/legacy/plugin_discovery/find_plugin_specs.js +++ /dev/null @@ -1,234 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import * as Rx from 'rxjs'; -import { - distinct, - toArray, - mergeMap, - share, - shareReplay, - filter, - last, - map, - tap, -} from 'rxjs/operators'; -import { realpathSync } from 'fs'; - -import { Config } from '../server/config'; - -import { extendConfigService, disableConfigExtension } from './plugin_config'; - -import { - createPack$, - createPackageJsonAtPath$, - createPackageJsonsInDirectory$, -} from './plugin_pack'; - -import { isInvalidDirectoryError, isInvalidPackError } from './errors'; - -export function defaultConfig(settings) { - return Config.withDefaultSchema(settings); -} - -function bufferAllResults(observable) { - return observable.pipe( - // buffer all results into a single array - toArray(), - // merge the array back into the stream when complete - mergeMap((array) => array) - ); -} - -/** - * Determine a distinct value for each result from find$ - * so they can be deduplicated - * @param {{error?,pack?}} result - * @return {Any} - */ -function getDistinctKeyForFindResult(result) { - // errors are distinct by their message - if (result.error) { - return result.error.message; - } - - // packs are distinct by their absolute and real path - if (result.packageJson) { - return realpathSync(result.packageJson.directoryPath); - } - - // non error/pack results shouldn't exist, but if they do they are all unique - return result; -} - -function groupSpecsById(specs) { - const specsById = new Map(); - for (const spec of specs) { - const id = spec.getId(); - if (specsById.has(id)) { - specsById.get(id).push(spec); - } else { - specsById.set(id, [spec]); - } - } - return specsById; -} - -/** - * Creates a collection of observables for discovering pluginSpecs - * using Kibana's defaults, settings, and config service - * - * @param {Object} settings - * @param {ConfigService} [configToMutate] when supplied **it is mutated** to - * include the config from discovered plugin specs - * @return {Object} - */ -export function findPluginSpecs(settings, configToMutate) { - const config$ = Rx.defer(async () => { - if (configToMutate) { - return configToMutate; - } - - return defaultConfig(settings); - }).pipe(shareReplay()); - - // find plugin packs in configured paths/dirs - const packageJson$ = config$.pipe( - mergeMap((config) => - Rx.merge( - ...config.get('plugins.paths').map(createPackageJsonAtPath$), - ...config.get('plugins.scanDirs').map(createPackageJsonsInDirectory$) - ) - ), - distinct(getDistinctKeyForFindResult), - share() - ); - - const pack$ = createPack$(packageJson$).pipe(share()); - - const extendConfig$ = config$.pipe( - mergeMap((config) => - pack$.pipe( - // get the specs for each found plugin pack - mergeMap(({ pack }) => (pack ? pack.getPluginSpecs() : [])), - // make sure that none of the plugin specs have conflicting ids, fail - // early if conflicts detected or merge the specs back into the stream - toArray(), - mergeMap((allSpecs) => { - for (const [id, specs] of groupSpecsById(allSpecs)) { - if (specs.length > 1) { - throw new Error( - `Multiple plugins found with the id "${id}":\n${specs - .map((spec) => ` - ${id} at ${spec.getPath()}`) - .join('\n')}` - ); - } - } - - return allSpecs; - }), - mergeMap(async (spec) => { - // extend the config service with this plugin spec and - // collect its deprecations messages if some of its - // settings are outdated - const deprecations = []; - await extendConfigService(spec, config, settings, (message) => { - deprecations.push({ spec, message }); - }); - - return { - spec, - deprecations, - }; - }), - // extend the config with all plugins before determining enabled status - bufferAllResults, - map(({ spec, deprecations }) => { - const isRightVersion = spec.isVersionCompatible(config.get('pkg.version')); - const enabled = isRightVersion && spec.isEnabled(config); - return { - config, - spec, - deprecations, - enabledSpecs: enabled ? [spec] : [], - disabledSpecs: enabled ? [] : [spec], - invalidVersionSpecs: isRightVersion ? [] : [spec], - }; - }), - // determine which plugins are disabled before actually removing things from the config - bufferAllResults, - tap((result) => { - for (const spec of result.disabledSpecs) { - disableConfigExtension(spec, config); - } - }) - ) - ), - share() - ); - - return { - // package JSONs found when searching configure paths - packageJson$: packageJson$.pipe( - mergeMap((result) => (result.packageJson ? [result.packageJson] : [])) - ), - - // plugin packs found when searching configured paths - pack$: pack$.pipe(mergeMap((result) => (result.pack ? [result.pack] : []))), - - // errors caused by invalid directories of plugin directories - invalidDirectoryError$: pack$.pipe( - mergeMap((result) => (isInvalidDirectoryError(result.error) ? [result.error] : [])) - ), - - // errors caused by directories that we expected to be plugin but were invalid - invalidPackError$: pack$.pipe( - mergeMap((result) => (isInvalidPackError(result.error) ? [result.error] : [])) - ), - - otherError$: pack$.pipe( - mergeMap((result) => (isUnhandledError(result.error) ? [result.error] : [])) - ), - - // { spec, message } objects produced when transforming deprecated - // settings for a plugin spec - deprecation$: extendConfig$.pipe(mergeMap((result) => result.deprecations)), - - // the config service we extended with all of the plugin specs, - // only emitted once it is fully extended by all - extendedConfig$: extendConfig$.pipe( - mergeMap((result) => result.config), - filter(Boolean), - last() - ), - - // all enabled PluginSpec objects - spec$: extendConfig$.pipe(mergeMap((result) => result.enabledSpecs)), - - // all disabled PluginSpec objects - disabledSpec$: extendConfig$.pipe(mergeMap((result) => result.disabledSpecs)), - - // all PluginSpec objects that were disabled because their version was incompatible - invalidVersionSpec$: extendConfig$.pipe(mergeMap((result) => result.invalidVersionSpecs)), - }; -} - -function isUnhandledError(error) { - return error != null && !isInvalidDirectoryError(error) && !isInvalidPackError(error); -} diff --git a/src/legacy/plugin_discovery/index.js b/src/legacy/plugin_discovery/index.js deleted file mode 100644 index b60806f6cbc23..0000000000000 --- a/src/legacy/plugin_discovery/index.js +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -export { findPluginSpecs } from './find_plugin_specs'; -export { reduceExportSpecs } from './plugin_exports'; -export { PluginPack } from './plugin_pack'; diff --git a/src/legacy/plugin_discovery/plugin_config/__tests__/extend_config_service.js b/src/legacy/plugin_discovery/plugin_config/__tests__/extend_config_service.js deleted file mode 100644 index 40f84f6f54b3b..0000000000000 --- a/src/legacy/plugin_discovery/plugin_config/__tests__/extend_config_service.js +++ /dev/null @@ -1,162 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import sinon from 'sinon'; -import expect from '@kbn/expect'; - -import { Config } from '../../../server/config'; -import { PluginPack } from '../../plugin_pack'; -import { extendConfigService, disableConfigExtension } from '../extend_config_service'; -import * as SchemaNS from '../schema'; -import * as SettingsNS from '../settings'; - -describe('plugin discovery/extend config service', () => { - const sandbox = sinon.createSandbox(); - afterEach(() => sandbox.restore()); - - const pluginSpec = new PluginPack({ - path: '/dev/null', - pkg: { - name: 'test', - version: 'kibana', - }, - provider: ({ Plugin }) => - new Plugin({ - configPrefix: 'foo.bar.baz', - - config: (Joi) => - Joi.object({ - enabled: Joi.boolean().default(true), - test: Joi.string().default('bonk'), - }).default(), - }), - }) - .getPluginSpecs() - .pop(); - - describe('extendConfigService()', () => { - it('calls getSettings, getSchema, and Config.extendSchema() correctly', async () => { - const rootSettings = { - foo: { - bar: { - enabled: false, - }, - }, - }; - const schema = { - validate: () => {}, - }; - const configPrefix = 'foo.bar'; - const config = { - extendSchema: sandbox.stub(), - }; - const pluginSpec = { - getConfigPrefix: sandbox.stub().returns(configPrefix), - }; - - const getSettings = sandbox.stub(SettingsNS, 'getSettings').returns(rootSettings.foo.bar); - - const getSchema = sandbox.stub(SchemaNS, 'getSchema').returns(schema); - - await extendConfigService(pluginSpec, config, rootSettings); - - sinon.assert.calledOnce(getSettings); - sinon.assert.calledWithExactly(getSettings, pluginSpec, rootSettings); - - sinon.assert.calledOnce(getSchema); - sinon.assert.calledWithExactly(getSchema, pluginSpec); - - sinon.assert.calledOnce(config.extendSchema); - sinon.assert.calledWithExactly( - config.extendSchema, - schema, - rootSettings.foo.bar, - configPrefix - ); - }); - - it('adds the schema for a plugin spec to its config prefix', async () => { - const config = Config.withDefaultSchema(); - expect(config.has('foo.bar.baz')).to.be(false); - await extendConfigService(pluginSpec, config); - expect(config.has('foo.bar.baz')).to.be(true); - }); - - it('initializes it with the default settings', async () => { - const config = Config.withDefaultSchema(); - await extendConfigService(pluginSpec, config); - expect(config.get('foo.bar.baz.enabled')).to.be(true); - expect(config.get('foo.bar.baz.test')).to.be('bonk'); - }); - - it('initializes it with values from root settings if defined', async () => { - const config = Config.withDefaultSchema(); - await extendConfigService(pluginSpec, config, { - foo: { - bar: { - baz: { - test: 'hello world', - }, - }, - }, - }); - - expect(config.get('foo.bar.baz.test')).to.be('hello world'); - }); - - it('throws if root settings are invalid', async () => { - const config = Config.withDefaultSchema(); - try { - await extendConfigService(pluginSpec, config, { - foo: { - bar: { - baz: { - test: { - 'not a string': true, - }, - }, - }, - }, - }); - throw new Error('Expected extendConfigService() to throw because of bad settings'); - } catch (error) { - expect(error.message).to.contain('"test" must be a string'); - } - }); - }); - - describe('disableConfigExtension()', () => { - it('removes added config', async () => { - const config = Config.withDefaultSchema(); - await extendConfigService(pluginSpec, config); - expect(config.has('foo.bar.baz.test')).to.be(true); - await disableConfigExtension(pluginSpec, config); - expect(config.has('foo.bar.baz.test')).to.be(false); - }); - - it('leaves {configPrefix}.enabled config', async () => { - const config = Config.withDefaultSchema(); - expect(config.has('foo.bar.baz.enabled')).to.be(false); - await extendConfigService(pluginSpec, config); - expect(config.get('foo.bar.baz.enabled')).to.be(true); - await disableConfigExtension(pluginSpec, config); - expect(config.get('foo.bar.baz.enabled')).to.be(false); - }); - }); -}); diff --git a/src/legacy/plugin_discovery/plugin_config/__tests__/schema.js b/src/legacy/plugin_discovery/plugin_config/__tests__/schema.js deleted file mode 100644 index 78adb1e680e20..0000000000000 --- a/src/legacy/plugin_discovery/plugin_config/__tests__/schema.js +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import expect from '@kbn/expect'; - -import { PluginPack } from '../../plugin_pack'; -import { getSchema, getStubSchema } from '../schema'; - -describe('plugin discovery/schema', () => { - function createPluginSpec(configProvider) { - return new PluginPack({ - path: '/dev/null', - pkg: { - name: 'test', - version: 'kibana', - }, - provider: ({ Plugin }) => - new Plugin({ - configPrefix: 'foo.bar.baz', - config: configProvider, - }), - }) - .getPluginSpecs() - .pop(); - } - - describe('getSchema()', () => { - it('calls the config provider and returns its return value', async () => { - const pluginSpec = createPluginSpec(() => 'foo'); - expect(await getSchema(pluginSpec)).to.be('foo'); - }); - - it('supports config provider that returns a promise', async () => { - const pluginSpec = createPluginSpec(() => Promise.resolve('foo')); - expect(await getSchema(pluginSpec)).to.be('foo'); - }); - - it('uses default schema when no config provider', async () => { - const schema = await getSchema(createPluginSpec()); - expect(schema).to.be.an('object'); - expect(schema).to.have.property('validate').a('function'); - expect(schema.validate({}).value).to.eql({ - enabled: true, - }); - }); - - it('uses default schema when config returns falsy value', async () => { - const schema = await getSchema(createPluginSpec(() => null)); - expect(schema).to.be.an('object'); - expect(schema).to.have.property('validate').a('function'); - expect(schema.validate({}).value).to.eql({ - enabled: true, - }); - }); - - it('uses default schema when config promise resolves to falsy value', async () => { - const schema = await getSchema(createPluginSpec(() => Promise.resolve(null))); - expect(schema).to.be.an('object'); - expect(schema).to.have.property('validate').a('function'); - expect(schema.validate({}).value).to.eql({ - enabled: true, - }); - }); - }); - - describe('getStubSchema()', () => { - it('returns schema with enabled: false', async () => { - const schema = await getStubSchema(); - expect(schema).to.be.an('object'); - expect(schema).to.have.property('validate').a('function'); - expect(schema.validate({}).value).to.eql({ - enabled: false, - }); - }); - }); -}); diff --git a/src/legacy/plugin_discovery/plugin_config/__tests__/settings.js b/src/legacy/plugin_discovery/plugin_config/__tests__/settings.js deleted file mode 100644 index 750c5ee6c6f50..0000000000000 --- a/src/legacy/plugin_discovery/plugin_config/__tests__/settings.js +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import expect from '@kbn/expect'; - -import { PluginPack } from '../../plugin_pack'; -import { getSettings } from '../settings'; - -describe('plugin_discovery/settings', () => { - const pluginSpec = new PluginPack({ - path: '/dev/null', - pkg: { - name: 'test', - version: 'kibana', - }, - provider: ({ Plugin }) => - new Plugin({ - configPrefix: 'a.b.c', - }), - }) - .getPluginSpecs() - .pop(); - - describe('getSettings()', () => { - it('reads settings from config prefix', async () => { - const rootSettings = { - a: { - b: { - c: { - enabled: false, - }, - }, - }, - }; - - expect(await getSettings(pluginSpec, rootSettings)).to.eql({ - enabled: false, - }); - }); - - it('allows rootSettings to be undefined', async () => { - expect(await getSettings(pluginSpec)).to.eql(undefined); - }); - }); -}); diff --git a/src/legacy/plugin_discovery/plugin_config/extend_config_service.js b/src/legacy/plugin_discovery/plugin_config/extend_config_service.js deleted file mode 100644 index a6d5d4ae5f990..0000000000000 --- a/src/legacy/plugin_discovery/plugin_config/extend_config_service.js +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { getSettings } from './settings'; -import { getSchema, getStubSchema } from './schema'; - -/** - * Extend a config service with the schema and settings for a - * plugin spec and optionally call logDeprecation with warning - * messages about deprecated settings that are used - * @param {PluginSpec} spec - * @param {Server.Config} config - * @param {Object} rootSettings - * @param {Function} [logDeprecation] - * @return {Promise} - */ -export async function extendConfigService(spec, config, rootSettings) { - const settings = await getSettings(spec, rootSettings); - const schema = await getSchema(spec); - config.extendSchema(schema, settings, spec.getConfigPrefix()); -} - -/** - * Disable the schema and settings applied to a config service for - * a plugin spec - * @param {PluginSpec} spec - * @param {Server.Config} config - * @return {undefined} - */ -export function disableConfigExtension(spec, config) { - const prefix = spec.getConfigPrefix(); - config.removeSchema(prefix); - config.extendSchema(getStubSchema(), { enabled: false }, prefix); -} diff --git a/src/legacy/plugin_discovery/plugin_config/index.js b/src/legacy/plugin_discovery/plugin_config/index.js deleted file mode 100644 index a27463bc9c7f5..0000000000000 --- a/src/legacy/plugin_discovery/plugin_config/index.js +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -export { extendConfigService, disableConfigExtension } from './extend_config_service'; diff --git a/src/legacy/plugin_discovery/plugin_config/schema.js b/src/legacy/plugin_discovery/plugin_config/schema.js deleted file mode 100644 index 14d10aa5568da..0000000000000 --- a/src/legacy/plugin_discovery/plugin_config/schema.js +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import Joi from 'joi'; - -const STUB_CONFIG_SCHEMA = Joi.object() - .keys({ - enabled: Joi.valid(false).default(false), - }) - .default(); - -const DEFAULT_CONFIG_SCHEMA = Joi.object() - .keys({ - enabled: Joi.boolean().default(true), - }) - .default(); - -/** - * Get the config schema for a plugin spec - * @param {PluginSpec} spec - * @return {Promise} - */ -export async function getSchema(spec) { - const provider = spec.getConfigSchemaProvider(); - return (provider && (await provider(Joi))) || DEFAULT_CONFIG_SCHEMA; -} - -export function getStubSchema() { - return STUB_CONFIG_SCHEMA; -} diff --git a/src/legacy/plugin_discovery/plugin_config/settings.js b/src/legacy/plugin_discovery/plugin_config/settings.js deleted file mode 100644 index e6a4741d76eca..0000000000000 --- a/src/legacy/plugin_discovery/plugin_config/settings.js +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { get } from 'lodash'; - -/** - * Get the settings for a pluginSpec from the raw root settings while - * optionally calling logDeprecation() with warnings about deprecated - * settings that were used - * @param {PluginSpec} spec - * @param {Object} rootSettings - * @return {Promise} - */ -export async function getSettings(spec, rootSettings) { - const prefix = spec.getConfigPrefix(); - const rawSettings = get(rootSettings, prefix); - return rawSettings; -} diff --git a/src/legacy/plugin_discovery/plugin_exports/__tests__/reduce_export_specs.js b/src/legacy/plugin_discovery/plugin_exports/__tests__/reduce_export_specs.js deleted file mode 100644 index 3beaacc1a8293..0000000000000 --- a/src/legacy/plugin_discovery/plugin_exports/__tests__/reduce_export_specs.js +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import expect from '@kbn/expect'; - -import { PluginPack } from '../../plugin_pack'; -import { reduceExportSpecs } from '../reduce_export_specs'; - -const PLUGIN = new PluginPack({ - path: __dirname, - pkg: { - name: 'foo', - version: 'kibana', - }, - provider: ({ Plugin }) => - new Plugin({ - uiExports: { - concatNames: { - name: 'export1', - }, - - concat: ['export2', 'export3'], - }, - }), -}); - -const REDUCERS = { - concatNames(acc, spec, type, pluginSpec) { - return { - names: [].concat(acc.names || [], `${pluginSpec.getId()}:${spec.name}`), - }; - }, - concat(acc, spec, type, pluginSpec) { - return { - names: [].concat(acc.names || [], `${pluginSpec.getId()}:${spec}`), - }; - }, -}; - -const PLUGIN_SPECS = PLUGIN.getPluginSpecs(); - -describe('reduceExportSpecs', () => { - it('combines ui exports from a list of plugin definitions', () => { - const exports = reduceExportSpecs(PLUGIN_SPECS, REDUCERS); - expect(exports).to.eql({ - names: ['foo:export1', 'foo:export2', 'foo:export3'], - }); - }); - - it('starts with the defaults', () => { - const exports = reduceExportSpecs(PLUGIN_SPECS, REDUCERS, { - names: ['default'], - }); - - expect(exports).to.eql({ - names: ['default', 'foo:export1', 'foo:export2', 'foo:export3'], - }); - }); -}); diff --git a/src/legacy/plugin_discovery/plugin_exports/index.js b/src/legacy/plugin_discovery/plugin_exports/index.js deleted file mode 100644 index 0e3511ea85dd4..0000000000000 --- a/src/legacy/plugin_discovery/plugin_exports/index.js +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -export { reduceExportSpecs } from './reduce_export_specs'; diff --git a/src/legacy/plugin_discovery/plugin_exports/reduce_export_specs.js b/src/legacy/plugin_discovery/plugin_exports/reduce_export_specs.js deleted file mode 100644 index a3adc3091085d..0000000000000 --- a/src/legacy/plugin_discovery/plugin_exports/reduce_export_specs.js +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -/** - * Combine the exportSpecs from a list of pluginSpecs - * by calling the reducers for each export type - * @param {Array} pluginSpecs - * @param {Object} reducers - * @param {Object} [defaults={}] - * @return {Object} - */ -export function reduceExportSpecs(pluginSpecs, reducers, defaults = {}) { - return pluginSpecs.reduce((acc, pluginSpec) => { - const specsByType = pluginSpec.getExportSpecs() || {}; - const types = Object.keys(specsByType); - - return types.reduce((acc, type) => { - const reducer = reducers[type] || reducers.unknown; - - if (!reducer) { - throw new Error(`Unknown export type ${type}`); - } - - // convert specs to an array if not already one or - // ignore the spec if it is undefined - const specs = [].concat(specsByType[type] === undefined ? [] : specsByType[type]); - - return specs.reduce((acc, spec) => reducer(acc, spec, type, pluginSpec), acc); - }, acc); - }, defaults); -} diff --git a/src/legacy/plugin_discovery/plugin_pack/__tests__/create_pack.js b/src/legacy/plugin_discovery/plugin_pack/__tests__/create_pack.js deleted file mode 100644 index b17bd69479ffa..0000000000000 --- a/src/legacy/plugin_discovery/plugin_pack/__tests__/create_pack.js +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { resolve } from 'path'; -import * as Rx from 'rxjs'; -import { toArray } from 'rxjs/operators'; -import expect from '@kbn/expect'; - -import { createPack$ } from '../create_pack'; -import { PluginPack } from '../plugin_pack'; - -import { PLUGINS_DIR, assertInvalidPackError } from './utils'; - -describe('plugin discovery/create pack', () => { - it('creates PluginPack', async () => { - const packageJson$ = Rx.from([ - { - packageJson: { - directoryPath: resolve(PLUGINS_DIR, 'prebuilt'), - contents: { - name: 'prebuilt', - }, - }, - }, - ]); - const results = await createPack$(packageJson$).pipe(toArray()).toPromise(); - expect(results).to.have.length(1); - expect(results[0]).to.only.have.keys(['pack']); - const { pack } = results[0]; - expect(pack).to.be.a(PluginPack); - }); - - describe('errors thrown', () => { - async function checkError(path, check) { - const packageJson$ = Rx.from([ - { - packageJson: { - directoryPath: path, - }, - }, - ]); - - const results = await createPack$(packageJson$).pipe(toArray()).toPromise(); - expect(results).to.have.length(1); - expect(results[0]).to.only.have.keys(['error']); - const { error } = results[0]; - await check(error); - } - it('default export is an object', () => - checkError(resolve(PLUGINS_DIR, 'exports_object'), (error) => { - assertInvalidPackError(error); - expect(error.message).to.contain('must export a function'); - })); - it('default export is an number', () => - checkError(resolve(PLUGINS_DIR, 'exports_number'), (error) => { - assertInvalidPackError(error); - expect(error.message).to.contain('must export a function'); - })); - it('default export is an string', () => - checkError(resolve(PLUGINS_DIR, 'exports_string'), (error) => { - assertInvalidPackError(error); - expect(error.message).to.contain('must export a function'); - })); - it('directory with code that fails when required', () => - checkError(resolve(PLUGINS_DIR, 'broken_code'), (error) => { - expect(error.message).to.contain("Cannot find module 'does-not-exist'"); - })); - }); -}); diff --git a/src/legacy/plugin_discovery/plugin_pack/__tests__/fixtures/plugins/broken/package.json b/src/legacy/plugin_discovery/plugin_pack/__tests__/fixtures/plugins/broken/package.json deleted file mode 100644 index f830e8b60c02d..0000000000000 --- a/src/legacy/plugin_discovery/plugin_pack/__tests__/fixtures/plugins/broken/package.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "name": -} diff --git a/src/legacy/plugin_discovery/plugin_pack/__tests__/fixtures/plugins/broken_code/index.js b/src/legacy/plugin_discovery/plugin_pack/__tests__/fixtures/plugins/broken_code/index.js deleted file mode 100644 index bdb26504d6b6e..0000000000000 --- a/src/legacy/plugin_discovery/plugin_pack/__tests__/fixtures/plugins/broken_code/index.js +++ /dev/null @@ -1,7 +0,0 @@ -const brokenRequire = require('does-not-exist'); // eslint-disable-line - -module.exports = function (kibana) { - return new kibana.Plugin({ - id: 'foo', - }); -}; diff --git a/src/legacy/plugin_discovery/plugin_pack/__tests__/fixtures/plugins/broken_code/package.json b/src/legacy/plugin_discovery/plugin_pack/__tests__/fixtures/plugins/broken_code/package.json deleted file mode 100644 index e43c2f0bc984c..0000000000000 --- a/src/legacy/plugin_discovery/plugin_pack/__tests__/fixtures/plugins/broken_code/package.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "name": "foo", - "version": "kibana" -} diff --git a/src/legacy/plugin_discovery/plugin_pack/__tests__/fixtures/plugins/exports_number/index.js b/src/legacy/plugin_discovery/plugin_pack/__tests__/fixtures/plugins/exports_number/index.js deleted file mode 100644 index f24fc54e38d9a..0000000000000 --- a/src/legacy/plugin_discovery/plugin_pack/__tests__/fixtures/plugins/exports_number/index.js +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -export default 1; diff --git a/src/legacy/plugin_discovery/plugin_pack/__tests__/fixtures/plugins/exports_number/package.json b/src/legacy/plugin_discovery/plugin_pack/__tests__/fixtures/plugins/exports_number/package.json deleted file mode 100644 index e43c2f0bc984c..0000000000000 --- a/src/legacy/plugin_discovery/plugin_pack/__tests__/fixtures/plugins/exports_number/package.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "name": "foo", - "version": "kibana" -} diff --git a/src/legacy/plugin_discovery/plugin_pack/__tests__/fixtures/plugins/exports_object/index.js b/src/legacy/plugin_discovery/plugin_pack/__tests__/fixtures/plugins/exports_object/index.js deleted file mode 100644 index 59f4a2649f019..0000000000000 --- a/src/legacy/plugin_discovery/plugin_pack/__tests__/fixtures/plugins/exports_object/index.js +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -export default { - foo: 'bar', -}; diff --git a/src/legacy/plugin_discovery/plugin_pack/__tests__/fixtures/plugins/exports_object/package.json b/src/legacy/plugin_discovery/plugin_pack/__tests__/fixtures/plugins/exports_object/package.json deleted file mode 100644 index e43c2f0bc984c..0000000000000 --- a/src/legacy/plugin_discovery/plugin_pack/__tests__/fixtures/plugins/exports_object/package.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "name": "foo", - "version": "kibana" -} diff --git a/src/legacy/plugin_discovery/plugin_pack/__tests__/fixtures/plugins/exports_string/index.js b/src/legacy/plugin_discovery/plugin_pack/__tests__/fixtures/plugins/exports_string/index.js deleted file mode 100644 index 8900db15321ae..0000000000000 --- a/src/legacy/plugin_discovery/plugin_pack/__tests__/fixtures/plugins/exports_string/index.js +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -export default 'foo'; diff --git a/src/legacy/plugin_discovery/plugin_pack/__tests__/fixtures/plugins/exports_string/package.json b/src/legacy/plugin_discovery/plugin_pack/__tests__/fixtures/plugins/exports_string/package.json deleted file mode 100644 index e43c2f0bc984c..0000000000000 --- a/src/legacy/plugin_discovery/plugin_pack/__tests__/fixtures/plugins/exports_string/package.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "name": "foo", - "version": "kibana" -} diff --git a/src/legacy/plugin_discovery/plugin_pack/__tests__/fixtures/plugins/foo/index.js b/src/legacy/plugin_discovery/plugin_pack/__tests__/fixtures/plugins/foo/index.js deleted file mode 100644 index e43a1dcedb372..0000000000000 --- a/src/legacy/plugin_discovery/plugin_pack/__tests__/fixtures/plugins/foo/index.js +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -module.exports = function (kibana) { - return new kibana.Plugin({ - id: 'foo', - }); -}; diff --git a/src/legacy/plugin_discovery/plugin_pack/__tests__/fixtures/plugins/foo/package.json b/src/legacy/plugin_discovery/plugin_pack/__tests__/fixtures/plugins/foo/package.json deleted file mode 100644 index e43c2f0bc984c..0000000000000 --- a/src/legacy/plugin_discovery/plugin_pack/__tests__/fixtures/plugins/foo/package.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "name": "foo", - "version": "kibana" -} diff --git a/src/legacy/plugin_discovery/plugin_pack/__tests__/fixtures/plugins/index.js b/src/legacy/plugin_discovery/plugin_pack/__tests__/fixtures/plugins/index.js deleted file mode 100644 index edb1dd15673da..0000000000000 --- a/src/legacy/plugin_discovery/plugin_pack/__tests__/fixtures/plugins/index.js +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -console.log('hello world'); diff --git a/src/legacy/plugin_discovery/plugin_pack/__tests__/fixtures/plugins/lib/index.js b/src/legacy/plugin_discovery/plugin_pack/__tests__/fixtures/plugins/lib/index.js deleted file mode 100644 index 050ffdfbde9ea..0000000000000 --- a/src/legacy/plugin_discovery/plugin_pack/__tests__/fixtures/plugins/lib/index.js +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -export { myLib } from './my_lib'; diff --git a/src/legacy/plugin_discovery/plugin_pack/__tests__/fixtures/plugins/lib/my_lib.js b/src/legacy/plugin_discovery/plugin_pack/__tests__/fixtures/plugins/lib/my_lib.js deleted file mode 100644 index 94e511632d9a6..0000000000000 --- a/src/legacy/plugin_discovery/plugin_pack/__tests__/fixtures/plugins/lib/my_lib.js +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -export function myLib() { - console.log('lib'); -} diff --git a/src/legacy/plugin_discovery/plugin_pack/__tests__/fixtures/plugins/prebuilt/index.js b/src/legacy/plugin_discovery/plugin_pack/__tests__/fixtures/plugins/prebuilt/index.js deleted file mode 100644 index 89744b2dd3fd9..0000000000000 --- a/src/legacy/plugin_discovery/plugin_pack/__tests__/fixtures/plugins/prebuilt/index.js +++ /dev/null @@ -1,14 +0,0 @@ -/* eslint-disable */ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -exports.default = function (_ref) { - var Plugin = _ref.Plugin; - - return new Plugin({ - id: 'foo' - }); -}; diff --git a/src/legacy/plugin_discovery/plugin_pack/__tests__/fixtures/plugins/prebuilt/package.json b/src/legacy/plugin_discovery/plugin_pack/__tests__/fixtures/plugins/prebuilt/package.json deleted file mode 100644 index b1b74e0e76b12..0000000000000 --- a/src/legacy/plugin_discovery/plugin_pack/__tests__/fixtures/plugins/prebuilt/package.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "name": "prebuilt" -} diff --git a/src/legacy/plugin_discovery/plugin_pack/__tests__/package_json_at_path.js b/src/legacy/plugin_discovery/plugin_pack/__tests__/package_json_at_path.js deleted file mode 100644 index fa1033180954e..0000000000000 --- a/src/legacy/plugin_discovery/plugin_pack/__tests__/package_json_at_path.js +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { resolve } from 'path'; -import { toArray } from 'rxjs/operators'; - -import expect from '@kbn/expect'; - -import { createPackageJsonAtPath$ } from '../package_json_at_path'; -import { PLUGINS_DIR, assertInvalidPackError, assertInvalidDirectoryError } from './utils'; - -describe('plugin discovery/plugin_pack', () => { - describe('createPackageJsonAtPath$()', () => { - it('returns an observable', () => { - expect(createPackageJsonAtPath$()).to.have.property('subscribe').a('function'); - }); - it('gets the default provider from prebuilt babel modules', async () => { - const results = await createPackageJsonAtPath$(resolve(PLUGINS_DIR, 'prebuilt')) - .pipe(toArray()) - .toPromise(); - expect(results).to.have.length(1); - expect(results[0]).to.only.have.keys(['packageJson']); - expect(results[0].packageJson).to.be.an(Object); - expect(results[0].packageJson.directoryPath).to.be(resolve(PLUGINS_DIR, 'prebuilt')); - expect(results[0].packageJson.contents).to.eql({ name: 'prebuilt' }); - }); - describe('errors emitted as { error } results', () => { - async function checkError(path, check) { - const results = await createPackageJsonAtPath$(path).pipe(toArray()).toPromise(); - expect(results).to.have.length(1); - expect(results[0]).to.only.have.keys(['error']); - const { error } = results[0]; - await check(error); - } - it('undefined path', () => - checkError(undefined, (error) => { - assertInvalidDirectoryError(error); - expect(error.message).to.contain('path must be a string'); - })); - it('relative path', () => - checkError('plugins/foo', (error) => { - assertInvalidDirectoryError(error); - expect(error.message).to.contain('path must be absolute'); - })); - it('./relative path', () => - checkError('./plugins/foo', (error) => { - assertInvalidDirectoryError(error); - expect(error.message).to.contain('path must be absolute'); - })); - it('non-existent path', () => - checkError(resolve(PLUGINS_DIR, 'baz'), (error) => { - assertInvalidPackError(error); - expect(error.message).to.contain('must be a directory'); - })); - it('path to a file', () => - checkError(resolve(PLUGINS_DIR, 'index.js'), (error) => { - assertInvalidPackError(error); - expect(error.message).to.contain('must be a directory'); - })); - it('directory without a package.json', () => - checkError(resolve(PLUGINS_DIR, 'lib'), (error) => { - assertInvalidPackError(error); - expect(error.message).to.contain('must have a package.json file'); - })); - it('directory with an invalid package.json', () => - checkError(resolve(PLUGINS_DIR, 'broken'), (error) => { - assertInvalidPackError(error); - expect(error.message).to.contain('must have a valid package.json file'); - })); - }); - }); -}); diff --git a/src/legacy/plugin_discovery/plugin_pack/__tests__/package_jsons_in_directory.js b/src/legacy/plugin_discovery/plugin_pack/__tests__/package_jsons_in_directory.js deleted file mode 100644 index 37cb4cc064da7..0000000000000 --- a/src/legacy/plugin_discovery/plugin_pack/__tests__/package_jsons_in_directory.js +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { resolve } from 'path'; - -import { toArray } from 'rxjs/operators'; -import expect from '@kbn/expect'; - -import { createPackageJsonsInDirectory$ } from '../package_jsons_in_directory'; - -import { PLUGINS_DIR, assertInvalidDirectoryError } from './utils'; - -describe('plugin discovery/packs in directory', () => { - describe('createPackageJsonsInDirectory$()', () => { - describe('errors emitted as { error } results', () => { - async function checkError(path, check) { - const results = await createPackageJsonsInDirectory$(path).pipe(toArray()).toPromise(); - expect(results).to.have.length(1); - expect(results[0]).to.only.have.keys('error'); - const { error } = results[0]; - await check(error); - } - - it('undefined path', () => - checkError(undefined, (error) => { - assertInvalidDirectoryError(error); - expect(error.message).to.contain('path must be a string'); - })); - it('relative path', () => - checkError('my/plugins', (error) => { - assertInvalidDirectoryError(error); - expect(error.message).to.contain('path must be absolute'); - })); - it('./relative path', () => - checkError('./my/pluginsd', (error) => { - assertInvalidDirectoryError(error); - expect(error.message).to.contain('path must be absolute'); - })); - it('non-existent path', () => - checkError(resolve(PLUGINS_DIR, 'notreal'), (error) => { - assertInvalidDirectoryError(error); - expect(error.message).to.contain('no such file or directory'); - })); - it('path to a file', () => - checkError(resolve(PLUGINS_DIR, 'index.js'), (error) => { - assertInvalidDirectoryError(error); - expect(error.message).to.contain('not a directory'); - })); - }); - - it('includes child errors for invalid packageJsons within a valid directory', async () => { - const results = await createPackageJsonsInDirectory$(PLUGINS_DIR).pipe(toArray()).toPromise(); - - const errors = results.map((result) => result.error).filter(Boolean); - - const packageJsons = results.map((result) => result.packageJson).filter(Boolean); - - packageJsons.forEach((pack) => expect(pack).to.be.an(Object)); - // there should be one result for each item in PLUGINS_DIR - expect(results).to.have.length(8); - // three of the fixtures are errors of some sort - expect(errors).to.have.length(2); - // six of them are valid - expect(packageJsons).to.have.length(6); - }); - }); -}); diff --git a/src/legacy/plugin_discovery/plugin_pack/__tests__/plugin_pack.js b/src/legacy/plugin_discovery/plugin_pack/__tests__/plugin_pack.js deleted file mode 100644 index 769fcd74ce6fb..0000000000000 --- a/src/legacy/plugin_discovery/plugin_pack/__tests__/plugin_pack.js +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import expect from '@kbn/expect'; -import sinon from 'sinon'; - -import { PluginPack } from '../plugin_pack'; -import { PluginSpec } from '../../plugin_spec'; - -describe('plugin discovery/plugin pack', () => { - describe('constructor', () => { - it('requires an object', () => { - expect(() => { - new PluginPack(); - }).to.throwError(); - }); - }); - describe('#getPkg()', () => { - it('returns the `pkg` constructor argument', () => { - const pkg = {}; - const pack = new PluginPack({ pkg }); - expect(pack.getPkg()).to.be(pkg); - }); - }); - describe('#getPath()', () => { - it('returns the `path` constructor argument', () => { - const path = {}; - const pack = new PluginPack({ path }); - expect(pack.getPath()).to.be(path); - }); - }); - describe('#getPluginSpecs()', () => { - it('calls the `provider` constructor argument with an api including a single sub class of PluginSpec', () => { - const provider = sinon.stub(); - const pack = new PluginPack({ provider }); - sinon.assert.notCalled(provider); - pack.getPluginSpecs(); - sinon.assert.calledOnce(provider); - sinon.assert.calledWithExactly(provider, { - Plugin: sinon.match((Class) => { - return Class.prototype instanceof PluginSpec; - }, 'Subclass of PluginSpec'), - }); - }); - - it('casts undefined return value to array', () => { - const pack = new PluginPack({ provider: () => undefined }); - expect(pack.getPluginSpecs()).to.eql([]); - }); - - it('casts single PluginSpec to an array', () => { - const pack = new PluginPack({ - path: '/dev/null', - pkg: { name: 'foo', version: 'kibana' }, - provider: ({ Plugin }) => new Plugin({}), - }); - - const specs = pack.getPluginSpecs(); - expect(specs).to.be.an('array'); - expect(specs).to.have.length(1); - expect(specs[0]).to.be.a(PluginSpec); - }); - - it('returns an array of PluginSpec', () => { - const pack = new PluginPack({ - path: '/dev/null', - pkg: { name: 'foo', version: 'kibana' }, - provider: ({ Plugin }) => [new Plugin({}), new Plugin({})], - }); - - const specs = pack.getPluginSpecs(); - expect(specs).to.be.an('array'); - expect(specs).to.have.length(2); - expect(specs[0]).to.be.a(PluginSpec); - expect(specs[1]).to.be.a(PluginSpec); - }); - - it('throws if non-undefined return value is not an instance of api.Plugin', () => { - let OtherPluginSpecClass; - const otherPack = new PluginPack({ - path: '/dev/null', - pkg: { name: 'foo', version: 'kibana' }, - provider: (api) => { - OtherPluginSpecClass = api.Plugin; - }, - }); - - // call getPluginSpecs() on other pack to get it's api.Plugin class - otherPack.getPluginSpecs(); - - const badPacks = [ - new PluginPack({ provider: () => false }), - new PluginPack({ provider: () => null }), - new PluginPack({ provider: () => 1 }), - new PluginPack({ provider: () => 'true' }), - new PluginPack({ provider: () => true }), - new PluginPack({ provider: () => new Date() }), - new PluginPack({ provider: () => /foo.*bar/ }), - new PluginPack({ provider: () => function () {} }), - new PluginPack({ provider: () => new OtherPluginSpecClass({}) }), - ]; - - for (const pack of badPacks) { - expect(() => pack.getPluginSpecs()).to.throwError((error) => { - expect(error.message).to.contain('unexpected plugin export'); - }); - } - }); - }); -}); diff --git a/src/legacy/plugin_discovery/plugin_pack/__tests__/utils.js b/src/legacy/plugin_discovery/plugin_pack/__tests__/utils.js deleted file mode 100644 index adcf60d809ff7..0000000000000 --- a/src/legacy/plugin_discovery/plugin_pack/__tests__/utils.js +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { resolve } from 'path'; -import { inspect } from 'util'; - -import { isInvalidPackError, isInvalidDirectoryError } from '../../errors'; - -export const PLUGINS_DIR = resolve(__dirname, 'fixtures/plugins'); - -export function assertInvalidDirectoryError(error) { - if (!isInvalidDirectoryError(error)) { - throw new Error(`Expected ${inspect(error)} to be an 'InvalidDirectoryError'`); - } -} - -export function assertInvalidPackError(error) { - if (!isInvalidPackError(error)) { - throw new Error(`Expected ${inspect(error)} to be an 'InvalidPackError'`); - } -} diff --git a/src/legacy/plugin_discovery/plugin_pack/create_pack.js b/src/legacy/plugin_discovery/plugin_pack/create_pack.js deleted file mode 100644 index 189c2ea324103..0000000000000 --- a/src/legacy/plugin_discovery/plugin_pack/create_pack.js +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { PluginPack } from './plugin_pack'; -import { map, catchError } from 'rxjs/operators'; -import { createInvalidPackError } from '../errors'; - -function createPack(packageJson) { - let provider = require(packageJson.directoryPath); // eslint-disable-line import/no-dynamic-require - if (provider.__esModule) { - provider = provider.default; - } - if (typeof provider !== 'function') { - throw createInvalidPackError(packageJson.directoryPath, 'must export a function'); - } - - return new PluginPack({ path: packageJson.directoryPath, pkg: packageJson.contents, provider }); -} - -export const createPack$ = (packageJson$) => - packageJson$.pipe( - map(({ error, packageJson }) => { - if (error) { - return { error }; - } - - if (!packageJson) { - throw new Error('packageJson is required to create the pack'); - } - - return { - pack: createPack(packageJson), - }; - }), - // createPack can throw errors, and we want them to be represented - // like the errors we consume from createPackageJsonAtPath/Directory - catchError((error) => [{ error }]) - ); diff --git a/src/legacy/plugin_discovery/plugin_pack/index.js b/src/legacy/plugin_discovery/plugin_pack/index.js deleted file mode 100644 index 69e55baee660b..0000000000000 --- a/src/legacy/plugin_discovery/plugin_pack/index.js +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -export { createPack$ } from './create_pack'; -export { createPackageJsonAtPath$ } from './package_json_at_path'; -export { createPackageJsonsInDirectory$ } from './package_jsons_in_directory'; -export { PluginPack } from './plugin_pack'; diff --git a/src/legacy/plugin_discovery/plugin_pack/lib/fs.js b/src/legacy/plugin_discovery/plugin_pack/lib/fs.js deleted file mode 100644 index 2b531e314df52..0000000000000 --- a/src/legacy/plugin_discovery/plugin_pack/lib/fs.js +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { stat, readdir } from 'fs'; -import { resolve, isAbsolute } from 'path'; - -import { fromNode as fcb } from 'bluebird'; -import * as Rx from 'rxjs'; -import { catchError, mergeAll, filter, map, mergeMap } from 'rxjs/operators'; - -import { createInvalidDirectoryError } from '../../errors'; - -function assertAbsolutePath(path) { - if (typeof path !== 'string') { - throw createInvalidDirectoryError(new TypeError('path must be a string'), path); - } - - if (!isAbsolute(path)) { - throw createInvalidDirectoryError(new TypeError('path must be absolute'), path); - } -} - -async function statTest(path, test) { - try { - const stats = await fcb((cb) => stat(path, cb)); - return Boolean(test(stats)); - } catch (error) { - if (error.code !== 'ENOENT') { - throw error; - } - } - return false; -} - -/** - * Determine if a path currently points to a directory - * @param {String} path - * @return {Promise} - */ -export async function isDirectory(path) { - assertAbsolutePath(path); - return await statTest(path, (stat) => stat.isDirectory()); -} - -/** - * Get absolute paths for child directories within a path - * @param {string} path - * @return {Promise>} - */ -export const createChildDirectory$ = (path) => - Rx.defer(() => { - assertAbsolutePath(path); - return fcb((cb) => readdir(path, cb)); - }).pipe( - catchError((error) => { - throw createInvalidDirectoryError(error, path); - }), - mergeAll(), - filter((name) => !name.startsWith('.')), - map((name) => resolve(path, name)), - mergeMap(async (absolute) => { - if (await isDirectory(absolute)) { - return [absolute]; - } else { - return []; - } - }), - mergeAll() - ); diff --git a/src/legacy/plugin_discovery/plugin_pack/lib/index.js b/src/legacy/plugin_discovery/plugin_pack/lib/index.js deleted file mode 100644 index 491deeda27516..0000000000000 --- a/src/legacy/plugin_discovery/plugin_pack/lib/index.js +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -export { isDirectory, createChildDirectory$ } from './fs'; diff --git a/src/legacy/plugin_discovery/plugin_pack/package_json_at_path.js b/src/legacy/plugin_discovery/plugin_pack/package_json_at_path.js deleted file mode 100644 index 18629ef3ea802..0000000000000 --- a/src/legacy/plugin_discovery/plugin_pack/package_json_at_path.js +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { readFileSync } from 'fs'; -import * as Rx from 'rxjs'; -import { map, mergeMap, catchError } from 'rxjs/operators'; -import { resolve } from 'path'; -import { createInvalidPackError } from '../errors'; -// eslint-disable-next-line @kbn/eslint/no-restricted-paths -import { isNewPlatformPlugin } from '../../../core/server/plugins'; - -import { isDirectory } from './lib'; - -async function createPackageJsonAtPath(path) { - if (!(await isDirectory(path))) { - throw createInvalidPackError(path, 'must be a directory'); - } - - let str; - try { - str = readFileSync(resolve(path, 'package.json')); - } catch (err) { - throw createInvalidPackError(path, 'must have a package.json file'); - } - - let pkg; - try { - pkg = JSON.parse(str); - } catch (err) { - throw createInvalidPackError(path, 'must have a valid package.json file'); - } - - return { - directoryPath: path, - contents: pkg, - }; -} - -export const createPackageJsonAtPath$ = (path) => - // If plugin directory contains manifest file, we should skip it since it - // should have been handled by the core plugin system already. - Rx.defer(() => isNewPlatformPlugin(path)).pipe( - mergeMap((isNewPlatformPlugin) => (isNewPlatformPlugin ? [] : createPackageJsonAtPath(path))), - map((packageJson) => ({ packageJson })), - catchError((error) => [{ error }]) - ); diff --git a/src/legacy/plugin_discovery/plugin_pack/package_jsons_in_directory.js b/src/legacy/plugin_discovery/plugin_pack/package_jsons_in_directory.js deleted file mode 100644 index 5f0977f4829b8..0000000000000 --- a/src/legacy/plugin_discovery/plugin_pack/package_jsons_in_directory.js +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { mergeMap, catchError } from 'rxjs/operators'; -import { isInvalidDirectoryError } from '../errors'; - -import { createChildDirectory$ } from './lib'; -import { createPackageJsonAtPath$ } from './package_json_at_path'; - -/** - * Finds the plugins within a directory. Results are - * an array of objects with either `pack` or `error` - * keys. - * - * - `{ error }` results are provided when the path is not - * a directory, or one of the child directories is not a - * valid plugin pack. - * - `{ pack }` results are for discovered plugins defs - * - * @param {String} path - * @return {Array<{pack}|{error}>} - */ -export const createPackageJsonsInDirectory$ = (path) => - createChildDirectory$(path).pipe( - mergeMap(createPackageJsonAtPath$), - catchError((error) => { - // this error is produced by createChildDirectory$() when the path - // is invalid, we return them as an error result similar to how - // createPackAtPath$ works when it finds invalid packs in a directory - if (isInvalidDirectoryError(error)) { - return [{ error }]; - } - - throw error; - }) - ); diff --git a/src/legacy/plugin_discovery/plugin_pack/plugin_pack.js b/src/legacy/plugin_discovery/plugin_pack/plugin_pack.js deleted file mode 100644 index 1baf3d104ca84..0000000000000 --- a/src/legacy/plugin_discovery/plugin_pack/plugin_pack.js +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { inspect } from 'util'; - -import { PluginSpec } from '../plugin_spec'; - -export class PluginPack { - constructor({ path, pkg, provider }) { - this._path = path; - this._pkg = pkg; - this._provider = provider; - } - - /** - * Get the contents of this plugin pack's package.json file - * @return {Object} - */ - getPkg() { - return this._pkg; - } - - /** - * Get the absolute path to this plugin pack on disk - * @return {String} - */ - getPath() { - return this._path; - } - - /** - * Invoke the plugin pack's provider to get the list - * of specs defined in this plugin. - * @return {Array} - */ - getPluginSpecs() { - const pack = this; - const api = { - Plugin: class ScopedPluginSpec extends PluginSpec { - constructor(options) { - super(pack, options); - } - }, - }; - - const result = this._provider(api); - const specs = [].concat(result === undefined ? [] : result); - - // verify that all specs are instances of passed "Plugin" class - specs.forEach((spec) => { - if (!(spec instanceof api.Plugin)) { - throw new TypeError('unexpected plugin export ' + inspect(spec)); - } - }); - - return specs; - } -} diff --git a/src/legacy/plugin_discovery/plugin_spec/__tests__/is_version_compatible.js b/src/legacy/plugin_discovery/plugin_spec/__tests__/is_version_compatible.js deleted file mode 100644 index 897184496af37..0000000000000 --- a/src/legacy/plugin_discovery/plugin_spec/__tests__/is_version_compatible.js +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import expect from '@kbn/expect'; - -import { isVersionCompatible } from '../is_version_compatible'; - -describe('plugin discovery/plugin spec', () => { - describe('isVersionCompatible()', () => { - const tests = [ - ['kibana', '6.0.0', true], - ['kibana', '6.0.0-rc1', true], - ['6.0.0-rc1', '6.0.0', true], - ['6.0.0', '6.0.0-rc1', true], - ['6.0.0-rc2', '6.0.0-rc1', true], - ['6.0.0-rc2', '6.0.0-rc3', true], - ['foo', 'bar', false], - ['6.0.0', '5.1.4', false], - ['5.1.4', '6.0.0', false], - ['5.1.4-SNAPSHOT', '6.0.0-rc2-SNAPSHOT', false], - ['5.1.4', '6.0.0-rc2-SNAPSHOT', false], - ['5.1.4-SNAPSHOT', '6.0.0', false], - ['5.1.4-SNAPSHOT', '6.0.0-rc2', false], - ]; - - for (const [plugin, kibana, shouldPass] of tests) { - it(`${shouldPass ? 'should' : `shouldn't`} allow plugin: ${plugin} kibana: ${kibana}`, () => { - expect(isVersionCompatible(plugin, kibana)).to.be(shouldPass); - }); - } - }); -}); diff --git a/src/legacy/plugin_discovery/plugin_spec/__tests__/plugin_spec.js b/src/legacy/plugin_discovery/plugin_spec/__tests__/plugin_spec.js deleted file mode 100644 index 02675f0bd60f8..0000000000000 --- a/src/legacy/plugin_discovery/plugin_spec/__tests__/plugin_spec.js +++ /dev/null @@ -1,496 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { resolve } from 'path'; - -import expect from '@kbn/expect'; -import sinon from 'sinon'; - -import { PluginPack } from '../../plugin_pack'; -import { PluginSpec } from '../plugin_spec'; -import * as IsVersionCompatibleNS from '../is_version_compatible'; - -const fooPack = new PluginPack({ - path: '/dev/null', - pkg: { name: 'foo', version: 'kibana' }, -}); - -describe('plugin discovery/plugin spec', () => { - describe('PluginSpec', () => { - describe('validation', () => { - it('throws if missing spec.id AND Pack has no name', () => { - const pack = new PluginPack({ pkg: {} }); - expect(() => new PluginSpec(pack, {})).to.throwError((error) => { - expect(error.message).to.contain('Unable to determine plugin id'); - }); - }); - - it('throws if missing spec.kibanaVersion AND Pack has no version', () => { - const pack = new PluginPack({ pkg: { name: 'foo' } }); - expect(() => new PluginSpec(pack, {})).to.throwError((error) => { - expect(error.message).to.contain('Unable to determine plugin version'); - }); - }); - - it('throws if spec.require is defined, but not an array', () => { - function assert(require) { - expect(() => new PluginSpec(fooPack, { require })).to.throwError((error) => { - expect(error.message).to.contain('"plugin.require" must be an array of plugin ids'); - }); - } - - assert(null); - assert(''); - assert('kibana'); - assert(1); - assert(0); - assert(/a.*b/); - }); - - it('throws if spec.publicDir is truthy and not a string', () => { - function assert(publicDir) { - expect(() => new PluginSpec(fooPack, { publicDir })).to.throwError((error) => { - expect(error.message).to.contain( - `The "path" argument must be of type string. Received type ${typeof publicDir}` - ); - }); - } - - assert(1); - assert(function () {}); - assert([]); - assert(/a.*b/); - }); - - it('throws if spec.publicDir is not an absolute path', () => { - function assert(publicDir) { - expect(() => new PluginSpec(fooPack, { publicDir })).to.throwError((error) => { - expect(error.message).to.contain('plugin.publicDir must be an absolute path'); - }); - } - - assert('relative/path'); - assert('./relative/path'); - }); - - it('throws if spec.publicDir basename is not `public`', () => { - function assert(publicDir) { - expect(() => new PluginSpec(fooPack, { publicDir })).to.throwError((error) => { - expect(error.message).to.contain('must end with a "public" directory'); - }); - } - - assert('/www'); - assert('/www/'); - assert('/www/public/my_plugin'); - assert('/www/public/my_plugin/'); - }); - }); - - describe('#getPack()', () => { - it('returns the pack', () => { - const spec = new PluginSpec(fooPack, {}); - expect(spec.getPack()).to.be(fooPack); - }); - }); - - describe('#getPkg()', () => { - it('returns the pkg from the pack', () => { - const spec = new PluginSpec(fooPack, {}); - expect(spec.getPkg()).to.be(fooPack.getPkg()); - }); - }); - - describe('#getPath()', () => { - it('returns the path from the pack', () => { - const spec = new PluginSpec(fooPack, {}); - expect(spec.getPath()).to.be(fooPack.getPath()); - }); - }); - - describe('#getId()', () => { - it('uses spec.id', () => { - const spec = new PluginSpec(fooPack, { - id: 'bar', - }); - - expect(spec.getId()).to.be('bar'); - }); - - it('defaults to pack.pkg.name', () => { - const spec = new PluginSpec(fooPack, {}); - - expect(spec.getId()).to.be('foo'); - }); - }); - - describe('#getVersion()', () => { - it('uses spec.version', () => { - const spec = new PluginSpec(fooPack, { - version: 'bar', - }); - - expect(spec.getVersion()).to.be('bar'); - }); - - it('defaults to pack.pkg.version', () => { - const spec = new PluginSpec(fooPack, {}); - - expect(spec.getVersion()).to.be('kibana'); - }); - }); - - describe('#isEnabled()', () => { - describe('spec.isEnabled is not defined', () => { - function setup(configPrefix, configGetImpl) { - const spec = new PluginSpec(fooPack, { configPrefix }); - const config = { - get: sinon.spy(configGetImpl), - has: sinon.stub(), - }; - - return { spec, config }; - } - - it('throws if not passed a config service', () => { - const { spec } = setup('a.b.c', () => true); - - expect(() => spec.isEnabled()).to.throwError((error) => { - expect(error.message).to.contain('must be called with a config service'); - }); - expect(() => spec.isEnabled(null)).to.throwError((error) => { - expect(error.message).to.contain('must be called with a config service'); - }); - expect(() => spec.isEnabled({ get: () => {} })).to.throwError((error) => { - expect(error.message).to.contain('must be called with a config service'); - }); - }); - - it('returns true when config.get([...configPrefix, "enabled"]) returns true', () => { - const { spec, config } = setup('d.e.f', () => true); - - expect(spec.isEnabled(config)).to.be(true); - sinon.assert.calledOnce(config.get); - sinon.assert.calledWithExactly(config.get, ['d', 'e', 'f', 'enabled']); - }); - - it('returns false when config.get([...configPrefix, "enabled"]) returns false', () => { - const { spec, config } = setup('g.h.i', () => false); - - expect(spec.isEnabled(config)).to.be(false); - sinon.assert.calledOnce(config.get); - sinon.assert.calledWithExactly(config.get, ['g', 'h', 'i', 'enabled']); - }); - }); - - describe('spec.isEnabled is defined', () => { - function setup(isEnabledImpl) { - const isEnabled = sinon.spy(isEnabledImpl); - const spec = new PluginSpec(fooPack, { isEnabled }); - const config = { - get: sinon.stub(), - has: sinon.stub(), - }; - - return { isEnabled, spec, config }; - } - - it('throws if not passed a config service', () => { - const { spec } = setup(() => true); - - expect(() => spec.isEnabled()).to.throwError((error) => { - expect(error.message).to.contain('must be called with a config service'); - }); - expect(() => spec.isEnabled(null)).to.throwError((error) => { - expect(error.message).to.contain('must be called with a config service'); - }); - expect(() => spec.isEnabled({ get: () => {} })).to.throwError((error) => { - expect(error.message).to.contain('must be called with a config service'); - }); - }); - - it('does not check config if spec.isEnabled returns true', () => { - const { spec, isEnabled, config } = setup(() => true); - - expect(spec.isEnabled(config)).to.be(true); - sinon.assert.calledOnce(isEnabled); - sinon.assert.notCalled(config.get); - }); - - it('does not check config if spec.isEnabled returns false', () => { - const { spec, isEnabled, config } = setup(() => false); - - expect(spec.isEnabled(config)).to.be(false); - sinon.assert.calledOnce(isEnabled); - sinon.assert.notCalled(config.get); - }); - }); - }); - - describe('#getExpectedKibanaVersion()', () => { - describe('has: spec.kibanaVersion,pkg.kibana.version,spec.version,pkg.version', () => { - it('uses spec.kibanaVersion', () => { - const pack = new PluginPack({ - path: '/dev/null', - pkg: { - name: 'expkv', - version: '1.0.0', - kibana: { - version: '6.0.0', - }, - }, - }); - - const spec = new PluginSpec(pack, { - version: '2.0.0', - kibanaVersion: '5.0.0', - }); - - expect(spec.getExpectedKibanaVersion()).to.be('5.0.0'); - }); - }); - describe('missing: spec.kibanaVersion, has: pkg.kibana.version,spec.version,pkg.version', () => { - it('uses pkg.kibana.version', () => { - const pack = new PluginPack({ - path: '/dev/null', - pkg: { - name: 'expkv', - version: '1.0.0', - kibana: { - version: '6.0.0', - }, - }, - }); - - const spec = new PluginSpec(pack, { - version: '2.0.0', - }); - - expect(spec.getExpectedKibanaVersion()).to.be('6.0.0'); - }); - }); - describe('missing: spec.kibanaVersion,pkg.kibana.version, has: spec.version,pkg.version', () => { - it('uses spec.version', () => { - const pack = new PluginPack({ - path: '/dev/null', - pkg: { - name: 'expkv', - version: '1.0.0', - }, - }); - - const spec = new PluginSpec(pack, { - version: '2.0.0', - }); - - expect(spec.getExpectedKibanaVersion()).to.be('2.0.0'); - }); - }); - describe('missing: spec.kibanaVersion,pkg.kibana.version,spec.version, has: pkg.version', () => { - it('uses pkg.version', () => { - const pack = new PluginPack({ - path: '/dev/null', - pkg: { - name: 'expkv', - version: '1.0.0', - }, - }); - - const spec = new PluginSpec(pack, {}); - - expect(spec.getExpectedKibanaVersion()).to.be('1.0.0'); - }); - }); - }); - - describe('#isVersionCompatible()', () => { - it('passes this.getExpectedKibanaVersion() and arg to isVersionCompatible(), returns its result', () => { - const spec = new PluginSpec(fooPack, { version: '1.0.0' }); - sinon.stub(spec, 'getExpectedKibanaVersion').returns('foo'); - const isVersionCompatible = sinon - .stub(IsVersionCompatibleNS, 'isVersionCompatible') - .returns('bar'); - expect(spec.isVersionCompatible('baz')).to.be('bar'); - - sinon.assert.calledOnce(spec.getExpectedKibanaVersion); - sinon.assert.calledWithExactly(spec.getExpectedKibanaVersion); - - sinon.assert.calledOnce(isVersionCompatible); - sinon.assert.calledWithExactly(isVersionCompatible, 'foo', 'baz'); - }); - }); - - describe('#getRequiredPluginIds()', () => { - it('returns spec.require', () => { - const spec = new PluginSpec(fooPack, { require: [1, 2, 3] }); - expect(spec.getRequiredPluginIds()).to.eql([1, 2, 3]); - }); - }); - - describe('#getPublicDir()', () => { - describe('spec.publicDir === false', () => { - it('returns null', () => { - const spec = new PluginSpec(fooPack, { publicDir: false }); - expect(spec.getPublicDir()).to.be(null); - }); - }); - - describe('spec.publicDir is falsy', () => { - it('returns public child of pack path', () => { - function assert(publicDir) { - const spec = new PluginSpec(fooPack, { publicDir }); - expect(spec.getPublicDir()).to.be(resolve('/dev/null/public')); - } - - assert(0); - assert(''); - assert(null); - assert(undefined); - assert(NaN); - }); - }); - - describe('spec.publicDir is an absolute path', () => { - it('returns the path', () => { - const spec = new PluginSpec(fooPack, { - publicDir: '/var/www/public', - }); - - expect(spec.getPublicDir()).to.be('/var/www/public'); - }); - }); - - // NOTE: see constructor tests for other truthy-tests that throw in constructor - }); - - describe('#getExportSpecs()', () => { - it('returns spec.uiExports', () => { - const spec = new PluginSpec(fooPack, { - uiExports: 'foo', - }); - - expect(spec.getExportSpecs()).to.be('foo'); - }); - }); - - describe('#getPreInitHandler()', () => { - it('returns spec.preInit', () => { - const spec = new PluginSpec(fooPack, { - preInit: 'foo', - }); - - expect(spec.getPreInitHandler()).to.be('foo'); - }); - }); - - describe('#getInitHandler()', () => { - it('returns spec.init', () => { - const spec = new PluginSpec(fooPack, { - init: 'foo', - }); - - expect(spec.getInitHandler()).to.be('foo'); - }); - }); - - describe('#getConfigPrefix()', () => { - describe('spec.configPrefix is truthy', () => { - it('returns spec.configPrefix', () => { - const spec = new PluginSpec(fooPack, { - configPrefix: 'foo.bar.baz', - }); - - expect(spec.getConfigPrefix()).to.be('foo.bar.baz'); - }); - }); - describe('spec.configPrefix is falsy', () => { - it('returns spec.getId()', () => { - function assert(configPrefix) { - const spec = new PluginSpec(fooPack, { configPrefix }); - sinon.stub(spec, 'getId').returns('foo'); - expect(spec.getConfigPrefix()).to.be('foo'); - sinon.assert.calledOnce(spec.getId); - } - - assert(false); - assert(null); - assert(undefined); - assert(''); - assert(0); - }); - }); - }); - - describe('#getConfigSchemaProvider()', () => { - it('returns spec.config', () => { - const spec = new PluginSpec(fooPack, { - config: 'foo', - }); - - expect(spec.getConfigSchemaProvider()).to.be('foo'); - }); - }); - - describe('#readConfigValue()', () => { - const spec = new PluginSpec(fooPack, { - configPrefix: 'foo.bar', - }); - - const config = { - get: sinon.stub(), - }; - - afterEach(() => config.get.resetHistory()); - - describe('key = "foo"', () => { - it('passes key as own array item', () => { - spec.readConfigValue(config, 'foo'); - sinon.assert.calledOnce(config.get); - sinon.assert.calledWithExactly(config.get, ['foo', 'bar', 'foo']); - }); - }); - - describe('key = "foo.bar"', () => { - it('passes key as two array items', () => { - spec.readConfigValue(config, 'foo.bar'); - sinon.assert.calledOnce(config.get); - sinon.assert.calledWithExactly(config.get, ['foo', 'bar', 'foo', 'bar']); - }); - }); - - describe('key = ["foo", "bar"]', () => { - it('merged keys into array', () => { - spec.readConfigValue(config, ['foo', 'bar']); - sinon.assert.calledOnce(config.get); - sinon.assert.calledWithExactly(config.get, ['foo', 'bar', 'foo', 'bar']); - }); - }); - }); - - describe('#getDeprecationsProvider()', () => { - it('returns spec.deprecations', () => { - const spec = new PluginSpec(fooPack, { - deprecations: 'foo', - }); - - expect(spec.getDeprecationsProvider()).to.be('foo'); - }); - }); - }); -}); diff --git a/src/legacy/plugin_discovery/plugin_spec/index.js b/src/legacy/plugin_discovery/plugin_spec/index.js deleted file mode 100644 index 671d311b152e2..0000000000000 --- a/src/legacy/plugin_discovery/plugin_spec/index.js +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -export { PluginSpec } from './plugin_spec'; diff --git a/src/legacy/plugin_discovery/plugin_spec/is_version_compatible.js b/src/legacy/plugin_discovery/plugin_spec/is_version_compatible.js deleted file mode 100644 index 6822c168f368d..0000000000000 --- a/src/legacy/plugin_discovery/plugin_spec/is_version_compatible.js +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { cleanVersion, versionSatisfies } from '../../utils/version'; - -export function isVersionCompatible(version, compatibleWith) { - // the special "kibana" version can be used to always be compatible, - // but is intentionally not supported by the plugin installer - if (version === 'kibana') { - return true; - } - - return versionSatisfies(cleanVersion(version), cleanVersion(compatibleWith)); -} diff --git a/src/legacy/plugin_discovery/plugin_spec/plugin_spec.js b/src/legacy/plugin_discovery/plugin_spec/plugin_spec.js deleted file mode 100644 index db1ec425f2ce5..0000000000000 --- a/src/legacy/plugin_discovery/plugin_spec/plugin_spec.js +++ /dev/null @@ -1,210 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { resolve, basename, isAbsolute as isAbsolutePath } from 'path'; - -import { get, toPath } from 'lodash'; - -import { createInvalidPluginError } from '../errors'; -import { isVersionCompatible } from './is_version_compatible'; - -export class PluginSpec { - /** - * @param {PluginPack} pack The plugin pack that produced this spec - * @param {Object} opts the options for this plugin - * @param {String} [opts.id=pkg.name] the id for this plugin. - * @param {Object} [opts.uiExports] a mapping of UiExport types to - * UI modules or metadata about the UI module - * @param {Array} [opts.require] the other plugins that this plugin - * requires. These plugins must exist and be enabled for this plugin - * to function. The require'd plugins will also be initialized first, - * in order to make sure that dependencies provided by these plugins - * are available - * @param {String} [opts.version=pkg.version] the version of this plugin - * @param {Function} [opts.init] A function that will be called to initialize - * this plugin at the appropriate time. - * @param {Function} [opts.configPrefix=this.id] The prefix to use for - * configuration values in the main configuration service - * @param {Function} [opts.config] A function that produces a configuration - * schema using Joi, which is passed as its first argument. - * @param {String|False} [opts.publicDir=path + '/public'] the public - * directory for this plugin. The final directory must have the name "public", - * though it can be located somewhere besides the root of the plugin. Set - * this to false to disable exposure of a public directory - */ - constructor(pack, options) { - const { - id, - require, - version, - kibanaVersion, - uiExports, - uiCapabilities, - publicDir, - configPrefix, - config, - deprecations, - preInit, - init, - postInit, - isEnabled, - } = options; - - this._id = id; - this._pack = pack; - this._version = version; - this._kibanaVersion = kibanaVersion; - this._require = require; - - this._publicDir = publicDir; - this._uiExports = uiExports; - this._uiCapabilities = uiCapabilities; - - this._configPrefix = configPrefix; - this._configSchemaProvider = config; - this._configDeprecationsProvider = deprecations; - - this._isEnabled = isEnabled; - this._preInit = preInit; - this._init = init; - this._postInit = postInit; - - if (!this.getId()) { - throw createInvalidPluginError(this, 'Unable to determine plugin id'); - } - - if (!this.getVersion()) { - throw createInvalidPluginError(this, 'Unable to determine plugin version'); - } - - if (this.getRequiredPluginIds() !== undefined && !Array.isArray(this.getRequiredPluginIds())) { - throw createInvalidPluginError(this, '"plugin.require" must be an array of plugin ids'); - } - - if (this._publicDir) { - if (!isAbsolutePath(this._publicDir)) { - throw createInvalidPluginError(this, 'plugin.publicDir must be an absolute path'); - } - if (basename(this._publicDir) !== 'public') { - throw createInvalidPluginError( - this, - `publicDir for plugin ${this.getId()} must end with a "public" directory.` - ); - } - } - } - - getPack() { - return this._pack; - } - - getPkg() { - return this._pack.getPkg(); - } - - getPath() { - return this._pack.getPath(); - } - - getId() { - return this._id || this.getPkg().name; - } - - getVersion() { - return this._version || this.getPkg().version; - } - - isEnabled(config) { - if (!config || typeof config.get !== 'function' || typeof config.has !== 'function') { - throw new TypeError('PluginSpec#isEnabled() must be called with a config service'); - } - - if (this._isEnabled) { - return this._isEnabled(config); - } - - return Boolean(this.readConfigValue(config, 'enabled')); - } - - getExpectedKibanaVersion() { - // Plugins must specify their version, and by default that version should match - // the version of kibana down to the patch level. If these two versions need - // to diverge, they can specify a kibana.version in the package to indicate the - // version of kibana the plugin is intended to work with. - return ( - this._kibanaVersion || get(this.getPack().getPkg(), 'kibana.version') || this.getVersion() - ); - } - - isVersionCompatible(actualKibanaVersion) { - return isVersionCompatible(this.getExpectedKibanaVersion(), actualKibanaVersion); - } - - getRequiredPluginIds() { - return this._require; - } - - getPublicDir() { - if (this._publicDir === false) { - return null; - } - - if (!this._publicDir) { - return resolve(this.getPack().getPath(), 'public'); - } - - return this._publicDir; - } - - getExportSpecs() { - return this._uiExports; - } - - getUiCapabilitiesProvider() { - return this._uiCapabilities; - } - - getPreInitHandler() { - return this._preInit; - } - - getInitHandler() { - return this._init; - } - - getPostInitHandler() { - return this._postInit; - } - - getConfigPrefix() { - return this._configPrefix || this.getId(); - } - - getConfigSchemaProvider() { - return this._configSchemaProvider; - } - - readConfigValue(config, key) { - return config.get([...toPath(this.getConfigPrefix()), ...toPath(key)]); - } - - getDeprecationsProvider() { - return this._configDeprecationsProvider; - } -} diff --git a/src/legacy/plugin_discovery/plugin_spec/plugin_spec_options.d.ts b/src/legacy/plugin_discovery/plugin_spec/plugin_spec_options.d.ts deleted file mode 100644 index e1ed2f57375a4..0000000000000 --- a/src/legacy/plugin_discovery/plugin_spec/plugin_spec_options.d.ts +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -import { Server } from '../../server/kbn_server'; -import { Capabilities } from '../../../core/server'; - -export type InitPluginFunction = (server: Server) => void; -export interface UiExports { - injectDefaultVars?: (server: Server) => { [key: string]: any }; -} - -export interface PluginSpecOptions { - id: string; - require?: string[]; - publicDir?: string; - uiExports?: UiExports; - uiCapabilities?: Capabilities; - init?: InitPluginFunction; - config?: any; -} diff --git a/src/legacy/plugin_discovery/types.ts b/src/legacy/plugin_discovery/types.ts deleted file mode 100644 index 700ca6fa68c95..0000000000000 --- a/src/legacy/plugin_discovery/types.ts +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { Server } from '../server/kbn_server'; -import { Capabilities } from '../../core/server'; -import { AppCategory } from '../../core/types'; - -/** - * Usage - * - * ``` - * const apmOss: LegacyPlugin = (kibana) => { - * return new kibana.Plugin({ - * id: 'apm_oss', - * // ... - * }); - * }; - * ``` - */ -export type LegacyPluginInitializer = (kibana: LegacyPluginApi) => ArrayOrItem; - -export type ArrayOrItem = T | T[]; - -export interface LegacyPluginApi { - Plugin: new (options: Partial) => LegacyPluginSpec; -} - -export interface LegacyPluginOptions { - id: string; - require: string[]; - version: string; - kibanaVersion: 'kibana'; - uiExports: Partial<{ - app: Partial<{ - title: string; - category?: AppCategory; - description: string; - main: string; - icon: string; - euiIconType: string; - order: number; - listed: boolean; - }>; - apps: any; - hacks: string[]; - visualize: string[]; - devTools: string[]; - injectDefaultVars: (server: Server) => Record; - home: string[]; - mappings: any; - migrations: any; - visTypes: string[]; - embeddableActions?: string[]; - embeddableFactories?: string[]; - uiSettingDefaults?: Record; - interpreter: string | string[]; - }>; - uiCapabilities?: Capabilities; - publicDir: any; - configPrefix: any; - config: any; - deprecations: any; - preInit: any; - init: InitPluginFunction; - postInit: any; - isEnabled: boolean; -} - -export type InitPluginFunction = (server: Server) => void; - -export interface LegacyPluginSpec { - getPack(): any; - getPkg(): any; - getPath(): string; - getId(): string; - getVersion(): string; - isEnabled(config: any): boolean; - getExpectedKibanaVersion(): string; - isVersionCompatible(actualKibanaVersion: any): boolean; - getRequiredPluginIds(): string[]; - getPublicDir(): string | null; - getExportSpecs(): any; - getUiCapabilitiesProvider(): any; - getPreInitHandler(): any; - getInitHandler(): any; - getPostInitHandler(): any; - getConfigPrefix(): string; - getConfigSchemaProvider(): any; - readConfigValue(config: any, key: string): any; - getDeprecationsProvider(): any; -} diff --git a/src/legacy/server/config/schema.js b/src/legacy/server/config/schema.js index f8736fb30f90e..e1f03b8a08847 100644 --- a/src/legacy/server/config/schema.js +++ b/src/legacy/server/config/schema.js @@ -25,6 +25,10 @@ const HANDLED_IN_NEW_PLATFORM = Joi.any().description( ); export default () => Joi.object({ + elastic: Joi.object({ + apm: HANDLED_IN_NEW_PLATFORM, + }).default(), + pkg: Joi.object({ version: Joi.string().default(Joi.ref('$version')), branch: Joi.string().default(Joi.ref('$branch')), @@ -38,12 +42,8 @@ export default () => prod: Joi.boolean().default(Joi.ref('$prod')), }).default(), - dev: Joi.object({ - basePathProxyTarget: Joi.number().default(5603), - }).default(), - + dev: HANDLED_IN_NEW_PLATFORM, pid: HANDLED_IN_NEW_PLATFORM, - csp: HANDLED_IN_NEW_PLATFORM, server: Joi.object({ @@ -125,12 +125,10 @@ export default () => ops: Joi.object({ interval: Joi.number().default(5000), - cGroupOverrides: Joi.object().keys({ - cpuPath: Joi.string().default(), - cpuAcctPath: Joi.string().default(), - }), + cGroupOverrides: HANDLED_IN_NEW_PLATFORM, }).default(), + // still used by the legacy i18n mixin plugins: Joi.object({ paths: Joi.array().items(Joi.string()).default([]), scanDirs: Joi.array().items(Joi.string()).default([]), @@ -138,79 +136,9 @@ export default () => }).default(), path: HANDLED_IN_NEW_PLATFORM, - - stats: Joi.object({ - maximumWaitTimeForAllCollectorsInS: Joi.number().default(60), - }).default(), - - status: Joi.object({ - allowAnonymous: Joi.boolean().default(false), - }).default(), - map: Joi.object({ - includeElasticMapsService: Joi.boolean().default(true), - proxyElasticMapsServiceInMaps: Joi.boolean().default(false), - tilemap: Joi.object({ - url: Joi.string(), - options: Joi.object({ - attribution: Joi.string(), - minZoom: Joi.number().min(0, 'Must be 0 or higher').default(0), - maxZoom: Joi.number().default(10), - tileSize: Joi.number(), - subdomains: Joi.array().items(Joi.string()).single(), - errorTileUrl: Joi.string().uri(), - tms: Joi.boolean(), - reuseTiles: Joi.boolean(), - bounds: Joi.array().items(Joi.array().items(Joi.number()).min(2).required()).min(2), - default: Joi.boolean(), - }).default({ - default: true, - }), - }).default(), - regionmap: Joi.object({ - includeElasticMapsService: Joi.boolean().default(true), - layers: Joi.array() - .items( - Joi.object({ - url: Joi.string(), - format: Joi.object({ - type: Joi.string().default('geojson'), - }).default({ - type: 'geojson', - }), - meta: Joi.object({ - feature_collection_path: Joi.string().default('data'), - }).default({ - feature_collection_path: 'data', - }), - attribution: Joi.string(), - name: Joi.string(), - fields: Joi.array().items( - Joi.object({ - name: Joi.string(), - description: Joi.string(), - }) - ), - }) - ) - .default([]), - }).default(), - manifestServiceUrl: Joi.string().default('').allow(''), - emsFileApiUrl: Joi.string().default('https://vector.maps.elastic.co'), - emsTileApiUrl: Joi.string().default('https://tiles.maps.elastic.co'), - emsLandingPageUrl: Joi.string().default('https://maps.elastic.co/v7.9'), - emsFontLibraryUrl: Joi.string().default( - 'https://tiles.maps.elastic.co/fonts/{fontstack}/{range}.pbf' - ), - emsTileLayerId: Joi.object({ - bright: Joi.string().default('road_map'), - desaturated: Joi.string().default('road_map_desaturated'), - dark: Joi.string().default('dark_map'), - }).default({ - bright: 'road_map', - desaturated: 'road_map_desaturated', - dark: 'dark_map', - }), - }).default(), + stats: HANDLED_IN_NEW_PLATFORM, + status: HANDLED_IN_NEW_PLATFORM, + map: HANDLED_IN_NEW_PLATFORM, i18n: Joi.object({ locale: Joi.string().default('en'), @@ -225,8 +153,5 @@ export default () => autocompleteTimeout: Joi.number().integer().min(1).default(1000), }).default(), - savedObjects: Joi.object({ - maxImportPayloadBytes: Joi.number().default(10485760), - maxImportExportSize: Joi.number().default(10000), - }).default(), + savedObjects: HANDLED_IN_NEW_PLATFORM, }).default(); diff --git a/src/legacy/server/kbn_server.d.ts b/src/legacy/server/kbn_server.d.ts index 3cfda0e0696bb..1718a9a8f55da 100644 --- a/src/legacy/server/kbn_server.d.ts +++ b/src/legacy/server/kbn_server.d.ts @@ -26,11 +26,10 @@ import { LoggerFactory, PackageInfo, LegacyServiceSetupDeps, - LegacyServiceDiscoverPlugins, } from '../../core/server'; // eslint-disable-next-line @kbn/eslint/no-restricted-paths -import { LegacyConfig, ILegacyInternals } from '../../core/server/legacy'; +import { LegacyConfig } from '../../core/server/legacy'; // eslint-disable-next-line @kbn/eslint/no-restricted-paths import { UiPlugins } from '../../core/server/plugins'; @@ -58,9 +57,7 @@ export interface PluginsSetup { export interface KibanaCore { __internals: { - elasticsearch: LegacyServiceSetupDeps['core']['elasticsearch']; hapiServer: LegacyServiceSetupDeps['core']['http']['server']; - legacy: ILegacyInternals; rendering: LegacyServiceSetupDeps['core']['rendering']; uiPlugins: UiPlugins; }; @@ -90,31 +87,18 @@ export interface NewPlatform { stop: null; } -export type LegacyPlugins = Pick< - LegacyServiceDiscoverPlugins, - 'pluginSpecs' | 'disabledPluginSpecs' | 'uiExports' ->; - // eslint-disable-next-line import/no-default-export export default class KbnServer { public readonly newPlatform: NewPlatform; public server: Server; public inject: Server['inject']; - public pluginSpecs: any[]; - public uiBundles: any; - constructor( - settings: Record, - config: KibanaConfig, - core: KibanaCore, - legacyPlugins: LegacyPlugins - ); + constructor(settings: Record, config: KibanaConfig, core: KibanaCore); public ready(): Promise; public mixin(...fns: KbnMixinFunc[]): Promise; public listen(): Promise; public close(): Promise; - public afterPluginsInit(callback: () => void): void; public applyLoggingConfiguration(settings: any): void; public config: KibanaConfig; } diff --git a/src/legacy/server/kbn_server.js b/src/legacy/server/kbn_server.js index 107e5f6387833..e29563a7c6266 100644 --- a/src/legacy/server/kbn_server.js +++ b/src/legacy/server/kbn_server.js @@ -30,7 +30,6 @@ import { loggingMixin } from './logging'; import warningsMixin from './warnings'; import configCompleteMixin from './config/complete'; import { optimizeMixin } from '../../optimize'; -import * as Plugins from './plugins'; import { uiMixin } from '../ui'; import { i18nMixin } from './i18n'; @@ -47,9 +46,8 @@ export default class KbnServer { * @param {Record} settings * @param {KibanaConfig} config * @param {KibanaCore} core - * @param {LegacyPlugins} legacyPlugins */ - constructor(settings, config, core, legacyPlugins) { + constructor(settings, config, core) { this.name = pkg.name; this.version = pkg.version; this.build = pkg.build || false; @@ -74,14 +72,8 @@ export default class KbnServer { stop: null, }; - this.uiExports = legacyPlugins.uiExports; - this.pluginSpecs = legacyPlugins.pluginSpecs; - this.disabledPluginSpecs = legacyPlugins.disabledPluginSpecs; - this.ready = constant( this.mixin( - Plugins.waitForInitSetupMixin, - // Sets global HTTP behaviors httpMixin, @@ -93,22 +85,13 @@ export default class KbnServer { // scan translations dirs, register locale files and initialize i18n engine. i18nMixin, - // find plugins and set this.plugins and this.pluginSpecs - Plugins.scanMixin, - // tell the config we are done loading plugins configCompleteMixin, uiMixin, // setup routes that serve the @kbn/optimizer output - optimizeMixin, - - // initialize the plugins - Plugins.initializeMixin, - - // notify any deferred setup logic that plugins have initialized - Plugins.waitForInitResolveMixin + optimizeMixin ) ); diff --git a/src/legacy/server/logging/rotate/log_rotator.test.ts b/src/legacy/server/logging/rotate/log_rotator.test.ts index 70842d42f5e1f..8f67b47f6949e 100644 --- a/src/legacy/server/logging/rotate/log_rotator.test.ts +++ b/src/legacy/server/logging/rotate/log_rotator.test.ts @@ -22,6 +22,7 @@ import fs, { existsSync, mkdirSync, statSync, writeFileSync } from 'fs'; import { LogRotator } from './log_rotator'; import { tmpdir } from 'os'; import { dirname, join } from 'path'; +import lodash from 'lodash'; const mockOn = jest.fn(); jest.mock('chokidar', () => ({ @@ -31,10 +32,7 @@ jest.mock('chokidar', () => ({ })), })); -jest.mock('lodash', () => ({ - ...require.requireActual('lodash'), - throttle: (fn: any) => fn, -})); +lodash.throttle = (fn: any) => fn; const tempDir = join(tmpdir(), 'kbn_log_rotator_test'); const testFilePath = join(tempDir, 'log_rotator_test_log_file.log'); diff --git a/src/legacy/server/plugins/index.js b/src/legacy/server/plugins/index.js deleted file mode 100644 index 1511b63b519ae..0000000000000 --- a/src/legacy/server/plugins/index.js +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -export { scanMixin } from './scan_mixin'; -export { initializeMixin } from './initialize_mixin'; -export { waitForInitSetupMixin, waitForInitResolveMixin } from './wait_for_plugins_init'; diff --git a/src/legacy/server/plugins/initialize_mixin.js b/src/legacy/server/plugins/initialize_mixin.js deleted file mode 100644 index ccf4cd1c1a404..0000000000000 --- a/src/legacy/server/plugins/initialize_mixin.js +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { callPluginHook } from './lib'; - -/** - * KbnServer mixin that initializes all plugins found in ./scan mixin - * @param {KbnServer} kbnServer - * @param {Hapi.Server} server - * @param {Config} config - * @return {Promise} - */ -export async function initializeMixin(kbnServer, server, config) { - if (!config.get('plugins.initialize')) { - server.log(['info'], 'Plugin initialization disabled.'); - return; - } - - async function callHookOnPlugins(hookName) { - const { plugins } = kbnServer; - const ids = plugins.map((p) => p.id); - - for (const id of ids) { - await callPluginHook(hookName, plugins, id, []); - } - } - - await callHookOnPlugins('preInit'); - await callHookOnPlugins('init'); - await callHookOnPlugins('postInit'); -} diff --git a/src/legacy/server/plugins/lib/call_plugin_hook.js b/src/legacy/server/plugins/lib/call_plugin_hook.js deleted file mode 100644 index b665869f5d25f..0000000000000 --- a/src/legacy/server/plugins/lib/call_plugin_hook.js +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { last } from 'lodash'; - -export async function callPluginHook(hookName, plugins, id, history) { - const plugin = plugins.find((plugin) => plugin.id === id); - - // make sure this is a valid plugin id - if (!plugin) { - if (history.length) { - throw new Error(`Unmet requirement "${id}" for plugin "${last(history)}"`); - } else { - throw new Error(`Unknown plugin "${id}"`); - } - } - - const circleStart = history.indexOf(id); - const path = [...history, id]; - - // make sure we are not trying to load a dependency within itself - if (circleStart > -1) { - const circle = path.slice(circleStart); - throw new Error(`circular dependency found: "${circle.join(' -> ')}"`); - } - - // call hook on all dependencies - for (const req of plugin.requiredIds) { - await callPluginHook(hookName, plugins, req, path); - } - - // call hook on this plugin - await plugin[hookName](); -} diff --git a/src/legacy/server/plugins/lib/call_plugin_hook.test.js b/src/legacy/server/plugins/lib/call_plugin_hook.test.js deleted file mode 100644 index 30dc2d91a9ab2..0000000000000 --- a/src/legacy/server/plugins/lib/call_plugin_hook.test.js +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import sinon from 'sinon'; -import { callPluginHook } from './call_plugin_hook'; - -describe('server/plugins/callPluginHook', () => { - it('should call in correct order based on requirements', async () => { - const plugins = [ - { - id: 'foo', - init: sinon.spy(), - preInit: sinon.spy(), - requiredIds: ['bar', 'baz'], - }, - { - id: 'bar', - init: sinon.spy(), - preInit: sinon.spy(), - requiredIds: [], - }, - { - id: 'baz', - init: sinon.spy(), - preInit: sinon.spy(), - requiredIds: ['bar'], - }, - ]; - - await callPluginHook('init', plugins, 'foo', []); - const [foo, bar, baz] = plugins; - sinon.assert.calledOnce(foo.init); - sinon.assert.calledTwice(bar.init); - sinon.assert.calledOnce(baz.init); - sinon.assert.callOrder(bar.init, baz.init, foo.init); - }); - - it('throws meaningful error when required plugin is missing', async () => { - const plugins = [ - { - id: 'foo', - init: sinon.spy(), - preInit: sinon.spy(), - requiredIds: ['bar'], - }, - ]; - - try { - await callPluginHook('init', plugins, 'foo', []); - throw new Error('expected callPluginHook to throw'); - } catch (error) { - expect(error.message).toContain('"bar" for plugin "foo"'); - } - }); - - it('throws meaningful error when dependencies are circular', async () => { - const plugins = [ - { - id: 'foo', - init: sinon.spy(), - preInit: sinon.spy(), - requiredIds: ['bar'], - }, - { - id: 'bar', - init: sinon.spy(), - preInit: sinon.spy(), - requiredIds: ['baz'], - }, - { - id: 'baz', - init: sinon.spy(), - preInit: sinon.spy(), - requiredIds: ['foo'], - }, - ]; - - try { - await callPluginHook('init', plugins, 'foo', []); - throw new Error('expected callPluginHook to throw'); - } catch (error) { - expect(error.message).toContain('foo -> bar -> baz -> foo'); - } - }); -}); diff --git a/src/legacy/server/plugins/lib/index.js b/src/legacy/server/plugins/lib/index.js deleted file mode 100644 index 2329d24498b6b..0000000000000 --- a/src/legacy/server/plugins/lib/index.js +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -export { callPluginHook } from './call_plugin_hook'; -export { Plugin } from './plugin'; diff --git a/src/legacy/server/plugins/lib/plugin.js b/src/legacy/server/plugins/lib/plugin.js deleted file mode 100644 index 48389061199ff..0000000000000 --- a/src/legacy/server/plugins/lib/plugin.js +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { once } from 'lodash'; - -/** - * The server plugin class, used to extend the server - * and add custom behavior. A "scoped" plugin class is - * created by the PluginApi class and provided to plugin - * providers that automatically binds all but the `opts` - * arguments. - * - * @class Plugin - * @param {KbnServer} kbnServer - the KbnServer this plugin - * belongs to. - * @param {PluginDefinition} def - * @param {PluginSpec} spec - */ -export class Plugin { - constructor(kbnServer, spec) { - this.kbnServer = kbnServer; - this.spec = spec; - this.pkg = spec.getPkg(); - this.path = spec.getPath(); - this.id = spec.getId(); - this.version = spec.getVersion(); - this.requiredIds = spec.getRequiredPluginIds() || []; - this.externalPreInit = spec.getPreInitHandler(); - this.externalInit = spec.getInitHandler(); - this.externalPostInit = spec.getPostInitHandler(); - this.enabled = spec.isEnabled(kbnServer.config); - this.configPrefix = spec.getConfigPrefix(); - this.publicDir = spec.getPublicDir(); - - this.preInit = once(this.preInit); - this.init = once(this.init); - this.postInit = once(this.postInit); - } - - async preInit() { - if (this.externalPreInit) { - return await this.externalPreInit(this.kbnServer.server); - } - } - - async init() { - const { id, version, kbnServer, configPrefix } = this; - const { config } = kbnServer; - - // setup the hapi register function and get on with it - const register = async (server, options) => { - this._server = server; - this._options = options; - - server.logWithMetadata(['plugins', 'debug'], `Initializing plugin ${this.toString()}`, { - plugin: this, - }); - - if (this.publicDir) { - server.newPlatform.__internals.http.registerStaticDir( - `/plugins/${id}/{path*}`, - this.publicDir - ); - } - - if (this.externalInit) { - await this.externalInit(server, options); - } - }; - - await kbnServer.server.register({ - plugin: { register, name: id, version }, - options: config.has(configPrefix) ? config.get(configPrefix) : null, - }); - } - - async postInit() { - if (this.externalPostInit) { - return await this.externalPostInit(this.kbnServer.server); - } - } - - getServer() { - return this._server; - } - - getOptions() { - return this._options; - } - - toJSON() { - return this.pkg; - } - - toString() { - return `${this.id}@${this.version}`; - } -} diff --git a/src/legacy/server/plugins/scan_mixin.js b/src/legacy/server/plugins/scan_mixin.js deleted file mode 100644 index 89ebaf920d9d1..0000000000000 --- a/src/legacy/server/plugins/scan_mixin.js +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -import { Plugin } from './lib'; - -export async function scanMixin(kbnServer) { - kbnServer.plugins = kbnServer.pluginSpecs.map((spec) => new Plugin(kbnServer, spec)); -} diff --git a/src/legacy/server/plugins/wait_for_plugins_init.js b/src/legacy/server/plugins/wait_for_plugins_init.js deleted file mode 100644 index 144eb5ef803cc..0000000000000 --- a/src/legacy/server/plugins/wait_for_plugins_init.js +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -/** - * Tracks the individual queue for each kbnServer, rather than attaching - * it to the kbnServer object via a property or something - * @type {WeakMap} - */ -const queues = new WeakMap(); - -export function waitForInitSetupMixin(kbnServer) { - queues.set(kbnServer, []); - - kbnServer.afterPluginsInit = function (callback) { - const queue = queues.get(kbnServer); - - if (!queue) { - throw new Error( - 'Plugins have already initialized. Only use this method for setup logic that must wait for plugins to initialize.' - ); - } - - queue.push(callback); - }; -} - -export async function waitForInitResolveMixin(kbnServer, server, config) { - const queue = queues.get(kbnServer); - queues.set(kbnServer, null); - - // only actually call the callbacks if we are really initializing - if (config.get('plugins.initialize')) { - for (const cb of queue) { - await cb(); - } - } -} diff --git a/src/legacy/types.ts b/src/legacy/types.ts deleted file mode 100644 index 43c9ac79538b1..0000000000000 --- a/src/legacy/types.ts +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -export * from './plugin_discovery/types'; diff --git a/src/legacy/ui/__tests__/fixtures/plugin_async_foo/index.js b/src/legacy/ui/__tests__/fixtures/plugin_async_foo/index.js deleted file mode 100644 index afe618c6d3d9c..0000000000000 --- a/src/legacy/ui/__tests__/fixtures/plugin_async_foo/index.js +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import Bluebird from 'bluebird'; - -export default (kibana) => - new kibana.Plugin({ - config(Joi) { - return Joi.object() - .keys({ - enabled: Joi.boolean().default(true), - delay: Joi.number().required(), - shared: Joi.string(), - }) - .default(); - }, - - uiExports: { - async injectDefaultVars(server, options) { - await Bluebird.delay(options.delay); - return { shared: options.shared }; - }, - }, - }); diff --git a/src/legacy/ui/__tests__/fixtures/plugin_async_foo/package.json b/src/legacy/ui/__tests__/fixtures/plugin_async_foo/package.json deleted file mode 100644 index fc1c8d8088f1b..0000000000000 --- a/src/legacy/ui/__tests__/fixtures/plugin_async_foo/package.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "name": "plugin_async_foo", - "version": "kibana" -} diff --git a/src/legacy/ui/__tests__/fixtures/plugin_bar/index.js b/src/legacy/ui/__tests__/fixtures/plugin_bar/index.js deleted file mode 100644 index 975a1dc7c92e7..0000000000000 --- a/src/legacy/ui/__tests__/fixtures/plugin_bar/index.js +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -export default (kibana) => - new kibana.Plugin({ - config(Joi) { - return Joi.object() - .keys({ - enabled: Joi.boolean().default(true), - shared: Joi.string(), - }) - .default(); - }, - - uiExports: { - injectDefaultVars(server, options) { - return { shared: options.shared }; - }, - }, - }); diff --git a/src/legacy/ui/__tests__/fixtures/plugin_bar/package.json b/src/legacy/ui/__tests__/fixtures/plugin_bar/package.json deleted file mode 100644 index f79b807990dca..0000000000000 --- a/src/legacy/ui/__tests__/fixtures/plugin_bar/package.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "name": "plugin_bar", - "version": "kibana" -} diff --git a/src/legacy/ui/__tests__/fixtures/plugin_foo/index.js b/src/legacy/ui/__tests__/fixtures/plugin_foo/index.js deleted file mode 100644 index 975a1dc7c92e7..0000000000000 --- a/src/legacy/ui/__tests__/fixtures/plugin_foo/index.js +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -export default (kibana) => - new kibana.Plugin({ - config(Joi) { - return Joi.object() - .keys({ - enabled: Joi.boolean().default(true), - shared: Joi.string(), - }) - .default(); - }, - - uiExports: { - injectDefaultVars(server, options) { - return { shared: options.shared }; - }, - }, - }); diff --git a/src/legacy/ui/__tests__/fixtures/plugin_foo/package.json b/src/legacy/ui/__tests__/fixtures/plugin_foo/package.json deleted file mode 100644 index c1b7ddd35c9a2..0000000000000 --- a/src/legacy/ui/__tests__/fixtures/plugin_foo/package.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "name": "plugin_foo", - "version": "kibana" -} diff --git a/src/legacy/ui/__tests__/fixtures/test_app/index.js b/src/legacy/ui/__tests__/fixtures/test_app/index.js deleted file mode 100644 index 3eddefd618ce0..0000000000000 --- a/src/legacy/ui/__tests__/fixtures/test_app/index.js +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -export default (kibana) => - new kibana.Plugin({ - uiExports: { - app: { - name: 'test_app', - main: 'plugins/test_app/index.js', - }, - - injectDefaultVars() { - return { - from_defaults: true, - }; - }, - }, - init(server) { - server.injectUiAppVars('test_app', () => ({ - from_test_app: true, - })); - }, - }); diff --git a/src/legacy/ui/__tests__/fixtures/test_app/package.json b/src/legacy/ui/__tests__/fixtures/test_app/package.json deleted file mode 100644 index 3aeb029e4f4cc..0000000000000 --- a/src/legacy/ui/__tests__/fixtures/test_app/package.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "name": "test_app", - "version": "kibana" -} diff --git a/src/legacy/ui/apm/index.js b/src/legacy/ui/apm/index.js index c43b7b01d1159..e58f6fb73320d 100644 --- a/src/legacy/ui/apm/index.js +++ b/src/legacy/ui/apm/index.js @@ -17,18 +17,10 @@ * under the License. */ -import { getConfig, isKibanaDistributable } from '../../../apm'; +import { getConfig } from '../../../apm'; import agent from 'elastic-apm-node'; -const apmEnabled = !isKibanaDistributable && process.env.ELASTIC_APM_ACTIVE === 'true'; - -export function apmImport() { - return apmEnabled ? 'import { init } from "@elastic/apm-rum"' : ''; -} - -export function apmInit(config) { - return apmEnabled ? `init(${config})` : ''; -} +const apmEnabled = getConfig()?.active; export function getApmConfig(requestPath) { if (!apmEnabled) { @@ -36,11 +28,9 @@ export function getApmConfig(requestPath) { } const config = { ...getConfig('kibana-frontend'), - ...{ - active: true, - pageLoadTransactionName: requestPath, - }, + pageLoadTransactionName: requestPath, }; + /** * Get current active backend transaction to make distrubuted tracing * work for rendering the app diff --git a/src/legacy/ui/index.js b/src/legacy/ui/index.js index 05373fa5d1964..5c06cb4677347 100644 --- a/src/legacy/ui/index.js +++ b/src/legacy/ui/index.js @@ -18,4 +18,3 @@ */ export { uiMixin } from './ui_mixin'; -export { collectUiExports } from './ui_exports'; diff --git a/src/legacy/ui/ui_exports/README.md b/src/legacy/ui/ui_exports/README.md deleted file mode 100644 index 7fb117b1c25b9..0000000000000 --- a/src/legacy/ui/ui_exports/README.md +++ /dev/null @@ -1,95 +0,0 @@ -# UI Exports - -When defining a Plugin, the `uiExports` key can be used to define a map of export types to values that will be used to configure the UI system. A common use for `uiExports` is `uiExports.app`, which defines the configuration of a [`UiApp`][UiApp] and teaches the UI System how to render, bundle and tell the user about an application. - - -## `collectUiExports(pluginSpecs): { [type: string]: any }` - -This function produces the object commonly found at `kbnServer.uiExports`. This object is created by calling `collectPluginExports()` with a standard set of export type reducers and defaults for the UI System. - -### export type reducers - -The [`ui_export_types` module][UiExportTypes] defines the reducer used for each uiExports key (or `type`). The name of every export in [./ui_export_types/index.js][UiExportTypes] is a key that plugins can define in their `uiExports` specification and the value of those exports are reducers that `collectPluginExports()` will call to produce the merged result of all export specs. - -### example - UiApps - -Plugin authors can define a new UiApp in their plugin specification like so: - -```js -// a single app export -export default function (kibana) { - return new kibana.Plugin({ - //... - uiExports: { - app: { - // uiApp spec options go here - } - } - }) -} - -// apps can also export multiple apps -export default function (kibana) { - return new kibana.Plugin({ - //... - uiExports: { - apps: [ - { /* uiApp spec options */ }, - { /* second uiApp spec options */ }, - ] - } - }) -} -``` - -To handle this export type, the [ui_export_types][UiExportTypes] module exports two reducers, one named `app` and the other `apps`. - -```js -export const app = ... -export const apps = ... -``` - -These reducers are defined in [`ui_export_types/ui_apps`][UiAppExportType] and have the exact same definition: - -```js -// `wrap()` produces a reducer by wrapping a base reducer with modifiers. -// All but the last argument are modifiers that take a reducer and return -// an alternate reducer to use in it's place. -// -// Most wrappers call their target reducer with slightly different -// arguments. This allows composing standard reducer modifications for -// reuse, consistency, and easy reference (once you get the hang of it). -wrap( - // calls the next reducer with the `type` set to `uiAppSpecs`, ignoring - // the key the plugin author used to define this spec ("app" or "apps" - // in this example) - alias('uiAppSpecs'), - - // calls the next reducer with the `spec` set to the result of calling - // `applySpecDefaults(spec, type, pluginSpec)` which merges some defaults - // from the `PluginSpec` because we want uiAppSpecs to be useful individually - mapSpec(applySpecDefaults), - - // writes this spec to `acc[type]` (`acc.uiAppSpecs` in this example since - // the type was set to `uiAppSpecs` by `alias()`). It does this by concatenating - // the current value and the spec into an array. If either item is already - // an array its items are added to the result individually. If either item - // is undefined it is ignored. - // - // NOTE: since flatConcatAtType is last it isn't a wrapper, it's - // just a normal reducer - flatConcatAtType -) -``` - -This reducer format was chosen so that it will be easier to look back at these reducers and see that `app` and `apps` export specs are written to `kbnServer.uiExports.uiAppSpecs`, with defaults applied, in an array. - -### defaults - -The [`ui_exports/ui_export_defaults`][UiExportDefaults] module defines the default shape of the uiExports object produced by `collectUiExports()`. The defaults generally describe the `uiExports` from the UI System itself, like default visTypes and such. - -[UiExportDefaults]: ./ui_export_defaults.js "uiExport defaults definition" -[UiExportTypes]: ./ui_export_types/index.js "Index of default ui_export_types module" -[UiAppExportType]: ./ui_export_types/ui_apps.js "UiApp extension type definition" -[PluginSpec]: ../../plugin_discovery/plugin_spec/plugin_spec.js "PluginSpec class definition" -[PluginDiscovery]: '../../plugin_discovery' "plugin_discovery module" \ No newline at end of file diff --git a/src/legacy/ui/ui_exports/collect_ui_exports.ts b/src/legacy/ui/ui_exports/collect_ui_exports.ts deleted file mode 100644 index edb2a11dc0527..0000000000000 --- a/src/legacy/ui/ui_exports/collect_ui_exports.ts +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { LegacyUiExports } from '../../../core/server'; - -// @ts-ignore -import { UI_EXPORT_DEFAULTS } from './ui_export_defaults'; -// @ts-ignore -import * as uiExportTypeReducers from './ui_export_types'; -// @ts-ignore -import { reduceExportSpecs } from '../../plugin_discovery'; - -export function collectUiExports(pluginSpecs: unknown[]): LegacyUiExports { - return reduceExportSpecs(pluginSpecs, uiExportTypeReducers, UI_EXPORT_DEFAULTS); -} diff --git a/src/legacy/ui/ui_exports/index.js b/src/legacy/ui/ui_exports/index.js deleted file mode 100644 index 56db698dc7b03..0000000000000 --- a/src/legacy/ui/ui_exports/index.js +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -export { collectUiExports } from './collect_ui_exports'; diff --git a/src/legacy/ui/ui_exports/ui_export_defaults.js b/src/legacy/ui/ui_exports/ui_export_defaults.js deleted file mode 100644 index 227954155ce88..0000000000000 --- a/src/legacy/ui/ui_exports/ui_export_defaults.js +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -export const UI_EXPORT_DEFAULTS = {}; diff --git a/src/legacy/ui/ui_exports/ui_export_types/index.js b/src/legacy/ui/ui_exports/ui_export_types/index.js deleted file mode 100644 index 9ff6a53f4afb9..0000000000000 --- a/src/legacy/ui/ui_exports/ui_export_types/index.js +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -export { injectDefaultVars, replaceInjectedVars } from './modify_injected_vars'; - -export { - mappings, - migrations, - savedObjectSchemas, - savedObjectsManagement, - validations, -} from './saved_object'; - -export { taskDefinitions } from './task_definitions'; - -export { link, links } from './ui_nav_links'; - -export { uiSettingDefaults } from './ui_settings'; - -export { unknown } from './unknown'; diff --git a/src/legacy/ui/ui_exports/ui_export_types/modify_injected_vars.js b/src/legacy/ui/ui_exports/ui_export_types/modify_injected_vars.js deleted file mode 100644 index 4bb9f350bd959..0000000000000 --- a/src/legacy/ui/ui_exports/ui_export_types/modify_injected_vars.js +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { flatConcatAtType } from './reduce'; -import { wrap, alias, mapSpec } from './modify_reduce'; - -export const replaceInjectedVars = wrap(alias('injectedVarsReplacers'), flatConcatAtType); - -export const injectDefaultVars = wrap( - alias('defaultInjectedVarProviders'), - mapSpec((spec, type, pluginSpec) => ({ - pluginSpec, - fn: spec, - })), - flatConcatAtType -); diff --git a/src/legacy/ui/ui_exports/ui_export_types/modify_reduce/alias.js b/src/legacy/ui/ui_exports/ui_export_types/modify_reduce/alias.js deleted file mode 100644 index a894e59a03c81..0000000000000 --- a/src/legacy/ui/ui_exports/ui_export_types/modify_reduce/alias.js +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -/** - * Creates a reducer wrapper which, when called with a reducer, creates a new - * reducer that replaces the `type` value with `newType` before delegating to - * the wrapped reducer - * @param {String} newType - * @return {Function} - */ -export const alias = (newType) => (next) => (acc, spec, type, pluginSpec) => - next(acc, spec, newType, pluginSpec); diff --git a/src/legacy/ui/ui_exports/ui_export_types/modify_reduce/debug.js b/src/legacy/ui/ui_exports/ui_export_types/modify_reduce/debug.js deleted file mode 100644 index c40bca59fe14c..0000000000000 --- a/src/legacy/ui/ui_exports/ui_export_types/modify_reduce/debug.js +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { mapSpec } from './map_spec'; - -/** - * Reducer wrapper which, replaces the `spec` with the details about the definition - * of that spec - * @type {Function} - */ -export const debug = mapSpec((spec, type, pluginSpec) => ({ - spec, - type, - pluginSpec, -})); diff --git a/src/legacy/ui/ui_exports/ui_export_types/modify_reduce/index.js b/src/legacy/ui/ui_exports/ui_export_types/modify_reduce/index.js deleted file mode 100644 index 54c81fefdd08a..0000000000000 --- a/src/legacy/ui/ui_exports/ui_export_types/modify_reduce/index.js +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -export { alias } from './alias'; -export { debug } from './debug'; -export { mapSpec } from './map_spec'; -export { wrap } from './wrap'; -export { uniqueKeys } from './unique_keys'; diff --git a/src/legacy/ui/ui_exports/ui_export_types/modify_reduce/map_spec.js b/src/legacy/ui/ui_exports/ui_export_types/modify_reduce/map_spec.js deleted file mode 100644 index 5970c45e7445e..0000000000000 --- a/src/legacy/ui/ui_exports/ui_export_types/modify_reduce/map_spec.js +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -/** - * Creates a reducer wrapper which, when called with a reducer, creates a new - * reducer that replaces the `specs` value with the result of calling - * `mapFn(spec, type, pluginSpec)` before delegating to the wrapped - * reducer - * @param {Function} mapFn receives `(specs, type, pluginSpec)` - * @return {Function} - */ -export const mapSpec = (mapFn) => (next) => (acc, spec, type, pluginSpec) => - next(acc, mapFn(spec, type, pluginSpec), type, pluginSpec); diff --git a/src/legacy/ui/ui_exports/ui_export_types/modify_reduce/unique_keys.js b/src/legacy/ui/ui_exports/ui_export_types/modify_reduce/unique_keys.js deleted file mode 100644 index dedcd057b09e3..0000000000000 --- a/src/legacy/ui/ui_exports/ui_export_types/modify_reduce/unique_keys.js +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -const pluginId = (pluginSpec) => (pluginSpec.id ? pluginSpec.id() : pluginSpec.getId()); - -export const uniqueKeys = (sourceType) => (next) => (acc, spec, type, pluginSpec) => { - const duplicates = Object.keys(spec).filter((key) => acc[type] && acc[type].hasOwnProperty(key)); - - if (duplicates.length) { - throw new Error( - `${pluginId(pluginSpec)} defined duplicate ${sourceType || type} values: ${duplicates}` - ); - } - - return next(acc, spec, type, pluginSpec); -}; diff --git a/src/legacy/ui/ui_exports/ui_export_types/modify_reduce/wrap.js b/src/legacy/ui/ui_exports/ui_export_types/modify_reduce/wrap.js deleted file mode 100644 index f84d83ed7c845..0000000000000 --- a/src/legacy/ui/ui_exports/ui_export_types/modify_reduce/wrap.js +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -/** - * Wrap a function with any number of wrappers. Wrappers - * are functions that take a reducer and return a reducer - * that should be called in its place. The wrappers will - * be called in reverse order for setup and then in the - * order they are defined when the resulting reducer is - * executed. - * - * const reducer = wrap( - * next => (acc) => acc[1] = 'a', - * next => (acc) => acc[1] = 'b', - * next => (acc) => acc[1] = 'c' - * ) - * - * reducer('foo') //=> 'fco' - * - * @param {Function} ...wrappers - * @param {Function} reducer - * @return {Function} - */ -export function wrap(...args) { - const reducer = args[args.length - 1]; - const wrappers = args.slice(0, -1); - - return wrappers.reverse().reduce((acc, wrapper) => wrapper(acc), reducer); -} diff --git a/src/legacy/ui/ui_exports/ui_export_types/reduce/flat_concat_at_type.js b/src/legacy/ui/ui_exports/ui_export_types/reduce/flat_concat_at_type.js deleted file mode 100644 index 5fcbcac463392..0000000000000 --- a/src/legacy/ui/ui_exports/ui_export_types/reduce/flat_concat_at_type.js +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { createTypeReducer, flatConcat } from './lib'; - -/** - * Reducer that merges two values concatenating all values - * into a flattened array - * @param {Any} [initial] - * @return {Function} - */ -export const flatConcatAtType = createTypeReducer(flatConcat); diff --git a/src/legacy/ui/ui_exports/ui_export_types/reduce/flat_concat_values_at_type.js b/src/legacy/ui/ui_exports/ui_export_types/reduce/flat_concat_values_at_type.js deleted file mode 100644 index 229c5be24aac5..0000000000000 --- a/src/legacy/ui/ui_exports/ui_export_types/reduce/flat_concat_values_at_type.js +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { createTypeReducer, flatConcat, mergeWith } from './lib'; - -/** - * Reducer that merges specs by concatenating the values of - * all keys in accumulator and spec with the same logic as concat - * @param {[type]} initial [description] - * @return {[type]} [description] - */ -export const flatConcatValuesAtType = createTypeReducer((objectA, objectB) => - mergeWith(objectA || {}, objectB || {}, flatConcat) -); diff --git a/src/legacy/ui/ui_exports/ui_export_types/reduce/index.js b/src/legacy/ui/ui_exports/ui_export_types/reduce/index.js deleted file mode 100644 index 7dc1ba60fb3cb..0000000000000 --- a/src/legacy/ui/ui_exports/ui_export_types/reduce/index.js +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -export { mergeAtType } from './merge_at_type'; -export { flatConcatValuesAtType } from './flat_concat_values_at_type'; -export { flatConcatAtType } from './flat_concat_at_type'; diff --git a/src/legacy/ui/ui_exports/ui_export_types/reduce/lib/create_type_reducer.js b/src/legacy/ui/ui_exports/ui_export_types/reduce/lib/create_type_reducer.js deleted file mode 100644 index bf4793c208308..0000000000000 --- a/src/legacy/ui/ui_exports/ui_export_types/reduce/lib/create_type_reducer.js +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -/** - * Creates a reducer that reduces the values within `acc[type]` by calling - * reducer with signature: - * - * reducer(acc[type], spec, type, pluginSpec) - * - * @param {Function} reducer - * @return {Function} - */ -export const createTypeReducer = (reducer) => (acc, spec, type, pluginSpec) => ({ - ...acc, - [type]: reducer(acc[type], spec, type, pluginSpec), -}); diff --git a/src/legacy/ui/ui_exports/ui_export_types/reduce/lib/flat_concat.js b/src/legacy/ui/ui_exports/ui_export_types/reduce/lib/flat_concat.js deleted file mode 100644 index 1337c8a85d5b4..0000000000000 --- a/src/legacy/ui/ui_exports/ui_export_types/reduce/lib/flat_concat.js +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -/** - * Concatenate two values into a single array, ignoring either - * value if it is undefined and flattening the value if it is an array - * @param {Array|T} a - * @param {Array} b - * @return {Array} - */ -export const flatConcat = (a, b) => [].concat(a === undefined ? [] : a, b === undefined ? [] : b); diff --git a/src/legacy/ui/ui_exports/ui_export_types/reduce/lib/index.js b/src/legacy/ui/ui_exports/ui_export_types/reduce/lib/index.js deleted file mode 100644 index e4281caebe245..0000000000000 --- a/src/legacy/ui/ui_exports/ui_export_types/reduce/lib/index.js +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -export { flatConcat } from './flat_concat'; -export { mergeWith } from './merge_with'; -export { createTypeReducer } from './create_type_reducer'; diff --git a/src/legacy/ui/ui_exports/ui_export_types/reduce/lib/merge_with.js b/src/legacy/ui/ui_exports/ui_export_types/reduce/lib/merge_with.js deleted file mode 100644 index 6c7d31e6fd74d..0000000000000 --- a/src/legacy/ui/ui_exports/ui_export_types/reduce/lib/merge_with.js +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -const uniqueConcat = (arrayA, arrayB) => - arrayB.reduce((acc, key) => (acc.includes(key) ? acc : acc.concat(key)), arrayA); - -/** - * Assign the keys from both objA and objB to target after passing the - * current and new value through merge as `(target[key], source[key])` - * @param {Object} objA - * @param {Object} objB - * @param {Function} merge - * @return {Object} target - */ -export function mergeWith(objA, objB, merge) { - const target = {}; - const keys = uniqueConcat(Object.keys(objA), Object.keys(objB)); - for (const key of keys) { - target[key] = merge(objA[key], objB[key]); - } - return target; -} diff --git a/src/legacy/ui/ui_exports/ui_export_types/reduce/merge_at_type.js b/src/legacy/ui/ui_exports/ui_export_types/reduce/merge_at_type.js deleted file mode 100644 index 4f5a501253851..0000000000000 --- a/src/legacy/ui/ui_exports/ui_export_types/reduce/merge_at_type.js +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { createTypeReducer } from './lib'; - -export const mergeAtType = createTypeReducer((a, b) => ({ - ...a, - ...b, -})); diff --git a/src/legacy/ui/ui_exports/ui_export_types/saved_object.js b/src/legacy/ui/ui_exports/ui_export_types/saved_object.js deleted file mode 100644 index be6898d3e642c..0000000000000 --- a/src/legacy/ui/ui_exports/ui_export_types/saved_object.js +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { flatConcatAtType, mergeAtType } from './reduce'; -import { alias, mapSpec, uniqueKeys, wrap } from './modify_reduce'; - -// mapping types -export const mappings = wrap( - alias('savedObjectMappings'), - mapSpec((spec, type, pluginSpec) => ({ - pluginId: pluginSpec.getId(), - properties: spec, - })), - flatConcatAtType -); - -const pluginId = (pluginSpec) => (pluginSpec.id ? pluginSpec.id() : pluginSpec.getId()); - -// Combines the `migrations` property of each plugin, -// ensuring that properties are unique across plugins -// and has migrations defined where the mappings are defined. -// See saved_objects/migrations for more details. -export const migrations = wrap( - alias('savedObjectMigrations'), - (next) => (acc, spec, type, pluginSpec) => { - const mappings = pluginSpec.getExportSpecs().mappings || {}; - const invalidMigrationTypes = Object.keys(spec).filter((type) => !mappings[type]); - if (invalidMigrationTypes.length) { - throw new Error( - 'Migrations and mappings must be defined together in the uiExports of a single plugin. ' + - `${pluginId(pluginSpec)} defines migrations for types ${invalidMigrationTypes.join( - ', ' - )} but does not define their mappings.` - ); - } - return next(acc, spec, type, pluginSpec); - }, - uniqueKeys(), - mergeAtType -); - -export const savedObjectSchemas = wrap(uniqueKeys(), mergeAtType); - -export const savedObjectsManagement = wrap(uniqueKeys(), mergeAtType); - -// Combines the `validations` property of each plugin, -// ensuring that properties are unique across plugins. -// See saved_objects/validation for more details. -export const validations = wrap(alias('savedObjectValidations'), uniqueKeys(), mergeAtType); diff --git a/src/legacy/ui/ui_exports/ui_export_types/task_definitions.js b/src/legacy/ui/ui_exports/ui_export_types/task_definitions.js deleted file mode 100644 index 8a0ed85d86f3e..0000000000000 --- a/src/legacy/ui/ui_exports/ui_export_types/task_definitions.js +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { mergeAtType } from './reduce'; -import { alias, wrap, uniqueKeys } from './modify_reduce'; - -// How plugins define tasks that the task manager can run. -export const taskDefinitions = wrap(alias('taskDefinitions'), uniqueKeys(), mergeAtType); diff --git a/src/legacy/ui/ui_exports/ui_export_types/ui_nav_links.js b/src/legacy/ui/ui_exports/ui_export_types/ui_nav_links.js deleted file mode 100644 index 34aff7463a249..0000000000000 --- a/src/legacy/ui/ui_exports/ui_export_types/ui_nav_links.js +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { flatConcatAtType } from './reduce'; -import { wrap, alias } from './modify_reduce'; - -export const links = wrap(alias('navLinkSpecs'), flatConcatAtType); -export const link = wrap(alias('navLinkSpecs'), flatConcatAtType); diff --git a/src/legacy/ui/ui_exports/ui_export_types/ui_settings.js b/src/legacy/ui/ui_exports/ui_export_types/ui_settings.js deleted file mode 100644 index 8d88490579c21..0000000000000 --- a/src/legacy/ui/ui_exports/ui_export_types/ui_settings.js +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { mergeAtType } from './reduce'; -import { wrap, uniqueKeys } from './modify_reduce'; - -export const uiSettingDefaults = wrap(uniqueKeys(), mergeAtType); diff --git a/src/legacy/ui/ui_exports/ui_export_types/unknown.js b/src/legacy/ui/ui_exports/ui_export_types/unknown.js deleted file mode 100644 index a12a514d2e6bf..0000000000000 --- a/src/legacy/ui/ui_exports/ui_export_types/unknown.js +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { flatConcatAtType } from './reduce'; -import { wrap, alias, debug } from './modify_reduce'; - -export const unknown = wrap(debug, alias('unknown'), flatConcatAtType); diff --git a/src/legacy/ui/ui_render/ui_render_mixin.js b/src/legacy/ui/ui_render/ui_render_mixin.js index e3b7c1e0c3ff9..2983dbbc28667 100644 --- a/src/legacy/ui/ui_render/ui_render_mixin.js +++ b/src/legacy/ui/ui_render/ui_render_mixin.js @@ -67,115 +67,108 @@ export function uiRenderMixin(kbnServer, server, config) { }, }); - // register the bootstrap.js route after plugins are initialized so that we can - // detect if any default auth strategies were registered - kbnServer.afterPluginsInit(() => { - const authEnabled = !!server.auth.settings.default; - - server.route({ - path: '/bootstrap.js', - method: 'GET', - config: { - tags: ['api'], - auth: authEnabled ? { mode: 'try' } : false, - }, - async handler(request, h) { - const soClient = kbnServer.newPlatform.start.core.savedObjects.getScopedClient( - KibanaRequest.from(request) - ); - const uiSettings = kbnServer.newPlatform.start.core.uiSettings.asScopedToClient(soClient); - - const darkMode = - !authEnabled || request.auth.isAuthenticated - ? await uiSettings.get('theme:darkMode') - : false; - - const themeVersion = - !authEnabled || request.auth.isAuthenticated - ? await uiSettings.get('theme:version') - : 'v7'; - - const themeTag = `${themeVersion === 'v7' ? 'v7' : 'v8'}${darkMode ? 'dark' : 'light'}`; - - const buildHash = server.newPlatform.env.packageInfo.buildNum; - const basePath = config.get('server.basePath'); - - const regularBundlePath = `${basePath}/${buildHash}/bundles`; - - const styleSheetPaths = [ - `${regularBundlePath}/kbn-ui-shared-deps/${UiSharedDeps.baseCssDistFilename}`, - ...(darkMode - ? [ - themeVersion === 'v7' - ? `${regularBundlePath}/kbn-ui-shared-deps/${UiSharedDeps.darkCssDistFilename}` - : `${regularBundlePath}/kbn-ui-shared-deps/${UiSharedDeps.darkV8CssDistFilename}`, - `${basePath}/node_modules/@kbn/ui-framework/dist/kui_dark.css`, - `${basePath}/ui/legacy_dark_theme.css`, - ] - : [ - themeVersion === 'v7' - ? `${regularBundlePath}/kbn-ui-shared-deps/${UiSharedDeps.lightCssDistFilename}` - : `${regularBundlePath}/kbn-ui-shared-deps/${UiSharedDeps.lightV8CssDistFilename}`, - `${basePath}/node_modules/@kbn/ui-framework/dist/kui_light.css`, - `${basePath}/ui/legacy_light_theme.css`, - ]), - ]; - - const kpUiPlugins = kbnServer.newPlatform.__internals.uiPlugins; - const kpPluginPublicPaths = new Map(); - const kpPluginBundlePaths = new Set(); - - // recursively iterate over the kpUiPlugin ids and their required bundles - // to populate kpPluginPublicPaths and kpPluginBundlePaths - (function readKpPlugins(ids) { - for (const id of ids) { - if (kpPluginPublicPaths.has(id)) { - continue; - } - - kpPluginPublicPaths.set(id, `${regularBundlePath}/plugin/${id}/`); - kpPluginBundlePaths.add(`${regularBundlePath}/plugin/${id}/${id}.plugin.js`); - readKpPlugins(kpUiPlugins.internal.get(id).requiredBundles); + const authEnabled = !!server.auth.settings.default; + server.route({ + path: '/bootstrap.js', + method: 'GET', + config: { + tags: ['api'], + auth: authEnabled ? { mode: 'try' } : false, + }, + async handler(request, h) { + const soClient = kbnServer.newPlatform.start.core.savedObjects.getScopedClient( + KibanaRequest.from(request) + ); + const uiSettings = kbnServer.newPlatform.start.core.uiSettings.asScopedToClient(soClient); + + const darkMode = + !authEnabled || request.auth.isAuthenticated + ? await uiSettings.get('theme:darkMode') + : false; + + const themeVersion = + !authEnabled || request.auth.isAuthenticated ? await uiSettings.get('theme:version') : 'v7'; + + const themeTag = `${themeVersion === 'v7' ? 'v7' : 'v8'}${darkMode ? 'dark' : 'light'}`; + + const buildHash = server.newPlatform.env.packageInfo.buildNum; + const basePath = config.get('server.basePath'); + + const regularBundlePath = `${basePath}/${buildHash}/bundles`; + + const styleSheetPaths = [ + `${regularBundlePath}/kbn-ui-shared-deps/${UiSharedDeps.baseCssDistFilename}`, + ...(darkMode + ? [ + themeVersion === 'v7' + ? `${regularBundlePath}/kbn-ui-shared-deps/${UiSharedDeps.darkCssDistFilename}` + : `${regularBundlePath}/kbn-ui-shared-deps/${UiSharedDeps.darkV8CssDistFilename}`, + `${basePath}/node_modules/@kbn/ui-framework/dist/kui_dark.css`, + `${basePath}/ui/legacy_dark_theme.css`, + ] + : [ + themeVersion === 'v7' + ? `${regularBundlePath}/kbn-ui-shared-deps/${UiSharedDeps.lightCssDistFilename}` + : `${regularBundlePath}/kbn-ui-shared-deps/${UiSharedDeps.lightV8CssDistFilename}`, + `${basePath}/node_modules/@kbn/ui-framework/dist/kui_light.css`, + `${basePath}/ui/legacy_light_theme.css`, + ]), + ]; + + const kpUiPlugins = kbnServer.newPlatform.__internals.uiPlugins; + const kpPluginPublicPaths = new Map(); + const kpPluginBundlePaths = new Set(); + + // recursively iterate over the kpUiPlugin ids and their required bundles + // to populate kpPluginPublicPaths and kpPluginBundlePaths + (function readKpPlugins(ids) { + for (const id of ids) { + if (kpPluginPublicPaths.has(id)) { + continue; } - })(kpUiPlugins.public.keys()); - - const jsDependencyPaths = [ - ...UiSharedDeps.jsDepFilenames.map( - (filename) => `${regularBundlePath}/kbn-ui-shared-deps/${filename}` - ), - `${regularBundlePath}/kbn-ui-shared-deps/${UiSharedDeps.jsFilename}`, - - `${regularBundlePath}/core/core.entry.js`, - ...kpPluginBundlePaths, - ]; - - // These paths should align with the bundle routes configured in - // src/optimize/bundles_route/bundles_route.ts - const publicPathMap = JSON.stringify({ - core: `${regularBundlePath}/core/`, - 'kbn-ui-shared-deps': `${regularBundlePath}/kbn-ui-shared-deps/`, - ...Object.fromEntries(kpPluginPublicPaths), - }); - - const bootstrap = new AppBootstrap({ - templateData: { - themeTag, - jsDependencyPaths, - styleSheetPaths, - publicPathMap, - }, - }); - - const body = await bootstrap.getJsFile(); - const etag = await bootstrap.getJsFileHash(); - - return h - .response(body) - .header('cache-control', 'must-revalidate') - .header('content-type', 'application/javascript') - .etag(etag); - }, - }); + + kpPluginPublicPaths.set(id, `${regularBundlePath}/plugin/${id}/`); + kpPluginBundlePaths.add(`${regularBundlePath}/plugin/${id}/${id}.plugin.js`); + readKpPlugins(kpUiPlugins.internal.get(id).requiredBundles); + } + })(kpUiPlugins.public.keys()); + + const jsDependencyPaths = [ + ...UiSharedDeps.jsDepFilenames.map( + (filename) => `${regularBundlePath}/kbn-ui-shared-deps/${filename}` + ), + `${regularBundlePath}/kbn-ui-shared-deps/${UiSharedDeps.jsFilename}`, + + `${regularBundlePath}/core/core.entry.js`, + ...kpPluginBundlePaths, + ]; + + // These paths should align with the bundle routes configured in + // src/optimize/bundles_route/bundles_route.ts + const publicPathMap = JSON.stringify({ + core: `${regularBundlePath}/core/`, + 'kbn-ui-shared-deps': `${regularBundlePath}/kbn-ui-shared-deps/`, + ...Object.fromEntries(kpPluginPublicPaths), + }); + + const bootstrap = new AppBootstrap({ + templateData: { + themeTag, + jsDependencyPaths, + styleSheetPaths, + publicPathMap, + }, + }); + + const body = await bootstrap.getJsFile(); + const etag = await bootstrap.getJsFileHash(); + + return h + .response(body) + .header('cache-control', 'must-revalidate') + .header('content-type', 'application/javascript') + .etag(etag); + }, }); server.route({ @@ -191,19 +184,17 @@ export function uiRenderMixin(kbnServer, server, config) { }); async function renderApp(h) { - const app = { getId: () => 'core' }; const { http } = kbnServer.newPlatform.setup.core; const { savedObjects } = kbnServer.newPlatform.start.core; - const { rendering, legacy } = kbnServer.newPlatform.__internals; + const { rendering } = kbnServer.newPlatform.__internals; const req = KibanaRequest.from(h.request); const uiSettings = kbnServer.newPlatform.start.core.uiSettings.asScopedToClient( savedObjects.getScopedClient(req) ); - const vars = await legacy.getVars(app.getId(), h.request, { + const vars = { apmConfig: getApmConfig(h.request.path), - }); + }; const content = await rendering.render(h.request, uiSettings, { - app, includeUserSettings: true, vars, }); diff --git a/src/plugins/advanced_settings/public/index.ts b/src/plugins/advanced_settings/public/index.ts index db478fa1579e6..0e621e7cd7d1a 100644 --- a/src/plugins/advanced_settings/public/index.ts +++ b/src/plugins/advanced_settings/public/index.ts @@ -17,11 +17,19 @@ * under the License. */ +import React from 'react'; import { PluginInitializerContext } from 'kibana/public'; import { AdvancedSettingsPlugin } from './plugin'; export { AdvancedSettingsSetup, AdvancedSettingsStart } from './types'; export { ComponentRegistry } from './component_registry'; -export { Field } from './management_app/components/field'; + +/** + * Exports the field component as a React.lazy component. We're explicitly naming it lazy here + * so any plugin that would import that can clearly see it's lazy loaded and can only be used + * inside a suspense context. + */ +const LazyField = React.lazy(() => import('./management_app/components/field')); +export { LazyField }; export function plugin(initializerContext: PluginInitializerContext) { return new AdvancedSettingsPlugin(); diff --git a/src/plugins/advanced_settings/public/management_app/_advanced_settings.scss b/src/plugins/advanced_settings/public/management_app/_advanced_settings.scss index 66ae9cca3f83b..fd26677e93894 100644 --- a/src/plugins/advanced_settings/public/management_app/_advanced_settings.scss +++ b/src/plugins/advanced_settings/public/management_app/_advanced_settings.scss @@ -64,3 +64,7 @@ .mgtAdvancedSettingsForm__button { width: 100%; } + +.kbnBody--mgtAdvancedSettingsHasBottomBar .mgtPage__body { + padding-bottom: $euiSizeXL * 2; +} diff --git a/src/plugins/advanced_settings/public/management_app/advanced_settings.tsx b/src/plugins/advanced_settings/public/management_app/advanced_settings.tsx index 8c9e3847844d9..afdd90959eabd 100644 --- a/src/plugins/advanced_settings/public/management_app/advanced_settings.tsx +++ b/src/plugins/advanced_settings/public/management_app/advanced_settings.tsx @@ -121,7 +121,18 @@ export class AdvancedSettingsComponent extends Component< setTimeout(() => { const id = hash.replace('#', ''); const element = document.getElementById(id); - const globalNavOffset = document.getElementById('globalHeaderBars')?.offsetHeight || 0; + + let globalNavOffset = 0; + + const globalNavBars = document + .getElementById('globalHeaderBars') + ?.getElementsByClassName('euiHeader'); + + if (globalNavBars) { + Array.from(globalNavBars).forEach((navBar) => { + globalNavOffset += (navBar as HTMLDivElement).offsetHeight; + }); + } if (element) { element.scrollIntoView(); diff --git a/src/plugins/advanced_settings/public/management_app/components/advanced_settings_voice_announcement/__snapshots__/advanced_settings_voice_announcement.test.tsx.snap b/src/plugins/advanced_settings/public/management_app/components/advanced_settings_voice_announcement/__snapshots__/advanced_settings_voice_announcement.test.tsx.snap index 490e105c18a7d..82c8dcd7f7ea1 100644 --- a/src/plugins/advanced_settings/public/management_app/components/advanced_settings_voice_announcement/__snapshots__/advanced_settings_voice_announcement.test.tsx.snap +++ b/src/plugins/advanced_settings/public/management_app/components/advanced_settings_voice_announcement/__snapshots__/advanced_settings_voice_announcement.test.tsx.snap @@ -3,6 +3,7 @@ exports[`Advanced Settings: Voice Announcement should render announcement 1`] = `
@@ -28,6 +29,7 @@ exports[`Advanced Settings: Voice Announcement should render announcement 1`] = exports[`Advanced Settings: Voice Announcement should render nothing 1`] = `
@@ -35,12 +37,11 @@ exports[`Advanced Settings: Voice Announcement should render nothing 1`] = ` delay={500} > { const filteredOptions = [...filteredSections]; return ( -
+
- + {this.props.queryText ? ( + + ) : ( + + )}
diff --git a/src/plugins/advanced_settings/public/management_app/components/field/__snapshots__/field.test.tsx.snap b/src/plugins/advanced_settings/public/management_app/components/field/__snapshots__/field.test.tsx.snap index 2aabacb061667..19bf9e6d73757 100644 --- a/src/plugins/advanced_settings/public/management_app/components/field/__snapshots__/field.test.tsx.snap +++ b/src/plugins/advanced_settings/public/management_app/components/field/__snapshots__/field.test.tsx.snap @@ -15,7 +15,7 @@ exports[`Field for array setting should render as read only if saving is disable } fullWidth={true} - id="array:test:setting" + id="array:test:setting-group" title={

} fullWidth={true} - id="array:test:setting" + id="array:test:setting-group" title={

} fullWidth={true} - id="array:test:setting" + id="array:test:setting-group" title={

} fullWidth={true} - id="array:test:setting" + id="array:test:setting-group" title={

} fullWidth={true} - id="array:test:setting" + id="array:test:setting-group" title={

Setting is currently not saved.

@@ -364,7 +364,7 @@ exports[`Field for array setting should render user value if there is user value } fullWidth={true} - id="array:test:setting" + id="array:test:setting-group" title={

} fullWidth={true} - id="boolean:test:setting" + id="boolean:test:setting-group" title={

} fullWidth={true} - id="boolean:test:setting" + id="boolean:test:setting-group" title={

} fullWidth={true} - id="boolean:test:setting" + id="boolean:test:setting-group" title={

} fullWidth={true} - id="boolean:test:setting" + id="boolean:test:setting-group" title={

} fullWidth={true} - id="boolean:test:setting" + id="boolean:test:setting-group" title={

Setting is currently not saved.

@@ -807,7 +807,7 @@ exports[`Field for boolean setting should render user value if there is user val } fullWidth={true} - id="boolean:test:setting" + id="boolean:test:setting-group" title={

} fullWidth={true} - id="image:test:setting" + id="image:test:setting-group" title={

} fullWidth={true} - id="image:test:setting" + id="image:test:setting-group" title={

} fullWidth={true} - id="image:test:setting" + id="image:test:setting-group" title={

} fullWidth={true} - id="image:test:setting" + id="image:test:setting-group" title={

} fullWidth={true} - id="image:test:setting" + id="image:test:setting-group" title={

Setting is currently not saved.

@@ -1231,7 +1235,7 @@ exports[`Field for image setting should render user value if there is user value } fullWidth={true} - id="image:test:setting" + id="image:test:setting-group" title={

} fullWidth={true} - id="json:test:setting" + id="json:test:setting-group" title={

} fullWidth={true} - id="json:test:setting" + id="json:test:setting-group" title={

} fullWidth={true} - id="json:test:setting" + id="json:test:setting-group" title={

} fullWidth={true} - id="json:test:setting" + id="json:test:setting-group" title={

} fullWidth={true} - id="json:test:setting" + id="json:test:setting-group" title={

Setting is currently not saved.

@@ -1832,7 +1836,7 @@ exports[`Field for json setting should render user value if there is user value } fullWidth={true} - id="json:test:setting" + id="json:test:setting-group" title={

} fullWidth={true} - id="markdown:test:setting" + id="markdown:test:setting-group" title={

} fullWidth={true} - id="markdown:test:setting" + id="markdown:test:setting-group" title={

} fullWidth={true} - id="markdown:test:setting" + id="markdown:test:setting-group" title={

} fullWidth={true} - id="markdown:test:setting" + id="markdown:test:setting-group" title={

} fullWidth={true} - id="markdown:test:setting" + id="markdown:test:setting-group" title={

Setting is currently not saved.

@@ -2365,7 +2369,7 @@ exports[`Field for markdown setting should render user value if there is user va } fullWidth={true} - id="markdown:test:setting" + id="markdown:test:setting-group" title={

} fullWidth={true} - id="number:test:setting" + id="number:test:setting-group" title={

} fullWidth={true} - id="number:test:setting" + id="number:test:setting-group" title={

} fullWidth={true} - id="number:test:setting" + id="number:test:setting-group" title={

} fullWidth={true} - id="number:test:setting" + id="number:test:setting-group" title={

} fullWidth={true} - id="number:test:setting" + id="number:test:setting-group" title={

Setting is currently not saved.

@@ -2798,7 +2802,7 @@ exports[`Field for number setting should render user value if there is user valu } fullWidth={true} - id="number:test:setting" + id="number:test:setting-group" title={

} fullWidth={true} - id="select:test:setting" + id="select:test:setting-group" title={

} fullWidth={true} - id="select:test:setting" + id="select:test:setting-group" title={

} fullWidth={true} - id="select:test:setting" + id="select:test:setting-group" title={

} fullWidth={true} - id="select:test:setting" + id="select:test:setting-group" title={

} fullWidth={true} - id="select:test:setting" + id="select:test:setting-group" title={

Setting is currently not saved.

@@ -3291,7 +3295,7 @@ exports[`Field for select setting should render user value if there is user valu } fullWidth={true} - id="select:test:setting" + id="select:test:setting-group" title={

} fullWidth={true} - id="string:test:setting" + id="string:test:setting-group" title={

} fullWidth={true} - id="string:test:setting" + id="string:test:setting-group" title={

} fullWidth={true} - id="string:test:setting" + id="string:test:setting-group" title={

} fullWidth={true} - id="string:test:setting" + id="string:test:setting-group" title={

} fullWidth={true} - id="string:test:setting" + id="string:test:setting-group" title={

Setting is currently not saved.

@@ -3720,7 +3724,7 @@ exports[`Field for string setting should render user value if there is user valu } fullWidth={true} - id="string:test:setting" + id="string:test:setting-group" title={

} fullWidth={true} - id="string:test-validation:setting" + id="string:test-validation:setting-group" title={

} fullWidth={true} - id="string:test-validation:setting" + id="string:test-validation:setting-group" title={

} fullWidth={true} - id="string:test-validation:setting" + id="string:test-validation:setting-group" title={

} fullWidth={true} - id="string:test-validation:setting" + id="string:test-validation:setting-group" title={

} fullWidth={true} - id="string:test-validation:setting" + id="string:test-validation:setting-group" title={

Setting is currently not saved.

@@ -4133,7 +4137,7 @@ exports[`Field for stringWithValidation setting should render user value if ther } fullWidth={true} - id="string:test-validation:setting" + id="string:test-validation:setting-group" title={

{ } }; - renderField(id: string, setting: FieldSetting) { + renderField(setting: FieldSetting, ariaDescribedBy?: string) { const { enableSaving, unsavedChanges, loading } = this.props; const { name, @@ -301,10 +299,10 @@ export class Field extends PureComponent { defVal, ariaName, } = setting; - const a11yProps: { [key: string]: string } = unsavedChanges + const a11yProps: { [key: string]: string } = ariaDescribedBy ? { 'aria-label': ariaName, - 'aria-describedby': id, + 'aria-describedby': ariaDescribedBy, } : { 'aria-label': ariaName, @@ -370,6 +368,7 @@ export class Field extends PureComponent { ref={this.changeImageForm} fullWidth data-test-subj={`advancedSetting-editField-${name}`} + aria-label={name} /> ); } @@ -669,11 +668,12 @@ export class Field extends PureComponent { // eslint-disable-next-line @typescript-eslint/naming-convention 'mgtAdvancedSettings__field--invalid': isInvalid, }); - const id = setting.name; + const groupId = `${setting.name}-group`; + const unsavedId = `${setting.name}-unsaved`; return ( { fullWidth > <> - {this.renderField(id, setting)} + {this.renderField(setting, unsavedChanges ? `${groupId} ${unsavedId}` : undefined)} {unsavedChanges && ( -

+

{unsavedChanges.error ? unsavedChanges.error : i18n.translate('advancedSettings.field.settingIsUnsaved', { diff --git a/src/plugins/advanced_settings/public/management_app/components/field/index.ts b/src/plugins/advanced_settings/public/management_app/components/field/index.ts index d1b9b34515532..c486dc96bfc33 100644 --- a/src/plugins/advanced_settings/public/management_app/components/field/index.ts +++ b/src/plugins/advanced_settings/public/management_app/components/field/index.ts @@ -18,3 +18,6 @@ */ export { Field, getEditableValue } from './field'; + +// eslint-disable-next-line import/no-default-export +export { Field as default } from './field'; diff --git a/src/plugins/advanced_settings/public/management_app/components/form/__snapshots__/form.test.tsx.snap b/src/plugins/advanced_settings/public/management_app/components/form/__snapshots__/form.test.tsx.snap index e38ccb6866ab6..ebebf49c5213f 100644 --- a/src/plugins/advanced_settings/public/management_app/components/form/__snapshots__/form.test.tsx.snap +++ b/src/plugins/advanced_settings/public/management_app/components/form/__snapshots__/form.test.tsx.snap @@ -18,6 +18,32 @@ exports[`Form should not render no settings message when instructed not to 1`] = General

+ + + + + + + , + "settingsCount": -1, + } + } + /> + + + + + + + + + + , + "settingsCount": -1, + } + } + /> + + + + + + + + + + , + "settingsCount": -1, + } + } + /> + + + + + + + + + + , + "settingsCount": -1, + } + } + /> + + + { }) ); }); + + it('should save an array typed field when user provides an empty string correctly', async () => { + const wrapper = mountWithI18nProvider( +
+ ); + + (wrapper.instance() as Form).setState({ + unsavedChanges: { + 'general:test:array': { + value: '', + }, + }, + }); + + findTestSubject(wrapper.update(), `advancedSetting-saveButton`).simulate('click'); + expect(save).toHaveBeenCalledWith({ 'general:test:array': [] }); + }); + + it('should save an array typed field when user provides a comma separated string correctly', async () => { + const wrapper = mountWithI18nProvider( + + ); + + (wrapper.instance() as Form).setState({ + unsavedChanges: { + 'general:test:array': { + value: 'test1, test2', + }, + }, + }); + + findTestSubject(wrapper.update(), `advancedSetting-saveButton`).simulate('click'); + expect(save).toHaveBeenCalledWith({ 'general:test:array': ['test1', 'test2'] }); + }); }); diff --git a/src/plugins/advanced_settings/public/management_app/components/form/form.tsx b/src/plugins/advanced_settings/public/management_app/components/form/form.tsx index 0378d816fd2c3..d243d85e12a66 100644 --- a/src/plugins/advanced_settings/public/management_app/components/form/form.tsx +++ b/src/plugins/advanced_settings/public/management_app/components/form/form.tsx @@ -154,7 +154,9 @@ export class Form extends PureComponent { let equalsToDefault = false; switch (type) { case 'array': - valueToSave = valueToSave.split(',').map((val: string) => val.trim()); + valueToSave = valueToSave.trim(); + valueToSave = + valueToSave === '' ? [] : valueToSave.split(',').map((val: string) => val.trim()); equalsToDefault = valueToSave.join(',') === (defVal as string[]).join(','); break; case 'json': @@ -386,6 +388,13 @@ export class Form extends PureComponent { const { unsavedChanges } = this.state; const { visibleSettings, categories, categoryCounts, clearQuery } = this.props; const currentCategories: Category[] = []; + const hasUnsavedChanges = !isEmpty(unsavedChanges); + + if (hasUnsavedChanges) { + document.body.classList.add('kbnBody--mgtAdvancedSettingsHasBottomBar'); + } else { + document.body.classList.remove('kbnBody--mgtAdvancedSettingsHasBottomBar'); + } categories.forEach((category) => { if (visibleSettings[category] && visibleSettings[category].length) { @@ -406,7 +415,7 @@ export class Form extends PureComponent { }) : this.maybeRenderNoSettings(clearQuery)}

- {!isEmpty(unsavedChanges) && this.renderBottomBar()} + {hasUnsavedChanges && this.renderBottomBar()} ); } diff --git a/src/plugins/apm_oss/server/tutorial/index_pattern.json b/src/plugins/apm_oss/server/tutorial/index_pattern.json index bb42b223c85ed..dbceaacfb4a27 100644 --- a/src/plugins/apm_oss/server/tutorial/index_pattern.json +++ b/src/plugins/apm_oss/server/tutorial/index_pattern.json @@ -1,11 +1,11 @@ { "attributes": { - "fieldFormatMap": "{\"client.bytes\":{\"id\":\"bytes\"},\"client.nat.port\":{\"id\":\"string\"},\"client.port\":{\"id\":\"string\"},\"destination.bytes\":{\"id\":\"bytes\"},\"destination.nat.port\":{\"id\":\"string\"},\"destination.port\":{\"id\":\"string\"},\"event.duration\":{\"id\":\"duration\",\"params\":{\"inputFormat\":\"nanoseconds\",\"outputFormat\":\"asMilliseconds\",\"outputPrecision\":1}},\"event.sequence\":{\"id\":\"string\"},\"event.severity\":{\"id\":\"string\"},\"http.request.body.bytes\":{\"id\":\"bytes\"},\"http.request.bytes\":{\"id\":\"bytes\"},\"http.response.body.bytes\":{\"id\":\"bytes\"},\"http.response.bytes\":{\"id\":\"bytes\"},\"http.response.status_code\":{\"id\":\"string\"},\"log.syslog.facility.code\":{\"id\":\"string\"},\"log.syslog.priority\":{\"id\":\"string\"},\"network.bytes\":{\"id\":\"bytes\"},\"package.size\":{\"id\":\"string\"},\"process.parent.pgid\":{\"id\":\"string\"},\"process.parent.pid\":{\"id\":\"string\"},\"process.parent.ppid\":{\"id\":\"string\"},\"process.parent.thread.id\":{\"id\":\"string\"},\"process.pgid\":{\"id\":\"string\"},\"process.pid\":{\"id\":\"string\"},\"process.ppid\":{\"id\":\"string\"},\"process.thread.id\":{\"id\":\"string\"},\"server.bytes\":{\"id\":\"bytes\"},\"server.nat.port\":{\"id\":\"string\"},\"server.port\":{\"id\":\"string\"},\"source.bytes\":{\"id\":\"bytes\"},\"source.nat.port\":{\"id\":\"string\"},\"source.port\":{\"id\":\"string\"},\"system.cpu.total.norm.pct\":{\"id\":\"percent\"},\"system.memory.actual.free\":{\"id\":\"bytes\"},\"system.memory.total\":{\"id\":\"bytes\"},\"system.process.cgroup.memory.mem.limit.bytes\":{\"id\":\"bytes\"},\"system.process.cgroup.memory.mem.usage.bytes\":{\"id\":\"bytes\"},\"system.process.cgroup.memory.stats.inactive_file.bytes\":{\"id\":\"bytes\"},\"system.process.cpu.total.norm.pct\":{\"id\":\"percent\"},\"system.process.memory.rss.bytes\":{\"id\":\"bytes\"},\"system.process.memory.size\":{\"id\":\"bytes\"},\"url.port\":{\"id\":\"string\"},\"view spans\":{\"id\":\"url\",\"params\":{\"labelTemplate\":\"View Spans\"}}}", - "fields": "[{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"@timestamp\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"labels\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"message\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tags\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"agent.ephemeral_id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"agent.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"agent.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"agent.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"agent.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"as.number\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"as.organization.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"as.organization.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.address\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.as.number\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.as.organization.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.as.organization.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.geo.city_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.geo.continent_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.geo.country_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.geo.country_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.geo.location\",\"scripted\":false,\"searchable\":true,\"type\":\"geo_point\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.geo.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.geo.region_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.geo.region_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.mac\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.nat.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.nat.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.packets\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.registered_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.top_level_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.email\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.full_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.full_name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.group.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.group.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.group.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.hash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.account.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.availability_zone\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.instance.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.instance.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.machine.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.provider\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.region\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"code_signature.exists\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"code_signature.status\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"code_signature.subject_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"code_signature.trusted\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"code_signature.valid\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"container.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"container.image.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"container.image.tag\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"container.labels\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"container.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"container.runtime\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.address\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.as.number\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.as.organization.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.as.organization.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.geo.city_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.geo.continent_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.geo.country_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.geo.country_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.geo.location\",\"scripted\":false,\"searchable\":true,\"type\":\"geo_point\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.geo.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.geo.region_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.geo.region_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.mac\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.nat.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.nat.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.packets\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.registered_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.top_level_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.email\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.full_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.full_name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.group.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.group.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.group.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.hash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.code_signature.exists\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.code_signature.status\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.code_signature.subject_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.code_signature.trusted\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.code_signature.valid\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.hash.md5\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.hash.sha1\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.hash.sha256\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.hash.sha512\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.path\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.pe.company\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.pe.description\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.pe.file_version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.pe.original_file_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.pe.product\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.answers\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.answers.class\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.answers.data\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.answers.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.answers.ttl\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.answers.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.header_flags\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.op_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.question.class\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.question.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.question.registered_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.question.subdomain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.question.top_level_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.question.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.resolved_ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.response_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"ecs.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":4,\"doc_values\":true,\"indexed\":true,\"name\":\"error.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.message\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.stack_trace\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.stack_trace.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.action\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.category\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.created\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.dataset\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.duration\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.end\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.hash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.ingested\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.kind\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.module\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.original\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.outcome\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.provider\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.reference\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.risk_score\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.risk_score_norm\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.sequence\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.severity\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.start\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.timezone\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.url\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.accessed\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.attributes\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.code_signature.exists\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.code_signature.status\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.code_signature.subject_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.code_signature.trusted\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.code_signature.valid\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.created\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.ctime\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.device\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.directory\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.drive_letter\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.extension\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.gid\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.group\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.hash.md5\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.hash.sha1\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.hash.sha256\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.hash.sha512\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.inode\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.mime_type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.mode\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.mtime\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.owner\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.path\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.path.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.pe.company\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.pe.description\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.pe.file_version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.pe.original_file_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.pe.product\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.size\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.target_path\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.target_path.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.uid\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"geo.city_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"geo.continent_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"geo.country_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"geo.country_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"geo.location\",\"scripted\":false,\"searchable\":true,\"type\":\"geo_point\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"geo.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"geo.region_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"geo.region_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"group.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"group.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"group.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"hash.md5\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"hash.sha1\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"hash.sha256\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"hash.sha512\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.architecture\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.geo.city_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.geo.continent_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.geo.country_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.geo.country_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.geo.location\",\"scripted\":false,\"searchable\":true,\"type\":\"geo_point\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.geo.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.geo.region_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.geo.region_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.hostname\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.mac\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.family\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.full\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.full.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.kernel\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.platform\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.uptime\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.email\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.full_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.full_name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.group.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.group.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.group.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.hash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.request.body.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.request.body.content\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.request.body.content.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.request.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.request.method\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.request.referrer\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.response.body.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.response.body.content\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.response.body.content.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.response.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.response.status_code\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"interface.alias\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"interface.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"interface.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.level\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.logger\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.origin.file.line\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.origin.file.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.origin.function\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.original\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.syslog\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.syslog.facility.code\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.syslog.facility.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.syslog.priority\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.syslog.severity.code\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.syslog.severity.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.application\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.community_id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.direction\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.forwarded_ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.iana_number\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.inner\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.inner.vlan.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.inner.vlan.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.packets\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.protocol\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.transport\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.vlan.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.vlan.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.egress\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.egress.interface.alias\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.egress.interface.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.egress.interface.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.egress.vlan.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.egress.vlan.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.egress.zone\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.geo.city_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.geo.continent_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.geo.country_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.geo.country_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.geo.location\",\"scripted\":false,\"searchable\":true,\"type\":\"geo_point\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.geo.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.geo.region_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.geo.region_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.hostname\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.ingress\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.ingress.interface.alias\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.ingress.interface.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.ingress.interface.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.ingress.vlan.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.ingress.vlan.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.ingress.zone\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.mac\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.os.family\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.os.full\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.os.full.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.os.kernel\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.os.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.os.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.os.platform\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.os.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.product\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.serial_number\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.vendor\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"organization.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"organization.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"organization.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"os.family\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"os.full\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"os.full.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"os.kernel\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"os.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"os.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"os.platform\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"os.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.architecture\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.build_version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.checksum\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.description\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.install_scope\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.installed\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.license\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.path\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.reference\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.size\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"pe.company\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"pe.description\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"pe.file_version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"pe.original_file_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"pe.product\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.args\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.args_count\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.code_signature.exists\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.code_signature.status\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.code_signature.subject_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.code_signature.trusted\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.code_signature.valid\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.command_line\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.command_line.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.entity_id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.executable\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.executable.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.exit_code\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.hash.md5\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.hash.sha1\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.hash.sha256\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.hash.sha512\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.args\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.args_count\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.code_signature.exists\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.code_signature.status\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.code_signature.subject_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.code_signature.trusted\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.code_signature.valid\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.command_line\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.command_line.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.entity_id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.executable\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.executable.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.exit_code\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.hash.md5\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.hash.sha1\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.hash.sha256\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.hash.sha512\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.pgid\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.pid\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.ppid\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.start\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.thread.id\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.thread.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.title\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.title.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.uptime\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.working_directory\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.working_directory.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.pe.company\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.pe.description\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.pe.file_version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.pe.original_file_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.pe.product\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.pgid\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.pid\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.ppid\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.start\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.thread.id\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.thread.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.title\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.title.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.uptime\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.working_directory\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.working_directory.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"registry.data.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"registry.data.strings\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"registry.data.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"registry.hive\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"registry.key\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"registry.path\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"registry.value\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"related.hash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"related.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"related.user\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"rule.author\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"rule.category\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"rule.description\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"rule.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"rule.license\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"rule.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"rule.reference\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"rule.ruleset\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"rule.uuid\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"rule.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.address\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.as.number\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.as.organization.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.as.organization.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.geo.city_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.geo.continent_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.geo.country_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.geo.country_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.geo.location\",\"scripted\":false,\"searchable\":true,\"type\":\"geo_point\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.geo.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.geo.region_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.geo.region_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.mac\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.nat.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.nat.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.packets\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.registered_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.top_level_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.email\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.full_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.full_name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.group.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.group.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.group.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.hash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.ephemeral_id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.node.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.state\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.address\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.as.number\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.as.organization.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.as.organization.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.geo.city_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.geo.continent_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.geo.country_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.geo.country_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.geo.location\",\"scripted\":false,\"searchable\":true,\"type\":\"geo_point\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.geo.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.geo.region_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.geo.region_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.mac\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.nat.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.nat.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.packets\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.registered_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.top_level_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.email\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.full_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.full_name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.group.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.group.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.group.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.hash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"threat.framework\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"threat.tactic.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"threat.tactic.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"threat.tactic.reference\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"threat.technique.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"threat.technique.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"threat.technique.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"threat.technique.reference\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.cipher\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.certificate\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.certificate_chain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.hash.md5\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.hash.sha1\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.hash.sha256\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.issuer\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.ja3\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.not_after\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.not_before\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.server_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.subject\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.supported_ciphers\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.curve\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.established\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.next_protocol\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.resumed\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.certificate\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.certificate_chain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.hash.md5\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.hash.sha1\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.hash.sha256\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.issuer\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.ja3s\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.not_after\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.not_before\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.subject\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.version_protocol\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tracing.trace.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tracing.transaction.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.extension\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.fragment\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.full\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.full.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.original\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.original.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.password\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.path\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.query\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.registered_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.scheme\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.top_level_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.username\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.email\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.full_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.full_name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.group.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.group.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.group.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.hash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.device.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.original\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.original.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.os.family\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.os.full\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.os.full.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.os.kernel\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.os.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.os.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.os.platform\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.os.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vlan.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vlan.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.category\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.classification\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.description\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.description.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.enumeration\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.reference\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.report_id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.scanner.vendor\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.score.base\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.score.environmental\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.score.temporal\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.score.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.severity\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"agent.hostname\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"fields\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"timeseries.instance\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.project.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.image.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"docker.container.labels\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.containerized\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.build\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.codename\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.pod.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.pod.uid\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.namespace\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.node.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.labels.*\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.annotations.*\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.replicaset.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.deployment.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.statefulset.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.container.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.container.image\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"processor.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"processor.event\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"timestamp.us\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":false,\"enabled\":false,\"indexed\":false,\"name\":\"http.request.headers\",\"scripted\":false,\"searchable\":false},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.response.finished\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":false,\"enabled\":false,\"indexed\":false,\"name\":\"http.response.headers\",\"scripted\":false,\"searchable\":false},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.environment\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.language.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.language.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.runtime.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.runtime.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.framework.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.framework.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.sampled\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.duration.count\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.duration.sum.us\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.self_time.count\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.self_time.sum.us\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.breakdown.count\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"span.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"span.subtype\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.self_time.count\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.self_time.sum.us\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"trace.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"parent.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.listening\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.version_major\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"experimental\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.account.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.project.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":2,\"doc_values\":true,\"indexed\":true,\"name\":\"error.culprit\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.grouping_key\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.exception.code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":2,\"doc_values\":true,\"indexed\":true,\"name\":\"error.exception.message\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.exception.module\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":4,\"doc_values\":true,\"indexed\":true,\"name\":\"error.exception.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":2,\"doc_values\":true,\"indexed\":true,\"name\":\"error.exception.handled\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.log.level\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.log.logger_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":2,\"doc_values\":true,\"indexed\":true,\"name\":\"error.log.message\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.log.param_message\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"system.cpu.total.norm.pct\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"system.memory.total\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"system.memory.actual.free\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"system.process.cpu.total.norm.pct\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"system.process.memory.size\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"system.process.memory.rss.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"system.process.cgroup.memory.mem.limit.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"system.process.cgroup.memory.mem.usage.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"system.process.cgroup.memory.stats.inactive_file.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.root\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.duration\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.cpu.ns\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.samples.count\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.alloc_objects.count\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.alloc_space.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.inuse_objects.count\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.inuse_space.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.top.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.top.function\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.top.filename\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.top.line\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.stack.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.stack.function\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.stack.filename\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.stack.line\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"sourcemap.service.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"sourcemap.service.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"sourcemap.bundle_filepath\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"view spans\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"child.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"span.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"span.action\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"span.start.us\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"span.duration.us\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.sync\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.db.link\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.db.rows_affected\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.destination.service.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.destination.service.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.destination.service.resource\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.message.queue.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.message.age.ms\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.duration.us\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.result\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.marks\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.marks.*.*\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.experience.cls\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.experience.fid\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.experience.tbt\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.span_count.dropped\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.message.queue.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.message.age.ms\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.duration.histogram\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"metricset.period\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.destination.service.response_time.count\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.destination.service.response_time.sum.us\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":false,\"indexed\":false,\"name\":\"_id\",\"scripted\":false,\"searchable\":false,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":false,\"indexed\":false,\"name\":\"_type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":false,\"indexed\":false,\"name\":\"_index\",\"scripted\":false,\"searchable\":false,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":false,\"indexed\":false,\"name\":\"_score\",\"scripted\":false,\"searchable\":false,\"type\":\"number\"}]", + "fieldFormatMap": "{\"client.bytes\":{\"id\":\"bytes\"},\"client.nat.port\":{\"id\":\"string\"},\"client.port\":{\"id\":\"string\"},\"destination.bytes\":{\"id\":\"bytes\"},\"destination.nat.port\":{\"id\":\"string\"},\"destination.port\":{\"id\":\"string\"},\"event.duration\":{\"id\":\"duration\",\"params\":{\"inputFormat\":\"nanoseconds\",\"outputFormat\":\"asMilliseconds\",\"outputPrecision\":1}},\"event.sequence\":{\"id\":\"string\"},\"event.severity\":{\"id\":\"string\"},\"http.request.body.bytes\":{\"id\":\"bytes\"},\"http.request.bytes\":{\"id\":\"bytes\"},\"http.response.body.bytes\":{\"id\":\"bytes\"},\"http.response.bytes\":{\"id\":\"bytes\"},\"http.response.status_code\":{\"id\":\"string\"},\"log.syslog.facility.code\":{\"id\":\"string\"},\"log.syslog.priority\":{\"id\":\"string\"},\"network.bytes\":{\"id\":\"bytes\"},\"package.size\":{\"id\":\"string\"},\"process.parent.pgid\":{\"id\":\"string\"},\"process.parent.pid\":{\"id\":\"string\"},\"process.parent.ppid\":{\"id\":\"string\"},\"process.parent.thread.id\":{\"id\":\"string\"},\"process.pgid\":{\"id\":\"string\"},\"process.pid\":{\"id\":\"string\"},\"process.ppid\":{\"id\":\"string\"},\"process.thread.id\":{\"id\":\"string\"},\"server.bytes\":{\"id\":\"bytes\"},\"server.nat.port\":{\"id\":\"string\"},\"server.port\":{\"id\":\"string\"},\"source.bytes\":{\"id\":\"bytes\"},\"source.nat.port\":{\"id\":\"string\"},\"source.port\":{\"id\":\"string\"},\"system.cpu.total.norm.pct\":{\"id\":\"percent\"},\"system.memory.actual.free\":{\"id\":\"bytes\"},\"system.memory.total\":{\"id\":\"bytes\"},\"system.process.cgroup.memory.mem.limit.bytes\":{\"id\":\"bytes\"},\"system.process.cgroup.memory.mem.usage.bytes\":{\"id\":\"bytes\"},\"system.process.cpu.total.norm.pct\":{\"id\":\"percent\"},\"system.process.memory.rss.bytes\":{\"id\":\"bytes\"},\"system.process.memory.size\":{\"id\":\"bytes\"},\"url.port\":{\"id\":\"string\"},\"view spans\":{\"id\":\"url\",\"params\":{\"labelTemplate\":\"View Spans\"}}}", + "fields": "[{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"@timestamp\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"labels\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"message\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tags\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"agent.build.original\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"agent.ephemeral_id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"agent.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"agent.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"agent.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"agent.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"as.number\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"as.organization.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"as.organization.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.address\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.as.number\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.as.organization.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.as.organization.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.geo.city_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.geo.continent_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.geo.country_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.geo.country_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.geo.location\",\"scripted\":false,\"searchable\":true,\"type\":\"geo_point\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.geo.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.geo.region_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.geo.region_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.mac\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.nat.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.nat.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.packets\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.registered_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.top_level_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.email\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.full_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.full_name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.group.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.group.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.group.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.hash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"client.user.roles\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.account.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.account.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.availability_zone\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.instance.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.instance.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.machine.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.project.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.project.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.provider\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.region\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"code_signature.exists\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"code_signature.status\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"code_signature.subject_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"code_signature.trusted\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"code_signature.valid\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"container.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"container.image.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"container.image.tag\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"container.labels\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"container.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"container.runtime\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.address\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.as.number\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.as.organization.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.as.organization.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.geo.city_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.geo.continent_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.geo.country_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.geo.country_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.geo.location\",\"scripted\":false,\"searchable\":true,\"type\":\"geo_point\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.geo.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.geo.region_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.geo.region_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.mac\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.nat.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.nat.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.packets\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.registered_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.top_level_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.email\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.full_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.full_name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.group.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.group.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.group.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.hash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"destination.user.roles\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.code_signature.exists\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.code_signature.status\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.code_signature.subject_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.code_signature.trusted\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.code_signature.valid\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.hash.md5\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.hash.sha1\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.hash.sha256\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.hash.sha512\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.path\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.pe.architecture\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.pe.company\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.pe.description\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.pe.file_version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.pe.imphash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.pe.original_file_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dll.pe.product\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.answers\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.answers.class\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.answers.data\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.answers.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.answers.ttl\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.answers.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.header_flags\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.op_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.question.class\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.question.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.question.registered_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.question.subdomain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.question.top_level_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.question.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.resolved_ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.response_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"dns.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"ecs.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":4,\"doc_values\":true,\"indexed\":true,\"name\":\"error.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.message\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":false,\"name\":\"error.stack_trace\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":false,\"name\":\"error.stack_trace.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.action\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.category\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.created\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.dataset\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.duration\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.end\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.hash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.ingested\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.kind\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.module\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":false,\"name\":\"event.original\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.outcome\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.provider\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.reason\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.reference\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.risk_score\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.risk_score_norm\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.sequence\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.severity\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.start\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.timezone\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"event.url\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.accessed\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.attributes\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.code_signature.exists\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.code_signature.status\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.code_signature.subject_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.code_signature.trusted\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.code_signature.valid\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.created\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.ctime\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.device\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.directory\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.drive_letter\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.extension\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.gid\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.group\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.hash.md5\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.hash.sha1\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.hash.sha256\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.hash.sha512\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.inode\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.mime_type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.mode\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.mtime\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.owner\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.path\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.path.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.pe.architecture\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.pe.company\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.pe.description\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.pe.file_version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.pe.imphash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.pe.original_file_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.pe.product\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.size\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.target_path\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.target_path.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.uid\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.x509.alternative_names\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.x509.issuer.common_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.x509.issuer.country\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.x509.issuer.distinguished_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.x509.issuer.locality\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.x509.issuer.organization\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.x509.issuer.organizational_unit\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.x509.issuer.state_or_province\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.x509.not_after\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.x509.not_before\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.x509.public_key_algorithm\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.x509.public_key_curve\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":false,\"name\":\"file.x509.public_key_exponent\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.x509.public_key_size\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.x509.serial_number\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.x509.signature_algorithm\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.x509.subject.common_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.x509.subject.country\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.x509.subject.distinguished_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.x509.subject.locality\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.x509.subject.organization\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.x509.subject.organizational_unit\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.x509.subject.state_or_province\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"file.x509.version_number\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"geo.city_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"geo.continent_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"geo.country_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"geo.country_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"geo.location\",\"scripted\":false,\"searchable\":true,\"type\":\"geo_point\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"geo.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"geo.region_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"geo.region_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"group.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"group.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"group.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"hash.md5\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"hash.sha1\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"hash.sha256\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"hash.sha512\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.architecture\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.geo.city_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.geo.continent_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.geo.country_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.geo.country_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.geo.location\",\"scripted\":false,\"searchable\":true,\"type\":\"geo_point\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.geo.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.geo.region_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.geo.region_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.hostname\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.mac\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.family\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.full\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.full.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.kernel\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.platform\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.uptime\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.email\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.full_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.full_name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.group.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.group.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.group.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.hash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.user.roles\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.request.body.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.request.body.content\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.request.body.content.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.request.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.request.method\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.request.referrer\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.response.body.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.response.body.content\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.response.body.content.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.response.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.response.status_code\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"interface.alias\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"interface.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"interface.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.file.path\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.level\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.logger\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.origin.file.line\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.origin.file.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.origin.function\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":false,\"name\":\"log.original\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.syslog\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.syslog.facility.code\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.syslog.facility.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.syslog.priority\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.syslog.severity.code\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"log.syslog.severity.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.application\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.community_id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.direction\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.forwarded_ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.iana_number\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.inner\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.inner.vlan.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.inner.vlan.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.packets\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.protocol\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.transport\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.vlan.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"network.vlan.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.egress\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.egress.interface.alias\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.egress.interface.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.egress.interface.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.egress.vlan.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.egress.vlan.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.egress.zone\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.geo.city_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.geo.continent_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.geo.country_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.geo.country_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.geo.location\",\"scripted\":false,\"searchable\":true,\"type\":\"geo_point\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.geo.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.geo.region_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.geo.region_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.hostname\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.ingress\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.ingress.interface.alias\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.ingress.interface.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.ingress.interface.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.ingress.vlan.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.ingress.vlan.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.ingress.zone\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.mac\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.os.family\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.os.full\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.os.full.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.os.kernel\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.os.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.os.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.os.platform\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.os.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.product\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.serial_number\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.vendor\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"organization.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"organization.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"organization.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"os.family\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"os.full\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"os.full.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"os.kernel\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"os.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"os.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"os.platform\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"os.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.architecture\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.build_version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.checksum\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.description\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.install_scope\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.installed\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.license\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.path\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.reference\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.size\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"package.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"pe.architecture\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"pe.company\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"pe.description\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"pe.file_version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"pe.imphash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"pe.original_file_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"pe.product\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.args\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.args_count\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.code_signature.exists\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.code_signature.status\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.code_signature.subject_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.code_signature.trusted\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.code_signature.valid\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.command_line\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.command_line.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.entity_id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.executable\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.executable.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.exit_code\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.hash.md5\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.hash.sha1\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.hash.sha256\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.hash.sha512\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.args\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.args_count\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.code_signature.exists\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.code_signature.status\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.code_signature.subject_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.code_signature.trusted\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.code_signature.valid\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.command_line\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.command_line.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.entity_id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.executable\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.executable.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.exit_code\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.hash.md5\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.hash.sha1\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.hash.sha256\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.hash.sha512\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.pe.architecture\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.pe.company\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.pe.description\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.pe.file_version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.pe.imphash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.pe.original_file_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.pe.product\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.pgid\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.pid\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.ppid\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.start\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.thread.id\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.thread.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.title\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.title.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.uptime\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.working_directory\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.parent.working_directory.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.pe.architecture\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.pe.company\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.pe.description\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.pe.file_version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.pe.imphash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.pe.original_file_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.pe.product\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.pgid\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.pid\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.ppid\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.start\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.thread.id\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.thread.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.title\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.title.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.uptime\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.working_directory\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"process.working_directory.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"registry.data.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"registry.data.strings\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"registry.data.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"registry.hive\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"registry.key\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"registry.path\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"registry.value\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"related.hash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"related.hosts\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"related.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"related.user\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"rule.author\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"rule.category\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"rule.description\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"rule.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"rule.license\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"rule.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"rule.reference\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"rule.ruleset\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"rule.uuid\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"rule.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.address\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.as.number\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.as.organization.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.as.organization.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.geo.city_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.geo.continent_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.geo.country_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.geo.country_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.geo.location\",\"scripted\":false,\"searchable\":true,\"type\":\"geo_point\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.geo.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.geo.region_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.geo.region_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.mac\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.nat.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.nat.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.packets\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.registered_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.top_level_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.email\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.full_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.full_name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.group.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.group.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.group.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.hash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"server.user.roles\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.ephemeral_id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.node.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.state\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.address\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.as.number\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.as.organization.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.as.organization.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.geo.city_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.geo.continent_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.geo.country_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.geo.country_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.geo.location\",\"scripted\":false,\"searchable\":true,\"type\":\"geo_point\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.geo.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.geo.region_iso_code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.geo.region_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.mac\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.nat.ip\",\"scripted\":false,\"searchable\":true,\"type\":\"ip\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.nat.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.packets\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.registered_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.top_level_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.email\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.full_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.full_name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.group.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.group.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.group.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.hash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"source.user.roles\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"threat.framework\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"threat.tactic.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"threat.tactic.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"threat.tactic.reference\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"threat.technique.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"threat.technique.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"threat.technique.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"threat.technique.reference\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.cipher\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.certificate\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.certificate_chain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.hash.md5\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.hash.sha1\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.hash.sha256\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.issuer\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.ja3\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.not_after\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.not_before\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.server_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.subject\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.supported_ciphers\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.x509.alternative_names\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.x509.issuer.common_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.x509.issuer.country\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.x509.issuer.distinguished_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.x509.issuer.locality\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.x509.issuer.organization\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.x509.issuer.organizational_unit\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.x509.issuer.state_or_province\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.x509.not_after\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.x509.not_before\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.x509.public_key_algorithm\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.x509.public_key_curve\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":false,\"name\":\"tls.client.x509.public_key_exponent\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.x509.public_key_size\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.x509.serial_number\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.x509.signature_algorithm\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.x509.subject.common_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.x509.subject.country\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.x509.subject.distinguished_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.x509.subject.locality\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.x509.subject.organization\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.x509.subject.organizational_unit\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.x509.subject.state_or_province\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.client.x509.version_number\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.curve\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.established\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.next_protocol\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.resumed\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.certificate\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.certificate_chain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.hash.md5\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.hash.sha1\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.hash.sha256\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.issuer\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.ja3s\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.not_after\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.not_before\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.subject\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.x509.alternative_names\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.x509.issuer.common_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.x509.issuer.country\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.x509.issuer.distinguished_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.x509.issuer.locality\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.x509.issuer.organization\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.x509.issuer.organizational_unit\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.x509.issuer.state_or_province\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.x509.not_after\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.x509.not_before\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.x509.public_key_algorithm\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.x509.public_key_curve\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":false,\"name\":\"tls.server.x509.public_key_exponent\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.x509.public_key_size\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.x509.serial_number\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.x509.signature_algorithm\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.x509.subject.common_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.x509.subject.country\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.x509.subject.distinguished_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.x509.subject.locality\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.x509.subject.organization\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.x509.subject.organizational_unit\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.x509.subject.state_or_province\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.server.x509.version_number\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tls.version_protocol\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tracing.span.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tracing.trace.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"tracing.transaction.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.extension\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.fragment\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.full\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.full.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.original\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.original.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.password\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.path\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.port\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.query\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.registered_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.scheme\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.top_level_domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"url.username\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.email\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.full_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.full_name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.group.domain\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.group.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.group.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.hash\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user.roles\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.device.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.original\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.original.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.os.family\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.os.full\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.os.full.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.os.kernel\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.os.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.os.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.os.platform\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.os.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"user_agent.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vlan.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vlan.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.category\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.classification\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.description\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.description.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.enumeration\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.reference\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.report_id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.scanner.vendor\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.score.base\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.score.environmental\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.score.temporal\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.score.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"vulnerability.severity\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"x509.alternative_names\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"x509.issuer.common_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"x509.issuer.country\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"x509.issuer.distinguished_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"x509.issuer.locality\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"x509.issuer.organization\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"x509.issuer.organizational_unit\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"x509.issuer.state_or_province\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"x509.not_after\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"x509.not_before\",\"scripted\":false,\"searchable\":true,\"type\":\"date\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"x509.public_key_algorithm\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"x509.public_key_curve\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":false,\"name\":\"x509.public_key_exponent\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"x509.public_key_size\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"x509.serial_number\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"x509.signature_algorithm\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"x509.subject.common_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"x509.subject.country\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"x509.subject.distinguished_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"x509.subject.locality\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"x509.subject.organization\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"x509.subject.organizational_unit\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"x509.subject.state_or_province\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"x509.version_number\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"agent.hostname\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"fields\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"timeseries.instance\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"cloud.image.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"docker.container.labels\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.containerized\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.build\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"host.os.codename\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.pod.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.pod.uid\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.namespace\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.node.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.labels.*\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.annotations.*\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.replicaset.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.deployment.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.statefulset.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.container.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"kubernetes.container.image\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"processor.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"processor.event\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"timestamp.us\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":false,\"enabled\":false,\"indexed\":false,\"name\":\"http.request.headers\",\"scripted\":false,\"searchable\":false},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"http.response.finished\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":false,\"enabled\":false,\"indexed\":false,\"name\":\"http.response.headers\",\"scripted\":false,\"searchable\":false},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.environment\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.language.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.language.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.runtime.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.runtime.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.framework.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"service.framework.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.sampled\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.name.text\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.duration.count\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.duration.sum.us\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.self_time.count\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.self_time.sum.us\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.breakdown.count\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"span.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"span.subtype\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.self_time.count\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.self_time.sum.us\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"trace.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"parent.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.listening\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"observer.version_major\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"experimental\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":2,\"doc_values\":true,\"indexed\":true,\"name\":\"error.culprit\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.grouping_key\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.exception.code\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":2,\"doc_values\":true,\"indexed\":true,\"name\":\"error.exception.message\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.exception.module\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":4,\"doc_values\":true,\"indexed\":true,\"name\":\"error.exception.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":2,\"doc_values\":true,\"indexed\":true,\"name\":\"error.exception.handled\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.log.level\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.log.logger_name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":2,\"doc_values\":true,\"indexed\":true,\"name\":\"error.log.message\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"error.log.param_message\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"system.cpu.total.norm.pct\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"system.memory.total\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"system.memory.actual.free\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"system.process.cpu.total.norm.pct\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"system.process.memory.size\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"system.process.memory.rss.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"system.process.cgroup.memory.mem.limit.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"system.process.cgroup.memory.mem.usage.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.root\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.duration\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.cpu.ns\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.samples.count\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.alloc_objects.count\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.alloc_space.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.inuse_objects.count\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.inuse_space.bytes\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.top.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.top.function\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.top.filename\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.top.line\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.stack.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.stack.function\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.stack.filename\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"profile.stack.line\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"sourcemap.service.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"sourcemap.service.version\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"sourcemap.bundle_filepath\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"view spans\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"child.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.id\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"span.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"span.action\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"span.start.us\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":1,\"doc_values\":true,\"indexed\":true,\"name\":\"span.duration.us\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.sync\",\"scripted\":false,\"searchable\":true,\"type\":\"boolean\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.db.link\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.db.rows_affected\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.destination.service.type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.destination.service.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.destination.service.resource\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.message.queue.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.message.age.ms\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.duration.us\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.result\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.marks\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.marks.*.*\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.experience.cls\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.experience.fid\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.experience.tbt\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.experience.longtask.count\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.experience.longtask.sum\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.experience.longtask.max\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.span_count.dropped\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.message.queue.name\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.message.age.ms\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"transaction.duration.histogram\",\"scripted\":false,\"searchable\":true},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"metricset.period\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.destination.service.response_time.count\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":true,\"indexed\":true,\"name\":\"span.destination.service.response_time.sum.us\",\"scripted\":false,\"searchable\":true,\"type\":\"number\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":false,\"indexed\":false,\"name\":\"_id\",\"scripted\":false,\"searchable\":false,\"type\":\"string\"},{\"aggregatable\":true,\"analyzed\":false,\"count\":0,\"doc_values\":false,\"indexed\":false,\"name\":\"_type\",\"scripted\":false,\"searchable\":true,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":false,\"indexed\":false,\"name\":\"_index\",\"scripted\":false,\"searchable\":false,\"type\":\"string\"},{\"aggregatable\":false,\"analyzed\":false,\"count\":0,\"doc_values\":false,\"indexed\":false,\"name\":\"_score\",\"scripted\":false,\"searchable\":false,\"type\":\"number\"}]", "sourceFilters": "[{\"value\":\"sourcemap.sourcemap\"}]", "timeFieldName": "@timestamp" }, "id": "apm-*", "type": "index-pattern", "version": "1" -} +} \ No newline at end of file diff --git a/src/plugins/apm_oss/server/tutorial/instructions/apm_agent_instructions.ts b/src/plugins/apm_oss/server/tutorial/instructions/apm_agent_instructions.ts index d2a4ee8297a11..a74223f28dd03 100644 --- a/src/plugins/apm_oss/server/tutorial/instructions/apm_agent_instructions.ts +++ b/src/plugins/apm_oss/server/tutorial/instructions/apm_agent_instructions.ts @@ -37,7 +37,7 @@ export const createNodeAgentInstructions = (apmServerUrl = '', secretToken = '') defaultMessage: 'Agents are libraries that run inside of your application process. \ APM services are created programmatically based on the `serviceName`. \ -This agent supports a vararity of frameworks but can also be used with your custom stack.', +This agent supports a variety of frameworks but can also be used with your custom stack.', }), commands: `// ${i18n.translate( 'apmOss.tutorial.nodeClient.configure.commands.addThisToTheFileTopComment', diff --git a/src/plugins/charts/kibana.json b/src/plugins/charts/kibana.json index c4643d541c31c..8967e931a0b10 100644 --- a/src/plugins/charts/kibana.json +++ b/src/plugins/charts/kibana.json @@ -3,5 +3,5 @@ "version": "kibana", "server": true, "ui": true, - "requiredBundles": ["kibanaUtils", "kibanaReact", "data"] + "requiredBundles": ["visDefaultEditor"] } diff --git a/src/plugins/charts/public/services/colors/color_palette.ts b/src/plugins/charts/public/services/colors/color_palette.ts index 464e9e3a66101..e1c32fe68da12 100644 --- a/src/plugins/charts/public/services/colors/color_palette.ts +++ b/src/plugins/charts/public/services/colors/color_palette.ts @@ -17,8 +17,8 @@ * under the License. */ -import d3 from 'd3'; import _ from 'lodash'; +import { hsl } from 'color'; import { seedColors } from './seed_colors'; @@ -49,7 +49,7 @@ const fraction = function (goal: number) { * If the number is greater than the length of seed colors available, * new colors are generated up to the value of the input number. */ -export function createColorPalette(num?: any): string[] { +export function createColorPalette(num: number): string[] { if (!_.isNumber(num)) { throw new TypeError('ColorPaletteUtilService expects a number'); } @@ -58,7 +58,7 @@ export function createColorPalette(num?: any): string[] { const seedLength = seedColors.length; _.times(num - seedLength, function (i) { - colors.push(d3.hsl((fraction(i + seedLength + 1) * 360 + offset) % 360, 0.5, 0.5).toString()); + colors.push(hsl((fraction(i + seedLength + 1) * 360 + offset) % 360, 0.5, 0.5).hex()); }); return colors; diff --git a/src/plugins/charts/public/services/colors/colors_palette.test.ts b/src/plugins/charts/public/services/colors/colors_palette.test.ts index 6612447cefe9e..02ff5a6056d54 100644 --- a/src/plugins/charts/public/services/colors/colors_palette.test.ts +++ b/src/plugins/charts/public/services/colors/colors_palette.test.ts @@ -37,26 +37,32 @@ describe('Color Palette', () => { it('should throw an error if input is not a number', () => { expect(() => { + // @ts-expect-error createColorPalette(string); }).toThrowError(); expect(() => { + // @ts-expect-error createColorPalette(bool); }).toThrowError(); expect(() => { + // @ts-expect-error createColorPalette(nullValue); }).toThrowError(); expect(() => { + // @ts-expect-error createColorPalette(emptyArr); }).toThrowError(); expect(() => { + // @ts-expect-error createColorPalette(emptyObject); }).toThrowError(); expect(() => { + // @ts-expect-error createColorPalette(); }).toThrowError(); }); diff --git a/src/plugins/charts/public/services/colors/mapped_colors.test.ts b/src/plugins/charts/public/services/colors/mapped_colors.test.ts index e97ca8ac257b4..9d00bf098de4c 100644 --- a/src/plugins/charts/public/services/colors/mapped_colors.test.ts +++ b/src/plugins/charts/public/services/colors/mapped_colors.test.ts @@ -18,7 +18,7 @@ */ import _ from 'lodash'; -import d3 from 'd3'; +import Color from 'color'; import { coreMock } from '../../../../../core/public/mocks'; import { COLOR_MAPPING_SETTING } from '../../../common'; @@ -61,7 +61,7 @@ describe('Mapped Colors', () => { mappedColors.mapKeys(arr); const colorValues = _(mappedColors.mapping).values(); - expect(colorValues.includes(seedColors[0])).toBe(false); + expect(colorValues).not.toContain(seedColors[0]); expect(colorValues.uniq().size()).toBe(arr.length); }); @@ -78,8 +78,8 @@ describe('Mapped Colors', () => { }); it('should treat different formats of colors as equal', () => { - const color = d3.rgb(seedColors[0]); - const rgb = `rgb(${color.r}, ${color.g}, ${color.b})`; + const color = new Color(seedColors[0]); + const rgb = `rgb(${color.red()}, ${color.green()}, ${color.blue()})`; const newConfig = { bar: rgb }; config.set(COLOR_MAPPING_SETTING, newConfig); diff --git a/src/plugins/charts/public/services/colors/mapped_colors.ts b/src/plugins/charts/public/services/colors/mapped_colors.ts index 3b9e1501d638d..15f9be32b829c 100644 --- a/src/plugins/charts/public/services/colors/mapped_colors.ts +++ b/src/plugins/charts/public/services/colors/mapped_colors.ts @@ -18,14 +18,14 @@ */ import _ from 'lodash'; -import d3 from 'd3'; +import Color from 'color'; import { CoreSetup } from 'kibana/public'; import { COLOR_MAPPING_SETTING } from '../../../common'; import { createColorPalette } from './color_palette'; -const standardizeColor = (color: string) => d3.rgb(color).toString(); +const standardizeColor = (color: string) => new Color(color).hex().toLowerCase(); /** * Maintains a lookup table that associates the value (key) with a hex color (value) diff --git a/src/plugins/console/public/application/containers/editor/legacy/console_editor/editor.tsx b/src/plugins/console/public/application/containers/editor/legacy/console_editor/editor.tsx index fc88b31711b23..abef8afcc3985 100644 --- a/src/plugins/console/public/application/containers/editor/legacy/console_editor/editor.tsx +++ b/src/plugins/console/public/application/containers/editor/legacy/console_editor/editor.tsx @@ -182,6 +182,9 @@ function EditorUI({ initialTextValue }: EditorProps) { unsubscribeResizer(); clearSubscriptions(); window.removeEventListener('hashchange', onHashChange); + if (editorInstanceRef.current) { + editorInstanceRef.current.getCoreEditor().destroy(); + } }; }, [saveCurrentTextObject, initialTextValue, history, setInputEditor, settingsService]); diff --git a/src/plugins/console/public/application/containers/editor/legacy/console_editor/editor_output.tsx b/src/plugins/console/public/application/containers/editor/legacy/console_editor/editor_output.tsx index dd5ef5209a244..44ed5f4b8051e 100644 --- a/src/plugins/console/public/application/containers/editor/legacy/console_editor/editor_output.tsx +++ b/src/plugins/console/public/application/containers/editor/legacy/console_editor/editor_output.tsx @@ -20,7 +20,7 @@ import { EuiScreenReaderOnly } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import React, { useEffect, useRef } from 'react'; -import { expandLiteralStrings } from '../../../../../../../es_ui_shared/public'; +import { expandLiteralStrings } from '../../../../../shared_imports'; import { useEditorReadContext, useRequestReadContext, diff --git a/src/plugins/console/public/application/hooks/use_send_current_request_to_es/send_request_to_es.ts b/src/plugins/console/public/application/hooks/use_send_current_request_to_es/send_request_to_es.ts index cfbd5691bc22b..d01adf332e24a 100644 --- a/src/plugins/console/public/application/hooks/use_send_current_request_to_es/send_request_to_es.ts +++ b/src/plugins/console/public/application/hooks/use_send_current_request_to_es/send_request_to_es.ts @@ -18,7 +18,8 @@ */ import { extractDeprecationMessages } from '../../../lib/utils'; -import { collapseLiteralStrings } from '../../../../../es_ui_shared/public'; +import { XJson } from '../../../../../es_ui_shared/public'; +const { collapseLiteralStrings } = XJson; // @ts-ignore import * as es from '../../../lib/es/es'; import { BaseResponseType } from '../../../types'; diff --git a/src/plugins/console/public/application/models/legacy_core_editor/legacy_core_editor.ts b/src/plugins/console/public/application/models/legacy_core_editor/legacy_core_editor.ts index 469ef6d79fae5..393b7eee346f5 100644 --- a/src/plugins/console/public/application/models/legacy_core_editor/legacy_core_editor.ts +++ b/src/plugins/console/public/application/models/legacy_core_editor/legacy_core_editor.ts @@ -408,4 +408,8 @@ export class LegacyCoreEditor implements CoreEditor { }, ]); } + + destroy() { + this.editor.destroy(); + } } diff --git a/src/plugins/console/public/application/models/legacy_core_editor/mode/input_highlight_rules.js b/src/plugins/console/public/application/models/legacy_core_editor/mode/input_highlight_rules.js index 1558cf0cb5554..bc0129850f299 100644 --- a/src/plugins/console/public/application/models/legacy_core_editor/mode/input_highlight_rules.js +++ b/src/plugins/console/public/application/models/legacy_core_editor/mode/input_highlight_rules.js @@ -18,7 +18,7 @@ */ import ace from 'brace'; -import { addXJsonToRules } from '../../../../../../es_ui_shared/public'; +import { addXJsonToRules } from '@kbn/ace'; export function addEOL(tokens, reg, nextIfEOL, normalNext) { if (typeof reg === 'object') { diff --git a/src/plugins/console/public/application/models/legacy_core_editor/mode/output_highlight_rules.js b/src/plugins/console/public/application/models/legacy_core_editor/mode/output_highlight_rules.js index 448fd847aeacd..2f39689319389 100644 --- a/src/plugins/console/public/application/models/legacy_core_editor/mode/output_highlight_rules.js +++ b/src/plugins/console/public/application/models/legacy_core_editor/mode/output_highlight_rules.js @@ -19,7 +19,7 @@ import ace from 'brace'; import 'brace/mode/json'; -import { addXJsonToRules } from '../../../../../../es_ui_shared/public'; +import { addXJsonToRules } from '@kbn/ace'; const oop = ace.acequire('ace/lib/oop'); const JsonHighlightRules = ace.acequire('ace/mode/json_highlight_rules').JsonHighlightRules; diff --git a/src/plugins/console/public/application/models/legacy_core_editor/mode/script.js b/src/plugins/console/public/application/models/legacy_core_editor/mode/script.js index 6079c9db40eef..03d5b10f82d01 100644 --- a/src/plugins/console/public/application/models/legacy_core_editor/mode/script.js +++ b/src/plugins/console/public/application/models/legacy_core_editor/mode/script.js @@ -18,7 +18,7 @@ */ import ace from 'brace'; -import { ScriptHighlightRules } from '../../../../../../es_ui_shared/public'; +import { ScriptHighlightRules } from '@kbn/ace'; const oop = ace.acequire('ace/lib/oop'); const TextMode = ace.acequire('ace/mode/text').Mode; diff --git a/src/plugins/console/public/application/models/sense_editor/__tests__/sense_editor.test.js b/src/plugins/console/public/application/models/sense_editor/__tests__/sense_editor.test.js index c3fb879f2eeeb..04d3cd1a724e1 100644 --- a/src/plugins/console/public/application/models/sense_editor/__tests__/sense_editor.test.js +++ b/src/plugins/console/public/application/models/sense_editor/__tests__/sense_editor.test.js @@ -22,9 +22,11 @@ import $ from 'jquery'; import _ from 'lodash'; import { create } from '../create'; -import { collapseLiteralStrings } from '../../../../../../es_ui_shared/public'; +import { XJson } from '../../../../../../es_ui_shared/public'; import editorInput1 from './editor_input1.txt'; +const { collapseLiteralStrings } = XJson; + describe('Editor', () => { let input; diff --git a/src/plugins/console/public/application/models/sense_editor/sense_editor.ts b/src/plugins/console/public/application/models/sense_editor/sense_editor.ts index dbf4f1adcba0a..66324050bc2fa 100644 --- a/src/plugins/console/public/application/models/sense_editor/sense_editor.ts +++ b/src/plugins/console/public/application/models/sense_editor/sense_editor.ts @@ -19,7 +19,7 @@ import _ from 'lodash'; import RowParser from '../../../lib/row_parser'; -import { collapseLiteralStrings } from '../../../../../es_ui_shared/public'; +import { XJson } from '../../../../../es_ui_shared/public'; import * as utils from '../../../lib/utils'; // @ts-ignore @@ -30,6 +30,8 @@ import { createTokenIterator } from '../../factories'; import Autocomplete from '../../../lib/autocomplete/autocomplete'; +const { collapseLiteralStrings } = XJson; + export class SenseEditor { currentReqRange: (Range & { markerRef: any }) | null; parser: any; diff --git a/src/plugins/console/public/lib/utils/index.ts b/src/plugins/console/public/lib/utils/index.ts index 917988e0e811b..b95680e5df47e 100644 --- a/src/plugins/console/public/lib/utils/index.ts +++ b/src/plugins/console/public/lib/utils/index.ts @@ -18,7 +18,9 @@ */ import _ from 'lodash'; -import { expandLiteralStrings, collapseLiteralStrings } from '../../../../es_ui_shared/public'; +import { XJson } from '../../../../es_ui_shared/public'; + +const { collapseLiteralStrings, expandLiteralStrings } = XJson; export function textFromRequest(request: any) { let data = request.data; diff --git a/src/plugins/console/public/shared_imports.ts b/src/plugins/console/public/shared_imports.ts index aa64091903fb7..36c50f9c51e0d 100644 --- a/src/plugins/console/public/shared_imports.ts +++ b/src/plugins/console/public/shared_imports.ts @@ -17,6 +17,8 @@ * under the License. */ -import { sendRequest } from '../../es_ui_shared/public'; +import { sendRequest, XJson } from '../../es_ui_shared/public'; -export { sendRequest }; +const { collapseLiteralStrings, expandLiteralStrings } = XJson; + +export { sendRequest, collapseLiteralStrings, expandLiteralStrings }; diff --git a/src/plugins/console/public/types/core_editor.ts b/src/plugins/console/public/types/core_editor.ts index b71f4fff44ca5..d88d8f86b874c 100644 --- a/src/plugins/console/public/types/core_editor.ts +++ b/src/plugins/console/public/types/core_editor.ts @@ -268,4 +268,9 @@ export interface CoreEditor { * detects a change */ registerAutocompleter(autocompleter: AutoCompleterFunction): void; + + /** + * Release any resources in use by the editor. + */ + destroy(): void; } diff --git a/src/plugins/console/server/lib/spec_definitions/js/mappings.ts b/src/plugins/console/server/lib/spec_definitions/js/mappings.ts index aa09278d07553..e6b3d4d5fcb6e 100644 --- a/src/plugins/console/server/lib/spec_definitions/js/mappings.ts +++ b/src/plugins/console/server/lib/spec_definitions/js/mappings.ts @@ -157,58 +157,65 @@ export const mappings = (specService: SpecDefinitionsService) => { // dates format: { + // outer array required to for an array of string values __one_of: [ - ...[ - 'date', - 'date_time', - 'date_time_no_millis', - 'ordinal_date', - 'ordinal_date_time', - 'ordinal_date_time_no_millis', - 'time', - 'time_no_millis', - 't_time', - 't_time_no_millis', - 'week_date', - 'week_date_time', - 'week_date_time_no_millis', - ].map(function (s) { - return ['basic_' + s, 'strict_' + s]; - }), - ...[ - 'date', - 'date_hour', - 'date_hour_minute', - 'date_hour_minute_second', - 'date_hour_minute_second_fraction', - 'date_hour_minute_second_millis', - 'date_optional_time', - 'date_time', - 'date_time_no_millis', - 'hour', - 'hour_minute', - 'hour_minute_second', - 'hour_minute_second_fraction', - 'hour_minute_second_millis', - 'ordinal_date', - 'ordinal_date_time', - 'ordinal_date_time_no_millis', - 'time', - 'time_no_millis', - 't_time', - 't_time_no_millis', - 'week_date', - 'week_date_time', - 'weekDateTimeNoMillis', - 'week_year', - 'weekyearWeek', - 'weekyearWeekDay', - 'year', - 'year_month', - 'year_month_day', - 'epoch_millis', - 'epoch_second', - ], + [ + ...[ + 'date', + 'date_time', + 'date_time_no_millis', + 'ordinal_date', + 'ordinal_date_time', + 'ordinal_date_time_no_millis', + 'time', + 'time_no_millis', + 't_time', + 't_time_no_millis', + 'week_date', + 'week_date_time', + 'week_date_time_no_millis', + ].flatMap(function (s) { + return ['basic_' + s, 'strict_' + s]; + }), + ...[ + 'date', + 'date_hour', + 'date_hour_minute', + 'date_hour_minute_second', + 'date_hour_minute_second_fraction', + 'date_hour_minute_second_millis', + 'date_optional_time', + 'date_time', + 'date_time_no_millis', + 'hour', + 'hour_minute', + 'hour_minute_second', + 'hour_minute_second_fraction', + 'hour_minute_second_millis', + 'ordinal_date', + 'ordinal_date_time', + 'ordinal_date_time_no_millis', + 'time', + 'time_no_millis', + 't_time', + 't_time_no_millis', + 'week_date', + 'week_date_time', + 'weekDateTimeNoMillis', + 'weekyear', + 'strict_weekyear', + 'weekyear_week', + 'strict_weekyear_week', + 'strict_date_optional_time_nanos', + 'weekyear_week_day', + 'strict_weekyear_week_day', + 'year', + 'year_month', + 'year_month_day', + 'epoch_millis', + 'epoch_second', + ], + ].sort(), ], }, diff --git a/src/plugins/dashboard/public/application/actions/expand_panel_action.tsx b/src/plugins/dashboard/public/application/actions/expand_panel_action.tsx index d0442fbc26073..933d2766d13f4 100644 --- a/src/plugins/dashboard/public/application/actions/expand_panel_action.tsx +++ b/src/plugins/dashboard/public/application/actions/expand_panel_action.tsx @@ -57,7 +57,7 @@ export class ExpandPanelAction implements ActionByType { return ( + embeddable.getRoot().isContainer && embeddable.getInput()?.viewMode !== ViewMode.VIEW && isReferenceOrValueEmbeddable(embeddable) && embeddable.inputIsRefType(embeddable.getInput()) diff --git a/src/plugins/dashboard/public/application/dashboard_app_controller.tsx b/src/plugins/dashboard/public/application/dashboard_app_controller.tsx index dd5eb1ee5ccaa..2ae7c6550b0cc 100644 --- a/src/plugins/dashboard/public/application/dashboard_app_controller.tsx +++ b/src/plugins/dashboard/public/application/dashboard_app_controller.tsx @@ -66,7 +66,6 @@ import { ViewMode, ContainerOutput, EmbeddableInput, - SavedObjectEmbeddableInput, } from '../../../embeddable/public'; import { NavAction, SavedDashboardPanel } from '../types'; @@ -82,7 +81,7 @@ import { getDashboardTitle } from './dashboard_strings'; import { DashboardAppScope } from './dashboard_app'; import { convertSavedDashboardPanelToPanelState } from './lib/embeddable_saved_object_converters'; import { RenderDeps } from './application'; -import { IKbnUrlStateStorage, unhashUrl } from '../../../kibana_utils/public'; +import { IKbnUrlStateStorage, setStateToKbnUrl, unhashUrl } from '../../../kibana_utils/public'; import { addFatalError, AngularHttpError, @@ -178,7 +177,7 @@ export class DashboardAppController { chrome.docTitle.change(dash.title); } - const incomingEmbeddable = embeddable + let incomingEmbeddable = embeddable .getStateTransfer(scopedHistory()) .getIncomingEmbeddablePackage(); @@ -344,10 +343,22 @@ export class DashboardAppController { dashboardStateManager.getPanels().forEach((panel: SavedDashboardPanel) => { embeddablesMap[panel.panelIndex] = convertSavedDashboardPanelToPanelState(panel); }); - let expandedPanelId; - if (dashboardContainer && !isErrorEmbeddable(dashboardContainer)) { - expandedPanelId = dashboardContainer.getInput().expandedPanelId; + + // If the incoming embeddable state's id already exists in the embeddables map, replace the input, retaining the existing gridData for that panel. + if (incomingEmbeddable?.embeddableId && embeddablesMap[incomingEmbeddable.embeddableId]) { + const originalPanelState = embeddablesMap[incomingEmbeddable.embeddableId]; + embeddablesMap[incomingEmbeddable.embeddableId] = { + gridData: originalPanelState.gridData, + type: incomingEmbeddable.type, + explicitInput: { + ...originalPanelState.explicitInput, + ...incomingEmbeddable.input, + id: incomingEmbeddable.embeddableId, + }, + }; + incomingEmbeddable = undefined; } + const shouldShowEditHelp = getShouldShowEditHelp(); const shouldShowViewHelp = getShouldShowViewHelp(); const isEmptyInReadonlyMode = shouldShowUnauthorizedEmptyState(); @@ -369,7 +380,7 @@ export class DashboardAppController { lastReloadRequestTime, title: dashboardStateManager.getTitle(), description: dashboardStateManager.getDescription(), - expandedPanelId, + expandedPanelId: dashboardStateManager.getExpandedPanelId(), }; }; @@ -482,32 +493,16 @@ export class DashboardAppController { refreshDashboardContainer(); }); - if (incomingEmbeddable) { - if ('id' in incomingEmbeddable) { - container.addOrUpdateEmbeddable( - incomingEmbeddable.type, - { - savedObjectId: incomingEmbeddable.id, - } - ); - } else if ('input' in incomingEmbeddable) { - const input = incomingEmbeddable.input; - // @ts-expect-error - delete input.id; - const explicitInput = { - savedVis: input, - }; - const embeddableId = - 'embeddableId' in incomingEmbeddable - ? incomingEmbeddable.embeddableId - : undefined; - container.addOrUpdateEmbeddable( - incomingEmbeddable.type, - // This ugly solution is temporary - https://github.com/elastic/kibana/pull/70272 fixes this whole section - (explicitInput as unknown) as EmbeddableInput, - embeddableId - ); - } + // If the incomingEmbeddable does not yet exist in the panels listing, create a new panel using the container's addEmbeddable method. + if ( + incomingEmbeddable && + (!incomingEmbeddable.embeddableId || + !container.getInput().panels[incomingEmbeddable.embeddableId]) + ) { + container.addNewEmbeddable( + incomingEmbeddable.type, + incomingEmbeddable.input + ); } } @@ -1084,7 +1079,12 @@ export class DashboardAppController { allowEmbed: true, allowShortUrl: !dashboardConfig.getHideWriteControls() || dashboardCapabilities.createShortUrl, - shareableUrl: unhashUrl(window.location.href), + shareableUrl: setStateToKbnUrl( + '_a', + dashboardStateManager.getAppState(), + { useHash: false, storeInHashQuery: true }, + unhashUrl(window.location.href) + ), objectId: dash.id, objectType: 'dashboard', sharingData: { diff --git a/src/plugins/dashboard/public/application/dashboard_state.test.ts b/src/plugins/dashboard/public/application/dashboard_state.test.ts index e32bb9b9ecabe..42425ebf2cacf 100644 --- a/src/plugins/dashboard/public/application/dashboard_state.test.ts +++ b/src/plugins/dashboard/public/application/dashboard_state.test.ts @@ -23,6 +23,9 @@ import { getSavedDashboardMock } from './test_helpers'; import { InputTimeRange, TimefilterContract, TimeRange } from 'src/plugins/data/public'; import { ViewMode } from 'src/plugins/embeddable/public'; import { createKbnUrlStateStorage } from 'src/plugins/kibana_utils/public'; +import { DashboardContainer, DashboardContainerInput } from '.'; +import { DashboardContainerOptions } from './embeddable/dashboard_container'; +import { embeddablePluginMock } from '../../../embeddable/public/mocks'; describe('DashboardState', function () { let dashboardState: DashboardStateManager; @@ -48,6 +51,23 @@ describe('DashboardState', function () { }); } + function initDashboardContainer(initialInput?: Partial) { + const { doStart } = embeddablePluginMock.createInstance(); + const defaultInput: DashboardContainerInput = { + id: '123', + viewMode: ViewMode.EDIT, + filters: [] as DashboardContainerInput['filters'], + query: {} as DashboardContainerInput['query'], + timeRange: {} as DashboardContainerInput['timeRange'], + useMargins: true, + title: 'ultra awesome test dashboard', + isFullScreenMode: false, + panels: {} as DashboardContainerInput['panels'], + }; + const input = { ...defaultInput, ...(initialInput ?? {}) }; + return new DashboardContainer(input, { embeddable: doStart() } as DashboardContainerOptions); + } + describe('syncTimefilterWithDashboard', function () { test('syncs quick time', function () { savedDashboard.timeRestore = true; @@ -95,6 +115,43 @@ describe('DashboardState', function () { }); }); + describe('Dashboard Container Changes', () => { + beforeEach(() => { + initDashboardState(); + }); + + test('expanedPanelId in container input casues state update', () => { + dashboardState.setExpandedPanelId = jest.fn(); + + const dashboardContainer = initDashboardContainer({ + expandedPanelId: 'theCoolestPanelOnThisDashboard', + }); + + dashboardState.handleDashboardContainerChanges(dashboardContainer); + expect(dashboardState.setExpandedPanelId).toHaveBeenCalledWith( + 'theCoolestPanelOnThisDashboard' + ); + }); + + test('expanedPanelId is not updated when it is the same', () => { + dashboardState.setExpandedPanelId = jest + .fn() + .mockImplementation(dashboardState.setExpandedPanelId); + + const dashboardContainer = initDashboardContainer({ + expandedPanelId: 'theCoolestPanelOnThisDashboard', + }); + + dashboardState.handleDashboardContainerChanges(dashboardContainer); + dashboardState.handleDashboardContainerChanges(dashboardContainer); + expect(dashboardState.setExpandedPanelId).toHaveBeenCalledTimes(1); + + dashboardContainer.updateInput({ expandedPanelId: 'woah it changed' }); + dashboardState.handleDashboardContainerChanges(dashboardContainer); + expect(dashboardState.setExpandedPanelId).toHaveBeenCalledTimes(2); + }); + }); + describe('isDirty', function () { beforeAll(() => { initDashboardState(); diff --git a/src/plugins/dashboard/public/application/dashboard_state_manager.ts b/src/plugins/dashboard/public/application/dashboard_state_manager.ts index 910a2b470b2eb..93a63b0535259 100644 --- a/src/plugins/dashboard/public/application/dashboard_state_manager.ts +++ b/src/plugins/dashboard/public/application/dashboard_state_manager.ts @@ -267,6 +267,10 @@ export class DashboardStateManager { this.setFullScreenMode(input.isFullScreenMode); } + if (input.expandedPanelId !== this.getExpandedPanelId()) { + this.setExpandedPanelId(input.expandedPanelId); + } + if (!_.isEqual(input.query, this.getQuery())) { this.setQuery(input.query); } @@ -282,6 +286,14 @@ export class DashboardStateManager { this.stateContainer.transitions.set('fullScreenMode', fullScreenMode); } + public getExpandedPanelId() { + return this.appState.expandedPanelId; + } + + public setExpandedPanelId(expandedPanelId?: string) { + this.stateContainer.transitions.set('expandedPanelId', expandedPanelId); + } + public setFilters(filters: Filter[]) { this.stateContainer.transitions.set('filters', filters); } diff --git a/src/plugins/dashboard/public/application/index.ts b/src/plugins/dashboard/public/application/index.ts index fcd92da33aa5f..2558c49648b10 100644 --- a/src/plugins/dashboard/public/application/index.ts +++ b/src/plugins/dashboard/public/application/index.ts @@ -19,4 +19,4 @@ export * from './embeddable'; export * from './actions'; -export { RenderDeps } from './application'; +export type { RenderDeps } from './application'; diff --git a/src/plugins/dashboard/public/application/listing/dashboard_listing.test.js b/src/plugins/dashboard/public/application/listing/dashboard_listing.test.js index 6acb491f9a20c..99b1ebf047d74 100644 --- a/src/plugins/dashboard/public/application/listing/dashboard_listing.test.js +++ b/src/plugins/dashboard/public/application/listing/dashboard_listing.test.js @@ -20,7 +20,7 @@ jest.mock( 'lodash', () => ({ - ...require.requireActual('lodash'), + ...jest.requireActual('lodash'), // mock debounce to fire immediately with no internal timer debounce: (func) => { function debounced(...args) { diff --git a/src/plugins/dashboard/public/application/top_nav/get_top_nav_config.ts b/src/plugins/dashboard/public/application/top_nav/get_top_nav_config.ts index dbdadeb4e4e7c..5713996ca9f78 100644 --- a/src/plugins/dashboard/public/application/top_nav/get_top_nav_config.ts +++ b/src/plugins/dashboard/public/application/top_nav/get_top_nav_config.ts @@ -18,6 +18,7 @@ */ import { i18n } from '@kbn/i18n'; +import { AppMountParameters } from 'kibana/public'; import { ViewMode } from '../../embeddable_plugin'; import { TopNavIds } from './top_nav_ids'; import { NavAction } from '../../types'; @@ -31,7 +32,8 @@ import { NavAction } from '../../types'; export function getTopNavConfig( dashboardMode: ViewMode, actions: { [key: string]: NavAction }, - hideWriteControls: boolean + hideWriteControls: boolean, + onAppLeave?: AppMountParameters['onAppLeave'] ) { switch (dashboardMode) { case ViewMode.VIEW: @@ -48,12 +50,12 @@ export function getTopNavConfig( ]; case ViewMode.EDIT: return [ - getCreateNewConfig(actions[TopNavIds.VISUALIZE]), - getSaveConfig(actions[TopNavIds.SAVE]), - getViewConfig(actions[TopNavIds.EXIT_EDIT_MODE]), - getAddConfig(actions[TopNavIds.ADD_EXISTING]), getOptionsConfig(actions[TopNavIds.OPTIONS]), getShareConfig(actions[TopNavIds.SHARE]), + getAddConfig(actions[TopNavIds.ADD_EXISTING]), + getViewConfig(actions[TopNavIds.EXIT_EDIT_MODE]), + getSaveConfig(actions[TopNavIds.SAVE]), + getCreateNewConfig(actions[TopNavIds.VISUALIZE]), ]; default: return []; @@ -79,7 +81,9 @@ function getFullScreenConfig(action: NavAction) { */ function getEditConfig(action: NavAction) { return { + emphasize: true, id: 'edit', + iconType: 'pencil', label: i18n.translate('dashboard.topNave.editButtonAriaLabel', { defaultMessage: 'edit', }), @@ -168,7 +172,7 @@ function getAddConfig(action: NavAction) { function getCreateNewConfig(action: NavAction) { return { emphasize: true, - iconType: 'plusInCircle', + iconType: 'plusInCircleFilled', id: 'addNew', label: i18n.translate('dashboard.topNave.addNewButtonAriaLabel', { defaultMessage: 'Create new', diff --git a/src/plugins/dashboard/public/attribute_service/attribute_service.test.ts b/src/plugins/dashboard/public/attribute_service/attribute_service.test.ts deleted file mode 100644 index 06f380ca3862b..0000000000000 --- a/src/plugins/dashboard/public/attribute_service/attribute_service.test.ts +++ /dev/null @@ -1,193 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { ATTRIBUTE_SERVICE_KEY } from './attribute_service'; -import { mockAttributeService } from './attribute_service_mock'; -import { coreMock } from '../../../../core/public/mocks'; - -interface TestAttributes { - title: string; - testAttr1?: string; - testAttr2?: { array: unknown[]; testAttr3: string }; -} - -interface TestByValueInput { - id: string; - [ATTRIBUTE_SERVICE_KEY]: TestAttributes; -} - -describe('attributeService', () => { - const defaultTestType = 'defaultTestType'; - let attributes: TestAttributes; - let byValueInput: TestByValueInput; - let byReferenceInput: { id: string; savedObjectId: string }; - - beforeEach(() => { - attributes = { - title: 'ultra title', - testAttr1: 'neat first attribute', - testAttr2: { array: [1, 2, 3], testAttr3: 'super attribute' }, - }; - byValueInput = { - id: '456', - attributes, - }; - byReferenceInput = { - id: '456', - savedObjectId: '123', - }; - }); - - describe('determining input type', () => { - const defaultAttributeService = mockAttributeService(defaultTestType); - const customAttributeService = mockAttributeService( - defaultTestType - ); - - it('can determine input type given default types', () => { - expect( - defaultAttributeService.inputIsRefType({ id: '456', savedObjectId: '123' }) - ).toBeTruthy(); - expect( - defaultAttributeService.inputIsRefType({ - id: '456', - attributes: { title: 'wow I am by value' }, - }) - ).toBeFalsy(); - }); - it('can determine input type given custom types', () => { - expect( - customAttributeService.inputIsRefType({ id: '456', savedObjectId: '123' }) - ).toBeTruthy(); - expect( - customAttributeService.inputIsRefType({ - id: '456', - [ATTRIBUTE_SERVICE_KEY]: { title: 'wow I am by value' }, - }) - ).toBeFalsy(); - }); - }); - - describe('unwrapping attributes', () => { - it('can unwrap all default attributes when given reference type input', async () => { - const core = coreMock.createStart(); - core.savedObjects.client.get = jest.fn().mockResolvedValueOnce({ - attributes, - }); - const attributeService = mockAttributeService( - defaultTestType, - undefined, - core - ); - expect(await attributeService.unwrapAttributes(byReferenceInput)).toEqual(attributes); - }); - - it('returns attributes when when given value type input', async () => { - const attributeService = mockAttributeService(defaultTestType); - expect(await attributeService.unwrapAttributes(byValueInput)).toEqual(attributes); - }); - - it('runs attributes through a custom unwrap method', async () => { - const core = coreMock.createStart(); - core.savedObjects.client.get = jest.fn().mockResolvedValueOnce({ - attributes, - }); - const attributeService = mockAttributeService( - defaultTestType, - { - customUnwrapMethod: (savedObject) => ({ - ...savedObject.attributes, - testAttr2: { array: [1, 2, 3, 4, 5], testAttr3: 'kibanana' }, - }), - }, - core - ); - expect(await attributeService.unwrapAttributes(byReferenceInput)).toEqual({ - ...attributes, - testAttr2: { array: [1, 2, 3, 4, 5], testAttr3: 'kibanana' }, - }); - }); - }); - - describe('wrapping attributes', () => { - it('returns given attributes when use ref type is false', async () => { - const attributeService = mockAttributeService(defaultTestType); - expect(await attributeService.wrapAttributes(attributes, false)).toEqual({ attributes }); - }); - - it('updates existing saved object with new attributes when given id', async () => { - const core = coreMock.createStart(); - const attributeService = mockAttributeService( - defaultTestType, - undefined, - core - ); - expect(await attributeService.wrapAttributes(attributes, true, byReferenceInput)).toEqual( - byReferenceInput - ); - expect(core.savedObjects.client.update).toHaveBeenCalledWith( - defaultTestType, - '123', - attributes - ); - }); - - it('creates new saved object with attributes when given no id', async () => { - const core = coreMock.createStart(); - core.savedObjects.client.create = jest.fn().mockResolvedValueOnce({ - id: '678', - }); - const attributeService = mockAttributeService( - defaultTestType, - undefined, - core - ); - expect(await attributeService.wrapAttributes(attributes, true)).toEqual({ - savedObjectId: '678', - }); - expect(core.savedObjects.client.create).toHaveBeenCalledWith(defaultTestType, attributes); - }); - - it('uses custom save method when given an id', async () => { - const customSaveMethod = jest.fn().mockReturnValue({ id: '123' }); - const attributeService = mockAttributeService(defaultTestType, { - customSaveMethod, - }); - expect(await attributeService.wrapAttributes(attributes, true, byReferenceInput)).toEqual( - byReferenceInput - ); - expect(customSaveMethod).toHaveBeenCalledWith( - defaultTestType, - attributes, - byReferenceInput.savedObjectId - ); - }); - - it('uses custom save method given no id', async () => { - const customSaveMethod = jest.fn().mockReturnValue({ id: '678' }); - const attributeService = mockAttributeService(defaultTestType, { - customSaveMethod, - }); - expect(await attributeService.wrapAttributes(attributes, true)).toEqual({ - savedObjectId: '678', - }); - expect(customSaveMethod).toHaveBeenCalledWith(defaultTestType, attributes, undefined); - }); - }); -}); diff --git a/src/plugins/dashboard/public/attribute_service/attribute_service.tsx b/src/plugins/dashboard/public/attribute_service/attribute_service.tsx deleted file mode 100644 index 84df05154fb63..0000000000000 --- a/src/plugins/dashboard/public/attribute_service/attribute_service.tsx +++ /dev/null @@ -1,229 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import React from 'react'; -import { i18n } from '@kbn/i18n'; -import { get } from 'lodash'; -import { - EmbeddableInput, - SavedObjectEmbeddableInput, - isSavedObjectEmbeddableInput, - IEmbeddable, - Container, - EmbeddableStart, - EmbeddableFactory, - EmbeddableFactoryNotFoundError, -} from '../embeddable_plugin'; -import { - SavedObjectsClientContract, - SimpleSavedObject, - I18nStart, - NotificationsStart, - OverlayStart, -} from '../../../../core/public'; -import { - SavedObjectSaveModal, - OnSaveProps, - SaveResult, - checkForDuplicateTitle, -} from '../../../saved_objects/public'; - -/** - * The attribute service is a shared, generic service that embeddables can use to provide the functionality - * required to fulfill the requirements of the ReferenceOrValueEmbeddable interface. The attribute_service - * can also be used as a higher level wrapper to transform an embeddable input shape that references a saved object - * into an embeddable input shape that contains that saved object's attributes by value. - */ -export const ATTRIBUTE_SERVICE_KEY = 'attributes'; - -export interface AttributeServiceOptions { - customSaveMethod?: ( - type: string, - attributes: A, - savedObjectId?: string - ) => Promise<{ id?: string } | { error: Error }>; - customUnwrapMethod?: (savedObject: SimpleSavedObject) => A; -} - -export class AttributeService< - SavedObjectAttributes extends { title: string }, - ValType extends EmbeddableInput & { - [ATTRIBUTE_SERVICE_KEY]: SavedObjectAttributes; - } = EmbeddableInput & { [ATTRIBUTE_SERVICE_KEY]: SavedObjectAttributes }, - RefType extends SavedObjectEmbeddableInput = SavedObjectEmbeddableInput -> { - private embeddableFactory?: EmbeddableFactory; - - constructor( - private type: string, - private showSaveModal: ( - saveModal: React.ReactElement, - I18nContext: I18nStart['Context'] - ) => void, - private savedObjectsClient: SavedObjectsClientContract, - private overlays: OverlayStart, - private i18nContext: I18nStart['Context'], - private toasts: NotificationsStart['toasts'], - getEmbeddableFactory?: EmbeddableStart['getEmbeddableFactory'], - private options?: AttributeServiceOptions - ) { - if (getEmbeddableFactory) { - const factory = getEmbeddableFactory(this.type); - if (!factory) { - throw new EmbeddableFactoryNotFoundError(this.type); - } - this.embeddableFactory = factory; - } - } - - public async unwrapAttributes(input: RefType | ValType): Promise { - if (this.inputIsRefType(input)) { - const savedObject: SimpleSavedObject = await this.savedObjectsClient.get< - SavedObjectAttributes - >(this.type, input.savedObjectId); - return this.options?.customUnwrapMethod - ? this.options?.customUnwrapMethod(savedObject) - : { ...savedObject.attributes }; - } - return input[ATTRIBUTE_SERVICE_KEY]; - } - - public async wrapAttributes( - newAttributes: SavedObjectAttributes, - useRefType: boolean, - input?: ValType | RefType - ): Promise> { - const originalInput = input ? input : {}; - const savedObjectId = - input && this.inputIsRefType(input) - ? (input as SavedObjectEmbeddableInput).savedObjectId - : undefined; - if (!useRefType) { - return { [ATTRIBUTE_SERVICE_KEY]: newAttributes } as ValType; - } - try { - if (this.options?.customSaveMethod) { - const savedItem = await this.options.customSaveMethod( - this.type, - newAttributes, - savedObjectId - ); - if ('id' in savedItem) { - return { ...originalInput, savedObjectId: savedItem.id } as RefType; - } - return { ...originalInput } as RefType; - } - - if (savedObjectId) { - await this.savedObjectsClient.update(this.type, savedObjectId, newAttributes); - return { ...originalInput, savedObjectId } as RefType; - } - - const savedItem = await this.savedObjectsClient.create(this.type, newAttributes); - return { ...originalInput, savedObjectId: savedItem.id } as RefType; - } catch (error) { - this.toasts.addDanger({ - title: i18n.translate('dashboard.attributeService.saveToLibraryError', { - defaultMessage: `Panel was not saved to the library. Error: {errorMessage}`, - values: { - errorMessage: error.message, - }, - }), - 'data-test-subj': 'saveDashboardFailure', - }); - return Promise.reject({ error }); - } - } - - inputIsRefType = (input: ValType | RefType): input is RefType => { - return isSavedObjectEmbeddableInput(input); - }; - - public getExplicitInputFromEmbeddable(embeddable: IEmbeddable): ValType | RefType { - return embeddable.getRoot() && - (embeddable.getRoot() as Container).getInput().panels[embeddable.id].explicitInput - ? ((embeddable.getRoot() as Container).getInput().panels[embeddable.id].explicitInput as - | ValType - | RefType) - : (embeddable.getInput() as ValType | RefType); - } - - getInputAsValueType = async (input: ValType | RefType): Promise => { - if (!this.inputIsRefType(input)) { - return input; - } - const attributes = await this.unwrapAttributes(input); - return { - ...input, - savedObjectId: undefined, - attributes, - }; - }; - - getInputAsRefType = async ( - input: ValType | RefType, - saveOptions?: { showSaveModal: boolean; saveModalTitle?: string } | { title: string } - ): Promise => { - if (this.inputIsRefType(input)) { - return input; - } - return new Promise((resolve, reject) => { - const onSave = async (props: OnSaveProps): Promise => { - await checkForDuplicateTitle( - { - title: props.newTitle, - copyOnSave: false, - lastSavedTitle: '', - getEsType: () => this.type, - getDisplayName: this.embeddableFactory?.getDisplayName || (() => this.type), - }, - props.isTitleDuplicateConfirmed, - props.onTitleDuplicate, - { - savedObjectsClient: this.savedObjectsClient, - overlays: this.overlays, - } - ); - try { - const newAttributes = { ...input[ATTRIBUTE_SERVICE_KEY] }; - newAttributes.title = props.newTitle; - const wrappedInput = (await this.wrapAttributes(newAttributes, true)) as RefType; - resolve(wrappedInput); - return { id: wrappedInput.savedObjectId }; - } catch (error) { - reject(error); - return { error }; - } - }; - if (saveOptions && (saveOptions as { showSaveModal: boolean }).showSaveModal) { - this.showSaveModal( - reject()} - title={get(saveOptions, 'saveModalTitle', input[ATTRIBUTE_SERVICE_KEY].title)} - showCopyOnSave={false} - objectType={this.type} - showDescription={false} - />, - this.i18nContext - ); - } - }); - }; -} diff --git a/src/plugins/dashboard/public/attribute_service/attribute_service_mock.tsx b/src/plugins/dashboard/public/attribute_service/attribute_service_mock.tsx deleted file mode 100644 index 321a53361fc7a..0000000000000 --- a/src/plugins/dashboard/public/attribute_service/attribute_service_mock.tsx +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { EmbeddableInput, SavedObjectEmbeddableInput } from '../embeddable_plugin'; -import { coreMock } from '../../../../core/public/mocks'; -import { AttributeServiceOptions } from './attribute_service'; -import { CoreStart } from '../../../../core/public'; -import { AttributeService, ATTRIBUTE_SERVICE_KEY } from '..'; - -export const mockAttributeService = < - A extends { title: string }, - V extends EmbeddableInput & { [ATTRIBUTE_SERVICE_KEY]: A } = EmbeddableInput & { - [ATTRIBUTE_SERVICE_KEY]: A; - }, - R extends SavedObjectEmbeddableInput = SavedObjectEmbeddableInput ->( - type: string, - options?: AttributeServiceOptions, - customCore?: jest.Mocked -): AttributeService => { - const core = customCore ? customCore : coreMock.createStart(); - const service = new AttributeService( - type, - jest.fn(), - core.savedObjects.client, - core.overlays, - core.i18n.Context, - core.notifications.toasts, - jest.fn().mockReturnValue(() => ({ getDisplayName: () => type })), - options - ); - return service; -}; diff --git a/src/plugins/dashboard/public/index.ts b/src/plugins/dashboard/public/index.ts index e22d1f038a456..004b1a901bca9 100644 --- a/src/plugins/dashboard/public/index.ts +++ b/src/plugins/dashboard/public/index.ts @@ -31,7 +31,12 @@ export { } from './application'; export { DashboardConstants, createDashboardEditUrl } from './dashboard_constants'; -export { DashboardStart, DashboardUrlGenerator } from './plugin'; +export { + DashboardSetup, + DashboardStart, + DashboardUrlGenerator, + DashboardFeatureFlagConfig, +} from './plugin'; export { DASHBOARD_APP_URL_GENERATOR, createDashboardUrlGenerator, @@ -40,7 +45,6 @@ export { export { addEmbeddableToDashboardUrl } from './url_utils/url_helper'; export { SavedObjectDashboard } from './saved_dashboards'; export { SavedDashboardPanel } from './types'; -export { AttributeService, ATTRIBUTE_SERVICE_KEY } from './attribute_service/attribute_service'; export function plugin(initializerContext: PluginInitializerContext) { return new DashboardPlugin(initializerContext); diff --git a/src/plugins/dashboard/public/mocks.tsx b/src/plugins/dashboard/public/mocks.tsx index ba30d72594f2a..be7460f3110a5 100644 --- a/src/plugins/dashboard/public/mocks.tsx +++ b/src/plugins/dashboard/public/mocks.tsx @@ -23,9 +23,7 @@ export type Start = jest.Mocked; const createStartContract = (): DashboardStart => { // @ts-ignore - const startContract: DashboardStart = { - getAttributeService: jest.fn(), - }; + const startContract: DashboardStart = {}; return startContract; }; diff --git a/src/plugins/dashboard/public/plugin.tsx b/src/plugins/dashboard/public/plugin.tsx index 5a45229a58a7d..2fda8008788e6 100644 --- a/src/plugins/dashboard/public/plugin.tsx +++ b/src/plugins/dashboard/public/plugin.tsx @@ -39,8 +39,6 @@ import { CONTEXT_MENU_TRIGGER, EmbeddableSetup, EmbeddableStart, - SavedObjectEmbeddableInput, - EmbeddableInput, PANEL_NOTIFICATION_TRIGGER, } from '../../embeddable/public'; import { DataPublicPluginSetup, DataPublicPluginStart, esFilters } from '../../data/public'; @@ -53,7 +51,6 @@ import { getSavedObjectFinder, SavedObjectLoader, SavedObjectsStart, - showSaveModal, } from '../../saved_objects/public'; import { ExitFullScreenButton as ExitFullScreenButtonUi, @@ -103,11 +100,6 @@ import { DashboardConstants } from './dashboard_constants'; import { addEmbeddableToDashboardUrl } from './url_utils/url_helper'; import { PlaceholderEmbeddableFactory } from './application/embeddable/placeholder'; import { UrlGeneratorState } from '../../share/public'; -import { AttributeService } from '.'; -import { - AttributeServiceOptions, - ATTRIBUTE_SERVICE_KEY, -} from './attribute_service/attribute_service'; declare module '../../share/public' { export interface UrlGeneratorStateMapping { @@ -117,7 +109,7 @@ declare module '../../share/public' { export type DashboardUrlGenerator = UrlGeneratorContract; -interface DashboardFeatureFlagConfig { +export interface DashboardFeatureFlagConfig { allowByValueEmbeddables: boolean; } @@ -145,7 +137,7 @@ interface StartDependencies { savedObjects: SavedObjectsStart; } -export type Setup = void; +export type DashboardSetup = void; export interface DashboardStart { getSavedDashboardLoader: () => SavedObjectLoader; @@ -156,16 +148,6 @@ export interface DashboardStart { dashboardUrlGenerator?: DashboardUrlGenerator; dashboardFeatureFlagConfig: DashboardFeatureFlagConfig; DashboardContainerByValueRenderer: ReturnType; - getAttributeService: < - A extends { title: string }, - V extends EmbeddableInput & { [ATTRIBUTE_SERVICE_KEY]: A } = EmbeddableInput & { - [ATTRIBUTE_SERVICE_KEY]: A; - }, - R extends SavedObjectEmbeddableInput = SavedObjectEmbeddableInput - >( - type: string, - options?: AttributeServiceOptions - ) => AttributeService; } declare module '../../../plugins/ui_actions/public' { @@ -180,7 +162,7 @@ declare module '../../../plugins/ui_actions/public' { } export class DashboardPlugin - implements Plugin { + implements Plugin { constructor(private initializerContext: PluginInitializerContext) {} private appStateUpdater = new BehaviorSubject(() => ({})); @@ -193,17 +175,8 @@ export class DashboardPlugin public setup( core: CoreSetup, - { - share, - uiActions, - embeddable, - home, - kibanaLegacy, - urlForwarding, - data, - usageCollection, - }: SetupDependencies - ): Setup { + { share, uiActions, embeddable, home, urlForwarding, data, usageCollection }: SetupDependencies + ): DashboardSetup { this.dashboardFeatureFlagConfig = this.initializerContext.config.get< DashboardFeatureFlagConfig >(); @@ -404,6 +377,9 @@ export class DashboardPlugin title: i18n.translate('dashboard.featureCatalogue.dashboardTitle', { defaultMessage: 'Dashboard', }), + subtitle: i18n.translate('dashboard.featureCatalogue.dashboardSubtitle', { + defaultMessage: 'Analyze data in dashboards.', + }), description: i18n.translate('dashboard.featureCatalogue.dashboardDescription', { defaultMessage: 'Display and share a collection of visualizations and saved searches.', }), @@ -411,6 +387,8 @@ export class DashboardPlugin path: `/app/dashboards#${DashboardConstants.LANDING_PAGE_PATH}`, showOnHomePage: false, category: FeatureCatalogueCategory.DATA, + solutionId: 'kibana', + order: 100, }); } } @@ -437,7 +415,6 @@ export class DashboardPlugin const { uiActions, data: { indexPatterns, search }, - embeddable, } = plugins; const SavedObjectFinder = getSavedObjectFinder(core.savedObjects, core.uiSettings); @@ -487,17 +464,6 @@ export class DashboardPlugin DashboardContainerByValueRenderer: createDashboardContainerByValueRenderer({ factory: dashboardContainerFactory, }), - getAttributeService: (type: string, options) => - new AttributeService( - type, - showSaveModal, - core.savedObjects.client, - core.overlays, - core.i18n.Context, - core.notifications.toasts, - embeddable.getEmbeddableFactory, - options - ), }; } diff --git a/src/plugins/dashboard/public/types.ts b/src/plugins/dashboard/public/types.ts index 21c6bbc1bfc51..2764f4b075579 100644 --- a/src/plugins/dashboard/public/types.ts +++ b/src/plugins/dashboard/public/types.ts @@ -89,6 +89,7 @@ export interface DashboardAppState { query: Query | string; filters: Filter[]; viewMode: ViewMode; + expandedPanelId?: string; savedQuery?: string; } diff --git a/src/plugins/dashboard/public/url_utils/url_helper.test.ts b/src/plugins/dashboard/public/url_utils/url_helper.test.ts index 28d4ab032c33d..d2210e7380667 100644 --- a/src/plugins/dashboard/public/url_utils/url_helper.test.ts +++ b/src/plugins/dashboard/public/url_utils/url_helper.test.ts @@ -24,16 +24,17 @@ describe('', () => { const id = '123eb456cd'; const url = "/pep/app/dashboards#/create?_g=(refreshInterval:(pause:!t,value:0),time:(from:now-15m,to:now))&_a=(description:'',filters:!())"; - expect(addEmbeddableToDashboardUrl(url, id, 'visualization')).toEqual( - `/pep/app/dashboards#/create?_a=%28description%3A%27%27%2Cfilters%3A%21%28%29%29&_g=%28refreshInterval%3A%28pause%3A%21t%2Cvalue%3A0%29%2Ctime%3A%28from%3Anow-15m%2Cto%3Anow%29%29&addEmbeddableId=${id}&addEmbeddableType=visualization` + + expect(addEmbeddableToDashboardUrl(url, id, 'visualization')).toBe( + '/pep/app/dashboards?addEmbeddableId=123eb456cd&addEmbeddableType=visualization#%2Fcreate%3F_g%3D%28refreshInterval%3A%28pause%3A%21t%2Cvalue%3A0%29%2Ctime%3A%28from%3Anow-15m%2Cto%3Anow%29%29%26_a%3D%28description%3A%27%27%2Cfilters%3A%21%28%29%29' ); }); it('addEmbeddableToDashboardUrl when dashboard is saved', () => { const id = '123eb456cd'; const url = "/pep/app/dashboards#/view/9b780cd0-3dd3-11e8-b2b9-5d5dc1715159?_g=(refreshInterval:(pause:!t,value:0),time:(from:now-15m,to:now))&_a=(description:'',filters:!())"; - expect(addEmbeddableToDashboardUrl(url, id, 'visualization')).toEqual( - `/pep/app/dashboards#/view/9b780cd0-3dd3-11e8-b2b9-5d5dc1715159?_a=%28description%3A%27%27%2Cfilters%3A%21%28%29%29&_g=%28refreshInterval%3A%28pause%3A%21t%2Cvalue%3A0%29%2Ctime%3A%28from%3Anow-15m%2Cto%3Anow%29%29&addEmbeddableId=${id}&addEmbeddableType=visualization` + expect(addEmbeddableToDashboardUrl(url, id, 'visualization')).toBe( + '/pep/app/dashboards?addEmbeddableId=123eb456cd&addEmbeddableType=visualization#%2Fview%2F9b780cd0-3dd3-11e8-b2b9-5d5dc1715159%3F_g%3D%28refreshInterval%3A%28pause%3A%21t%2Cvalue%3A0%29%2Ctime%3A%28from%3Anow-15m%2Cto%3Anow%29%29%26_a%3D%28description%3A%27%27%2Cfilters%3A%21%28%29%29' ); }); }); diff --git a/src/plugins/dashboard/public/url_utils/url_helper.ts b/src/plugins/dashboard/public/url_utils/url_helper.ts index 61737e81cf24d..1f4706f0b8a4d 100644 --- a/src/plugins/dashboard/public/url_utils/url_helper.ts +++ b/src/plugins/dashboard/public/url_utils/url_helper.ts @@ -17,7 +17,7 @@ * under the License. */ -import { parseUrl, stringify } from 'query-string'; +import { parseUrl, stringifyUrl } from 'query-string'; import { DashboardConstants } from '../index'; /** * @@ -34,12 +34,14 @@ export function addEmbeddableToDashboardUrl( embeddableId: string, embeddableType: string ) { - const { url, query } = parseUrl(dashboardUrl); + const { url, query, fragmentIdentifier } = parseUrl(dashboardUrl, { + parseFragmentIdentifier: true, + }); if (embeddableId) { query[DashboardConstants.ADD_EMBEDDABLE_TYPE] = embeddableType; query[DashboardConstants.ADD_EMBEDDABLE_ID] = embeddableId; } - return `${url}?${stringify(query)}`; + return stringifyUrl({ url, query, fragmentIdentifier }); } diff --git a/src/plugins/dashboard/server/saved_objects/dashboard.ts b/src/plugins/dashboard/server/saved_objects/dashboard.ts index 850b2470dd475..a85f67f5ba56a 100644 --- a/src/plugins/dashboard/server/saved_objects/dashboard.ts +++ b/src/plugins/dashboard/server/saved_objects/dashboard.ts @@ -46,10 +46,10 @@ export const dashboardSavedObjectType: SavedObjectsType = { description: { type: 'text' }, hits: { type: 'integer', index: false, doc_values: false }, kibanaSavedObjectMeta: { - properties: { searchSourceJSON: { type: 'text', index: false, doc_values: false } }, + properties: { searchSourceJSON: { type: 'text', index: false } }, }, - optionsJSON: { type: 'text', index: false, doc_values: false }, - panelsJSON: { type: 'text', index: false, doc_values: false }, + optionsJSON: { type: 'text', index: false }, + panelsJSON: { type: 'text', index: false }, refreshInterval: { properties: { display: { type: 'keyword', index: false, doc_values: false }, diff --git a/src/plugins/dashboard/server/saved_objects/dashboard_migrations.ts b/src/plugins/dashboard/server/saved_objects/dashboard_migrations.ts index 1e8356a1ef100..ac91c5a92048a 100644 --- a/src/plugins/dashboard/server/saved_objects/dashboard_migrations.ts +++ b/src/plugins/dashboard/server/saved_objects/dashboard_migrations.ts @@ -114,4 +114,5 @@ export const dashboardSavedObjectTypeMigrations = { '6.7.2': flow(migrateMatchAllQuery), '7.0.0': flow(migrations700), '7.3.0': flow(migrations730), + '7.9.3': flow(migrateMatchAllQuery), }; diff --git a/src/plugins/dashboard/server/saved_objects/migrate_match_all_query.test.ts b/src/plugins/dashboard/server/saved_objects/migrate_match_all_query.test.ts index 8a91c422eed3d..ce7a5ffcd9fe1 100644 --- a/src/plugins/dashboard/server/saved_objects/migrate_match_all_query.test.ts +++ b/src/plugins/dashboard/server/saved_objects/migrate_match_all_query.test.ts @@ -49,4 +49,21 @@ describe('migrate match_all query', () => { }, }); }); + + it('should return original doc if searchSourceJSON cannot be parsed', () => { + const migratedDoc = migrateMatchAllQuery( + { + attributes: { + kibanaSavedObjectMeta: 'kibanaSavedObjectMeta', + }, + } as Parameters[0], + savedObjectMigrationContext + ); + + expect(migratedDoc).toEqual({ + attributes: { + kibanaSavedObjectMeta: 'kibanaSavedObjectMeta', + }, + }); + }); }); diff --git a/src/plugins/dashboard/server/saved_objects/migrate_match_all_query.ts b/src/plugins/dashboard/server/saved_objects/migrate_match_all_query.ts index 452d68aa92394..3d7aadab5602c 100644 --- a/src/plugins/dashboard/server/saved_objects/migrate_match_all_query.ts +++ b/src/plugins/dashboard/server/saved_objects/migrate_match_all_query.ts @@ -21,6 +21,12 @@ import { SavedObjectMigrationFn } from 'kibana/server'; import { get } from 'lodash'; import { DEFAULT_QUERY_LANGUAGE } from '../../../data/common'; +/** + * This migration script is related to: + * @link https://github.com/elastic/kibana/pull/62194 + * @link https://github.com/elastic/kibana/pull/14644 + * This is only a problem when you import an object from 5.x into 6.x but to be sure that all saved objects migrated we should execute it twice in 6.7.2 and 7.9.3 + */ export const migrateMatchAllQuery: SavedObjectMigrationFn = (doc) => { const searchSourceJSON = get(doc, 'attributes.kibanaSavedObjectMeta.searchSourceJSON'); @@ -31,6 +37,7 @@ export const migrateMatchAllQuery: SavedObjectMigrationFn = (doc) => { searchSource = JSON.parse(searchSourceJSON); } catch (e) { // Let it go, the data is invalid and we'll leave it as is + return doc; } if (searchSource.query?.match_all) { diff --git a/src/plugins/data/README.md b/src/plugins/data/README.md index da0b71122fd9e..33c07078c5348 100644 --- a/src/plugins/data/README.md +++ b/src/plugins/data/README.md @@ -1,9 +1,137 @@ # data -`data` plugin provides common data access services. +The data plugin provides common data access services, such as `search` and `query`, for solutions and application developers. -- `expressions` — run pipeline functions and render results. -- `filter` -- `index_patterns` -- `query` -- `search`: Elasticsearch API service and strategies \ No newline at end of file +## Autocomplete + +The autocomplete service provides suggestions for field names and values. + +It is wired into the `TopNavMenu` component, but can be used independently. + +### Fetch Query Suggestions + +The `getQuerySuggestions` function helps to construct a query. +KQL suggestion functions are registered in X-Pack, so this API does not return results in OSS. + +```.ts + + // `inputValue` is the user input + const querySuggestions = await autocomplete.getQuerySuggestions({ + language: 'kuery', + indexPatterns: [indexPattern], + query: inputValue, + }); + +``` + +### Fetch Value Suggestions + +The `getValueSuggestions` function returns suggestions for field values. +This is helpful when you want to provide a user with options, for example when constructing a filter. + +```.ts + + // `inputValue` is the user input + const valueSuggestions = await autocomplete.getValueSuggestions({ + indexPattern, + field, + query: inputValue, + }); + +``` + +## Field Formats + +Coming soon. + +## Index Patterns + +Coming soon. + +## Query + +The query service is responsible for managing the configuration of a search query (`QueryState`): filters, time range, query string, and settings such as the auto refresh behavior and saved queries. + +It contains sub-services for each of those configurations: + - `data.query.filterManager` - Manages the `filters` component of a `QueryState`. The global filter state (filters that are persisted between applications) are owned by this service. + - `data.query.timefilter` - Responsible for the time range filter and the auto refresh behavior settings. + - `data.query.queryString` - Responsible for the query string and query language settings. + - `data.query.savedQueries` - Responsible for persisting a `QueryState` into a `SavedObject`, so it can be restored and used by other applications. + + Any changes to the `QueryState` are published on the `data.query.state$`, which is useful when wanting to persist global state or run a search upon data changes. + + A simple use case is: + + ```.ts + function searchOnChange(indexPattern: IndexPattern, aggConfigs: AggConfigs) { + data.query.state$.subscribe(() => { + + // Constuct the query portion of the search request + const query = data.query.getEsQuery(indexPattern); + + // Construct a request + const request = { + params: { + index: indexPattern.title, + body: { + aggs: aggConfigs.toDsl(), + query, + }, + }, + }; + + // Search with the `data.query` config + const search$ = data.search.search(request); + + ... + }); + } + + ``` + +## Search + +Provides access to Elasticsearch using the high-level `SearchSource` API or low-level `Search Strategies`. + +### SearchSource + +The `SearchSource` API is a convenient way to construct and run an Elasticsearch search query. + +```.tsx + + const searchSource = await data.search.searchSource.create(); + const searchResponse = await searchSource + .setParent(undefined) + .setField('index', indexPattern) + .setField('filter', filters) + .fetch(); + +``` + +### Low-level search + +#### Default Search Strategy + +One benefit of using the low-level search API, is partial response support in X-Pack, allowing for a better and more responsive user experience. +In OSS only the final result is returned. + +```.ts + import { isCompleteResponse } from '../plugins/data/public'; + + const search$ = data.search.search(request) + .subscribe({ + next: (response) => { + if (isCompleteResponse(response)) { + // Final result + search$.unsubscribe(); + } else { + // Partial result - you can update the UI, but data is still loading + } + }, + error: (e: Error) => { + // Show customized toast notifications. + // You may choose to handle errors differently if you prefer. + data.search.showError(e); + }, + }); +``` diff --git a/src/plugins/data/common/index.ts b/src/plugins/data/common/index.ts index bc7080e7d450b..153b6a633b66d 100644 --- a/src/plugins/data/common/index.ts +++ b/src/plugins/data/common/index.ts @@ -27,3 +27,10 @@ export * from './query'; export * from './search'; export * from './types'; export * from './utils'; + +/** + * Use data plugin interface instead + * @deprecated + */ + +export { IndexPatternAttributes } from './types'; diff --git a/src/plugins/data/common/index_patterns/errors.ts b/src/plugins/data/common/index_patterns/errors.ts deleted file mode 100644 index 3d92bae1968fb..0000000000000 --- a/src/plugins/data/common/index_patterns/errors.ts +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { FieldSpec } from './types'; - -export class FieldTypeUnknownError extends Error { - public readonly fieldSpec: FieldSpec; - constructor(message: string, spec: FieldSpec) { - super(message); - this.name = 'FieldTypeUnknownError'; - this.fieldSpec = spec; - } -} diff --git a/src/plugins/data/common/index_patterns/errors/duplicate_index_pattern.ts b/src/plugins/data/common/index_patterns/errors/duplicate_index_pattern.ts new file mode 100644 index 0000000000000..c42dcc1c6a24d --- /dev/null +++ b/src/plugins/data/common/index_patterns/errors/duplicate_index_pattern.ts @@ -0,0 +1,25 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export class DuplicateIndexPatternError extends Error { + constructor(message: string) { + super(message); + this.name = 'DuplicateIndexPatternError'; + } +} diff --git a/src/plugins/data/common/index_patterns/errors/index.ts b/src/plugins/data/common/index_patterns/errors/index.ts new file mode 100644 index 0000000000000..7cc39d93a2a18 --- /dev/null +++ b/src/plugins/data/common/index_patterns/errors/index.ts @@ -0,0 +1,20 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export * from './duplicate_index_pattern'; diff --git a/src/plugins/data/common/index_patterns/fields/field_list.ts b/src/plugins/data/common/index_patterns/fields/field_list.ts index 4cf6075869851..c0eb55a15fead 100644 --- a/src/plugins/data/common/index_patterns/fields/field_list.ts +++ b/src/plugins/data/common/index_patterns/fields/field_list.ts @@ -20,7 +20,7 @@ import { findIndex } from 'lodash'; import { IFieldType } from './types'; import { IndexPatternField } from './index_pattern_field'; -import { OnNotification, FieldSpec } from '../types'; +import { FieldSpec, IndexPatternFieldMap } from '../types'; import { IndexPattern } from '../index_patterns'; import { shortenDottedString } from '../../utils'; @@ -35,16 +35,11 @@ export interface IIndexPatternFieldList extends Array { removeAll(): void; replaceAll(specs: FieldSpec[]): void; update(field: FieldSpec): void; - toSpec(options?: { getFormatterForField?: IndexPattern['getFormatterForField'] }): FieldSpec[]; + toSpec(options?: { + getFormatterForField?: IndexPattern['getFormatterForField']; + }): IndexPatternFieldMap; } -export type CreateIndexPatternFieldList = ( - indexPattern: IndexPattern, - specs?: FieldSpec[], - shortDotsEnable?: boolean, - onNotification?: OnNotification -) => IIndexPatternFieldList; - // extending the array class and using a constructor doesn't work well // when calling filter and similar so wrapping in a callback. // to be removed in the future @@ -105,7 +100,7 @@ export const fieldList = ( this.groups.clear(); }; - public readonly replaceAll = (spcs: FieldSpec[]) => { + public readonly replaceAll = (spcs: FieldSpec[] = []) => { this.removeAll(); spcs.forEach(this.add); }; @@ -115,7 +110,12 @@ export const fieldList = ( }: { getFormatterForField?: IndexPattern['getFormatterForField']; } = {}) { - return [...this.map((field) => field.toSpec({ getFormatterForField }))]; + return { + ...this.reduce((collector, field) => { + collector[field.name] = field.toSpec({ getFormatterForField }); + return collector; + }, {}), + }; } } diff --git a/src/plugins/data/common/index_patterns/fields/index_pattern_field.ts b/src/plugins/data/common/index_patterns/fields/index_pattern_field.ts index 7f72bfe55c7cd..808afc3449c2a 100644 --- a/src/plugins/data/common/index_patterns/fields/index_pattern_field.ts +++ b/src/plugins/data/common/index_patterns/fields/index_pattern_field.ts @@ -17,12 +17,9 @@ * under the License. */ -import { i18n } from '@kbn/i18n'; import { KbnFieldType, getKbnFieldType } from '../../kbn_field_types'; -import { KBN_FIELD_TYPES } from '../../kbn_field_types/types'; import { IFieldType } from './types'; import { FieldSpec, IndexPattern } from '../..'; -import { FieldTypeUnknownError } from '../errors'; export class IndexPatternField implements IFieldType { readonly spec: FieldSpec; @@ -35,16 +32,12 @@ export class IndexPatternField implements IFieldType { this.displayName = displayName; this.kbnFieldType = getKbnFieldType(spec.type); - if (spec.type && this.kbnFieldType?.name === KBN_FIELD_TYPES.UNKNOWN) { - const msg = i18n.translate('data.indexPatterns.unknownFieldTypeErrorMsg', { - values: { type: spec.type, name: spec.name }, - defaultMessage: `Field '{name}' Unknown field type '{type}'`, - }); - throw new FieldTypeUnknownError(msg, spec); - } } // writable attrs + /** + * Count is used for field popularity + */ public get count() { return this.spec.count || 0; } @@ -53,6 +46,9 @@ export class IndexPatternField implements IFieldType { this.spec.count = count; } + /** + * Script field code + */ public get script() { return this.spec.script; } @@ -61,6 +57,9 @@ export class IndexPatternField implements IFieldType { this.spec.script = script; } + /** + * Script field language + */ public get lang() { return this.spec.lang; } @@ -69,6 +68,9 @@ export class IndexPatternField implements IFieldType { this.spec.lang = lang; } + /** + * Description of field type conflicts across different indices in the same index pattern + */ public get conflictDescriptions() { return this.spec.conflictDescriptions; } @@ -152,7 +154,7 @@ export class IndexPatternField implements IFieldType { getFormatterForField, }: { getFormatterForField?: IndexPattern['getFormatterForField']; - } = {}) { + } = {}): FieldSpec { return { count: this.count, script: this.script, diff --git a/src/plugins/data/common/index_patterns/index_patterns/__snapshots__/index_pattern.test.ts.snap b/src/plugins/data/common/index_patterns/index_patterns/__snapshots__/index_pattern.test.ts.snap index 1871627da76de..ed84aceb60e5a 100644 --- a/src/plugins/data/common/index_patterns/index_patterns/__snapshots__/index_pattern.test.ts.snap +++ b/src/plugins/data/common/index_patterns/index_patterns/__snapshots__/index_pattern.test.ts.snap @@ -2,13 +2,13 @@ exports[`IndexPattern toSpec should match snapshot 1`] = ` Object { - "fields": Array [ - Object { + "fields": Object { + "@tags": Object { "aggregatable": true, "conflictDescriptions": undefined, - "count": 10, + "count": 0, "esTypes": Array [ - "long", + "keyword", ], "format": Object { "id": "number", @@ -17,20 +17,20 @@ Object { }, }, "lang": undefined, - "name": "bytes", + "name": "@tags", "readFromDocValues": true, "script": undefined, "scripted": false, "searchable": true, "subType": undefined, - "type": "number", + "type": "string", }, - Object { + "@timestamp": Object { "aggregatable": true, "conflictDescriptions": undefined, - "count": 20, + "count": 30, "esTypes": Array [ - "boolean", + "date", ], "format": Object { "id": "number", @@ -39,20 +39,20 @@ Object { }, }, "lang": undefined, - "name": "ssl", + "name": "@timestamp", "readFromDocValues": true, "script": undefined, "scripted": false, "searchable": true, "subType": undefined, - "type": "boolean", + "type": "date", }, - Object { + "_id": Object { "aggregatable": true, "conflictDescriptions": undefined, - "count": 30, + "count": 0, "esTypes": Array [ - "date", + "_id", ], "format": Object { "id": "number", @@ -61,20 +61,20 @@ Object { }, }, "lang": undefined, - "name": "@timestamp", - "readFromDocValues": true, + "name": "_id", + "readFromDocValues": false, "script": undefined, "scripted": false, "searchable": true, "subType": undefined, - "type": "date", + "type": "string", }, - Object { + "_source": Object { "aggregatable": true, "conflictDescriptions": undefined, - "count": 30, + "count": 0, "esTypes": Array [ - "date", + "_source", ], "format": Object { "id": "number", @@ -83,20 +83,20 @@ Object { }, }, "lang": undefined, - "name": "time", - "readFromDocValues": true, + "name": "_source", + "readFromDocValues": false, "script": undefined, "scripted": false, "searchable": true, "subType": undefined, - "type": "date", + "type": "_source", }, - Object { + "_type": Object { "aggregatable": true, "conflictDescriptions": undefined, "count": 0, "esTypes": Array [ - "keyword", + "_type", ], "format": Object { "id": "number", @@ -105,20 +105,20 @@ Object { }, }, "lang": undefined, - "name": "@tags", - "readFromDocValues": true, + "name": "_type", + "readFromDocValues": false, "script": undefined, "scripted": false, "searchable": true, "subType": undefined, "type": "string", }, - Object { + "area": Object { "aggregatable": true, "conflictDescriptions": undefined, "count": 0, "esTypes": Array [ - "date", + "geo_shape", ], "format": Object { "id": "number", @@ -127,20 +127,20 @@ Object { }, }, "lang": undefined, - "name": "utc_time", - "readFromDocValues": true, + "name": "area", + "readFromDocValues": false, "script": undefined, "scripted": false, "searchable": true, "subType": undefined, - "type": "date", + "type": "geo_shape", }, - Object { + "bytes": Object { "aggregatable": true, "conflictDescriptions": undefined, - "count": 0, + "count": 10, "esTypes": Array [ - "integer", + "long", ], "format": Object { "id": "number", @@ -149,7 +149,7 @@ Object { }, }, "lang": undefined, - "name": "phpmemory", + "name": "bytes", "readFromDocValues": true, "script": undefined, "scripted": false, @@ -157,12 +157,12 @@ Object { "subType": undefined, "type": "number", }, - Object { + "custom_user_field": Object { "aggregatable": true, "conflictDescriptions": undefined, "count": 0, "esTypes": Array [ - "ip", + "conflict", ], "format": Object { "id": "number", @@ -171,20 +171,20 @@ Object { }, }, "lang": undefined, - "name": "ip", + "name": "custom_user_field", "readFromDocValues": true, "script": undefined, "scripted": false, "searchable": true, "subType": undefined, - "type": "ip", + "type": "conflict", }, - Object { + "extension": Object { "aggregatable": true, "conflictDescriptions": undefined, "count": 0, "esTypes": Array [ - "attachment", + "text", ], "format": Object { "id": "number", @@ -193,15 +193,41 @@ Object { }, }, "lang": undefined, - "name": "request_body", - "readFromDocValues": true, + "name": "extension", + "readFromDocValues": false, "script": undefined, "scripted": false, "searchable": true, "subType": undefined, - "type": "attachment", + "type": "string", }, - Object { + "extension.keyword": Object { + "aggregatable": true, + "conflictDescriptions": undefined, + "count": 0, + "esTypes": Array [ + "keyword", + ], + "format": Object { + "id": "number", + "params": Object { + "pattern": "$0,0.[00]", + }, + }, + "lang": undefined, + "name": "extension.keyword", + "readFromDocValues": true, + "script": undefined, + "scripted": false, + "searchable": true, + "subType": Object { + "multi": Object { + "parent": "extension", + }, + }, + "type": "string", + }, + "geo.coordinates": Object { "aggregatable": true, "conflictDescriptions": undefined, "count": 0, @@ -215,7 +241,7 @@ Object { }, }, "lang": undefined, - "name": "point", + "name": "geo.coordinates", "readFromDocValues": true, "script": undefined, "scripted": false, @@ -223,12 +249,12 @@ Object { "subType": undefined, "type": "geo_point", }, - Object { + "geo.src": Object { "aggregatable": true, "conflictDescriptions": undefined, "count": 0, "esTypes": Array [ - "geo_shape", + "keyword", ], "format": Object { "id": "number", @@ -237,15 +263,15 @@ Object { }, }, "lang": undefined, - "name": "area", - "readFromDocValues": false, + "name": "geo.src", + "readFromDocValues": true, "script": undefined, "scripted": false, "searchable": true, "subType": undefined, - "type": "geo_shape", + "type": "string", }, - Object { + "hashed": Object { "aggregatable": false, "conflictDescriptions": undefined, "count": 0, @@ -267,12 +293,12 @@ Object { "subType": undefined, "type": "murmur3", }, - Object { + "ip": Object { "aggregatable": true, "conflictDescriptions": undefined, "count": 0, "esTypes": Array [ - "geo_point", + "ip", ], "format": Object { "id": "number", @@ -281,15 +307,15 @@ Object { }, }, "lang": undefined, - "name": "geo.coordinates", + "name": "ip", "readFromDocValues": true, "script": undefined, "scripted": false, "searchable": true, "subType": undefined, - "type": "geo_point", + "type": "ip", }, - Object { + "machine.os": Object { "aggregatable": true, "conflictDescriptions": undefined, "count": 0, @@ -303,7 +329,7 @@ Object { }, }, "lang": undefined, - "name": "extension", + "name": "machine.os", "readFromDocValues": false, "script": undefined, "scripted": false, @@ -311,7 +337,7 @@ Object { "subType": undefined, "type": "string", }, - Object { + "machine.os.raw": Object { "aggregatable": true, "conflictDescriptions": undefined, "count": 0, @@ -325,19 +351,19 @@ Object { }, }, "lang": undefined, - "name": "extension.keyword", + "name": "machine.os.raw", "readFromDocValues": true, "script": undefined, "scripted": false, "searchable": true, "subType": Object { "multi": Object { - "parent": "extension", + "parent": "machine.os", }, }, "type": "string", }, - Object { + "non-filterable": Object { "aggregatable": true, "conflictDescriptions": undefined, "count": 0, @@ -351,20 +377,20 @@ Object { }, }, "lang": undefined, - "name": "machine.os", + "name": "non-filterable", "readFromDocValues": false, "script": undefined, "scripted": false, - "searchable": true, + "searchable": false, "subType": undefined, "type": "string", }, - Object { - "aggregatable": true, + "non-sortable": Object { + "aggregatable": false, "conflictDescriptions": undefined, "count": 0, "esTypes": Array [ - "keyword", + "text", ], "format": Object { "id": "number", @@ -373,24 +399,20 @@ Object { }, }, "lang": undefined, - "name": "machine.os.raw", - "readFromDocValues": true, + "name": "non-sortable", + "readFromDocValues": false, "script": undefined, "scripted": false, - "searchable": true, - "subType": Object { - "multi": Object { - "parent": "machine.os", - }, - }, + "searchable": false, + "subType": undefined, "type": "string", }, - Object { + "phpmemory": Object { "aggregatable": true, "conflictDescriptions": undefined, "count": 0, "esTypes": Array [ - "keyword", + "integer", ], "format": Object { "id": "number", @@ -399,20 +421,20 @@ Object { }, }, "lang": undefined, - "name": "geo.src", + "name": "phpmemory", "readFromDocValues": true, "script": undefined, "scripted": false, "searchable": true, "subType": undefined, - "type": "string", + "type": "number", }, - Object { + "point": Object { "aggregatable": true, "conflictDescriptions": undefined, "count": 0, "esTypes": Array [ - "_id", + "geo_point", ], "format": Object { "id": "number", @@ -421,20 +443,20 @@ Object { }, }, "lang": undefined, - "name": "_id", - "readFromDocValues": false, + "name": "point", + "readFromDocValues": true, "script": undefined, "scripted": false, "searchable": true, "subType": undefined, - "type": "string", + "type": "geo_point", }, - Object { + "request_body": Object { "aggregatable": true, "conflictDescriptions": undefined, "count": 0, "esTypes": Array [ - "_type", + "attachment", ], "format": Object { "id": "number", @@ -443,20 +465,20 @@ Object { }, }, "lang": undefined, - "name": "_type", - "readFromDocValues": false, + "name": "request_body", + "readFromDocValues": true, "script": undefined, "scripted": false, "searchable": true, "subType": undefined, - "type": "string", + "type": "attachment", }, - Object { + "script date": Object { "aggregatable": true, "conflictDescriptions": undefined, "count": 0, "esTypes": Array [ - "_source", + "date", ], "format": Object { "id": "number", @@ -464,43 +486,21 @@ Object { "pattern": "$0,0.[00]", }, }, - "lang": undefined, - "name": "_source", + "lang": "painless", + "name": "script date", "readFromDocValues": false, - "script": undefined, - "scripted": false, + "script": "1234", + "scripted": true, "searchable": true, "subType": undefined, - "type": "_source", + "type": "date", }, - Object { + "script murmur3": Object { "aggregatable": true, "conflictDescriptions": undefined, "count": 0, "esTypes": Array [ - "text", - ], - "format": Object { - "id": "number", - "params": Object { - "pattern": "$0,0.[00]", - }, - }, - "lang": undefined, - "name": "non-filterable", - "readFromDocValues": false, - "script": undefined, - "scripted": false, - "searchable": false, - "subType": undefined, - "type": "string", - }, - Object { - "aggregatable": false, - "conflictDescriptions": undefined, - "count": 0, - "esTypes": Array [ - "text", + "murmur3", ], "format": Object { "id": "number", @@ -508,21 +508,21 @@ Object { "pattern": "$0,0.[00]", }, }, - "lang": undefined, - "name": "non-sortable", + "lang": "expression", + "name": "script murmur3", "readFromDocValues": false, - "script": undefined, - "scripted": false, - "searchable": false, + "script": "1234", + "scripted": true, + "searchable": true, "subType": undefined, - "type": "string", + "type": "murmur3", }, - Object { + "script number": Object { "aggregatable": true, "conflictDescriptions": undefined, "count": 0, "esTypes": Array [ - "conflict", + "long", ], "format": Object { "id": "number", @@ -530,16 +530,16 @@ Object { "pattern": "$0,0.[00]", }, }, - "lang": undefined, - "name": "custom_user_field", - "readFromDocValues": true, - "script": undefined, - "scripted": false, + "lang": "expression", + "name": "script number", + "readFromDocValues": false, + "script": "1234", + "scripted": true, "searchable": true, "subType": undefined, - "type": "conflict", + "type": "number", }, - Object { + "script string": Object { "aggregatable": true, "conflictDescriptions": undefined, "count": 0, @@ -561,12 +561,12 @@ Object { "subType": undefined, "type": "string", }, - Object { + "ssl": Object { "aggregatable": true, "conflictDescriptions": undefined, - "count": 0, + "count": 20, "esTypes": Array [ - "long", + "boolean", ], "format": Object { "id": "number", @@ -574,19 +574,19 @@ Object { "pattern": "$0,0.[00]", }, }, - "lang": "expression", - "name": "script number", - "readFromDocValues": false, - "script": "1234", - "scripted": true, + "lang": undefined, + "name": "ssl", + "readFromDocValues": true, + "script": undefined, + "scripted": false, "searchable": true, "subType": undefined, - "type": "number", + "type": "boolean", }, - Object { + "time": Object { "aggregatable": true, "conflictDescriptions": undefined, - "count": 0, + "count": 30, "esTypes": Array [ "date", ], @@ -596,21 +596,21 @@ Object { "pattern": "$0,0.[00]", }, }, - "lang": "painless", - "name": "script date", - "readFromDocValues": false, - "script": "1234", - "scripted": true, + "lang": undefined, + "name": "time", + "readFromDocValues": true, + "script": undefined, + "scripted": false, "searchable": true, "subType": undefined, "type": "date", }, - Object { + "utc_time": Object { "aggregatable": true, "conflictDescriptions": undefined, "count": 0, "esTypes": Array [ - "murmur3", + "date", ], "format": Object { "id": "number", @@ -618,21 +618,22 @@ Object { "pattern": "$0,0.[00]", }, }, - "lang": "expression", - "name": "script murmur3", - "readFromDocValues": false, - "script": "1234", - "scripted": true, + "lang": undefined, + "name": "utc_time", + "readFromDocValues": true, + "script": undefined, + "scripted": false, "searchable": true, "subType": undefined, - "type": "murmur3", + "type": "date", }, - ], + }, "id": "test-pattern", "sourceFilters": undefined, "timeFieldName": "timestamp", "title": "title", + "type": "index-pattern", "typeMeta": undefined, - "version": 2, + "version": "2", } `; diff --git a/src/plugins/data/common/index_patterns/index_patterns/__snapshots__/index_patterns.test.ts.snap b/src/plugins/data/common/index_patterns/index_patterns/__snapshots__/index_patterns.test.ts.snap new file mode 100644 index 0000000000000..752fdcf11991c --- /dev/null +++ b/src/plugins/data/common/index_patterns/index_patterns/__snapshots__/index_patterns.test.ts.snap @@ -0,0 +1,22 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`IndexPatterns savedObjectToSpec 1`] = ` +Object { + "fields": Object {}, + "id": "id", + "intervalName": undefined, + "sourceFilters": Array [ + Object { + "value": "item1", + }, + Object { + "value": "item2", + }, + ], + "timeFieldName": "@timestamp", + "title": "kibana-*", + "type": "", + "typeMeta": Object {}, + "version": "version", +} +`; diff --git a/src/plugins/data/common/index_patterns/index_patterns/_fields_fetcher.ts b/src/plugins/data/common/index_patterns/index_patterns/_fields_fetcher.ts deleted file mode 100644 index 4eba0576ff235..0000000000000 --- a/src/plugins/data/common/index_patterns/index_patterns/_fields_fetcher.ts +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { IndexPattern } from '.'; -import { GetFieldsOptions, IIndexPatternsApiClient } from '../types'; - -/** @internal */ -export const createFieldsFetcher = ( - indexPattern: IndexPattern, - apiClient: IIndexPatternsApiClient, - metaFields: string[] = [] -) => { - const fieldFetcher = { - fetch: (options: GetFieldsOptions) => { - return fieldFetcher.fetchForWildcard(indexPattern.title, { - ...options, - type: indexPattern.type, - params: indexPattern.typeMeta && indexPattern.typeMeta.params, - }); - }, - fetchForWildcard: (pattern: string, options: GetFieldsOptions = {}) => { - return apiClient.getFieldsForWildcard({ - pattern, - metaFields, - type: options.type, - params: options.params || {}, - }); - }, - }; - - return fieldFetcher; -}; diff --git a/src/plugins/data/common/index_patterns/index_patterns/index_pattern.test.ts b/src/plugins/data/common/index_patterns/index_patterns/index_pattern.test.ts index f49897c47d562..a8d53223c06d1 100644 --- a/src/plugins/data/common/index_patterns/index_patterns/index_pattern.test.ts +++ b/src/plugins/data/common/index_patterns/index_patterns/index_pattern.test.ts @@ -17,19 +17,18 @@ * under the License. */ -import { defaults, map, last } from 'lodash'; +import { map, last } from 'lodash'; import { IndexPattern } from './index_pattern'; import { DuplicateField } from '../../../../kibana_utils/common'; -// @ts-ignore +// @ts-expect-error import mockLogStashFields from '../../../../../fixtures/logstash_fields'; -// @ts-ignore import { stubbedSavedObjectIndexPattern } from '../../../../../fixtures/stubbed_saved_object_index_pattern'; import { IndexPatternField } from '../fields'; import { fieldFormatsMock } from '../../field_formats/mocks'; -import { FieldFormat, IndexPatternsService } from '../..'; +import { FieldFormat } from '../..'; class MockFieldFormatter {} @@ -63,91 +62,33 @@ jest.mock('../../field_mapping', () => { }; }); -let mockFieldsFetcherResponse: any[] = []; - -jest.mock('./_fields_fetcher', () => ({ - createFieldsFetcher: jest.fn().mockImplementation(() => ({ - fetch: jest.fn().mockImplementation(() => { - return new Promise((resolve) => resolve(mockFieldsFetcherResponse)); - }), - every: jest.fn(), - })), -})); - -let object: any = {}; - -const savedObjectsClient = { - create: jest.fn(), - get: jest.fn().mockImplementation(() => object), - update: jest.fn().mockImplementation(async (type, id, body, { version }) => { - if (object.version !== version) { - throw new Object({ - res: { - status: 409, - }, - }); - } - object.attributes.title = body.title; - object.version += 'a'; - return { - id: object.id, - version: object.version, - }; - }), -}; - -const patternCache = { - clear: jest.fn(), - get: jest.fn(), - set: jest.fn(), - clearAll: jest.fn(), -}; - -const apiClient = { - _getUrl: jest.fn(), - getFieldsForTimePattern: jest.fn(), - getFieldsForWildcard: jest.fn(), -}; - // helper function to create index patterns -function create(id: string, payload?: any): Promise { - const indexPattern = new IndexPattern(id, { - savedObjectsClient: savedObjectsClient as any, - apiClient, - patternCache, +function create(id: string) { + const { + type, + version, + attributes: { timeFieldName, fields, title }, + } = stubbedSavedObjectIndexPattern(id); + + return new IndexPattern({ + spec: { id, type, version, timeFieldName, fields, title }, + savedObjectsClient: {} as any, fieldFormats: fieldFormatsMock, - indexPatternsService: {} as IndexPatternsService, - onNotification: () => {}, - onError: () => {}, shortDotsEnable: false, metaFields: [], }); - - setDocsourcePayload(id, payload); - - return indexPattern.init(); -} - -function setDocsourcePayload(id: string | null, providedPayload: any) { - object = defaults(providedPayload || {}, stubbedSavedObjectIndexPattern(id)); } describe('IndexPattern', () => { - const indexPatternId = 'test-pattern'; - let indexPattern: IndexPattern; // create an indexPattern instance for each test beforeEach(() => { - return create(indexPatternId).then((pattern: IndexPattern) => { - indexPattern = pattern; - }); + indexPattern = create('test-pattern'); }); describe('api', () => { test('should have expected properties', () => { - expect(indexPattern).toHaveProperty('refreshFields'); - expect(indexPattern).toHaveProperty('popularizeField'); expect(indexPattern).toHaveProperty('getScriptedFields'); expect(indexPattern).toHaveProperty('getNonScriptedFields'); expect(indexPattern).toHaveProperty('addScriptedField'); @@ -158,13 +99,6 @@ describe('IndexPattern', () => { }); }); - describe('init', () => { - test('should append the found fields', () => { - expect(savedObjectsClient.get).toHaveBeenCalled(); - expect(indexPattern.fields).toHaveLength(mockLogStashFields().length); - }); - }); - describe('fields', () => { test('should have expected properties on fields', function () { expect(indexPattern.fields[0]).toHaveProperty('displayName'); @@ -229,43 +163,9 @@ describe('IndexPattern', () => { }); }); - describe('refresh fields', () => { - test('should fetch fields from the fieldsFetcher', async () => { - expect(indexPattern.fields.length).toBeGreaterThan(2); - - mockFieldsFetcherResponse = [{ name: 'foo' }, { name: 'bar' }]; - - await indexPattern.refreshFields(); - - mockFieldsFetcherResponse = []; - - const newFields = indexPattern.getNonScriptedFields(); - - expect(newFields).toHaveLength(2); - expect([...newFields.map((f) => f.name)]).toEqual(['foo', 'bar']); - }); - - test('should preserve the scripted fields', async () => { - // add spy to indexPattern.getScriptedFields - // sinon.spy(indexPattern, 'getScriptedFields'); - - // refresh fields, which will fetch - await indexPattern.refreshFields(); - - // called to append scripted fields to the response from mapper.getFieldsForIndexPattern - // sinon.assert.calledOnce(indexPattern.getScriptedFields); - expect(indexPattern.getScriptedFields().map((f) => f.name)).toEqual( - mockLogStashFields() - .filter((f: IndexPatternField) => f.scripted) - .map((f: IndexPatternField) => f.name) - ); - }); - }); - describe('add and remove scripted fields', () => { test('should append the scripted field', async () => { // keep a copy of the current scripted field count - // const saveSpy = sinon.spy(indexPattern, 'save'); const oldCount = indexPattern.getScriptedFields().length; // add a new scripted field @@ -278,12 +178,10 @@ describe('IndexPattern', () => { await indexPattern.addScriptedField( scriptedField.name, scriptedField.script, - scriptedField.type, - 'lang' + scriptedField.type ); const scriptedFields = indexPattern.getScriptedFields(); - // expect(saveSpy.callCount).to.equal(1); expect(scriptedFields).toHaveLength(oldCount + 1); expect((indexPattern.fields.getByName(scriptedField.name) as IndexPatternField).name).toEqual( scriptedField.name @@ -291,14 +189,12 @@ describe('IndexPattern', () => { }); test('should remove scripted field, by name', async () => { - // const saveSpy = sinon.spy(indexPattern, 'save'); const scriptedFields = indexPattern.getScriptedFields(); const oldCount = scriptedFields.length; const scriptedField = last(scriptedFields)!; await indexPattern.removeScriptedField(scriptedField.name); - // expect(saveSpy.callCount).to.equal(1); expect(indexPattern.getScriptedFields().length).toEqual(oldCount - 1); expect(indexPattern.fields.getByName(scriptedField.name)).toEqual(undefined); }); @@ -308,7 +204,7 @@ describe('IndexPattern', () => { const scriptedField = last(scriptedFields) as any; expect.assertions(1); try { - await indexPattern.addScriptedField(scriptedField.name, "'new script'", 'string', 'lang'); + await indexPattern.addScriptedField(scriptedField.name, "'new script'", 'string'); } catch (e) { expect(e).toBeInstanceOf(DuplicateField); } @@ -330,8 +226,13 @@ describe('IndexPattern', () => { } as FieldFormat; indexPattern.getFormatterForField = () => formatter; const spec = indexPattern.toSpec(); - const restoredPattern = await create(spec.id as string); - restoredPattern.initFromSpec(spec); + const restoredPattern = new IndexPattern({ + spec, + savedObjectsClient: {} as any, + fieldFormats: fieldFormatsMock, + shortDotsEnable: false, + metaFields: [], + }); expect(restoredPattern.id).toEqual(indexPattern.id); expect(restoredPattern.title).toEqual(indexPattern.title); expect(restoredPattern.timeFieldName).toEqual(indexPattern.timeFieldName); @@ -339,54 +240,4 @@ describe('IndexPattern', () => { expect(restoredPattern.fieldFormatMap.bytes instanceof MockFieldFormatter).toEqual(true); }); }); - - describe('popularizeField', () => { - test('should increment the popularity count by default', () => { - // const saveSpy = sinon.stub(indexPattern, 'save'); - indexPattern.fields.forEach(async (field) => { - const oldCount = field.count || 0; - - await indexPattern.popularizeField(field.name); - - // expect(saveSpy.callCount).to.equal(i + 1); - expect(field.count).toEqual(oldCount + 1); - }); - }); - - test('should increment the popularity count', () => { - // const saveSpy = sinon.stub(indexPattern, 'save'); - indexPattern.fields.forEach(async (field) => { - const oldCount = field.count || 0; - const incrementAmount = 4; - - await indexPattern.popularizeField(field.name, incrementAmount); - - // expect(saveSpy.callCount).to.equal(i + 1); - expect(field.count).toEqual(oldCount + incrementAmount); - }); - }); - - test('should decrement the popularity count', () => { - indexPattern.fields.forEach(async (field) => { - const oldCount = field.count || 0; - const incrementAmount = 4; - const decrementAmount = -2; - - await indexPattern.popularizeField(field.name, incrementAmount); - await indexPattern.popularizeField(field.name, decrementAmount); - - expect(field.count).toEqual(oldCount + incrementAmount + decrementAmount); - }); - }); - - test('should not go below 0', () => { - indexPattern.fields.forEach(async (field) => { - const decrementAmount = -Number.MAX_VALUE; - - await indexPattern.popularizeField(field.name, decrementAmount); - - expect(field.count).toEqual(0); - }); - }); - }); }); diff --git a/src/plugins/data/common/index_patterns/index_patterns/index_pattern.ts b/src/plugins/data/common/index_patterns/index_patterns/index_pattern.ts index 76f1a5e59d0ee..5fc6344c935d5 100644 --- a/src/plugins/data/common/index_patterns/index_patterns/index_pattern.ts +++ b/src/plugins/data/common/index_patterns/index_patterns/index_pattern.ts @@ -18,211 +18,91 @@ */ import _, { each, reject } from 'lodash'; -import { i18n } from '@kbn/i18n'; import { SavedObjectsClientCommon } from '../..'; -import { DuplicateField, SavedObjectNotFound } from '../../../../kibana_utils/common'; +import { DuplicateField } from '../../../../kibana_utils/common'; import { ES_FIELD_TYPES, KBN_FIELD_TYPES, IIndexPattern, - FieldTypeUnknownError, FieldFormatNotFoundError, + IFieldType, } from '../../../common'; -import { findByTitle } from '../utils'; -import { IndexPatternMissingIndices } from '../lib'; import { IndexPatternField, IIndexPatternFieldList, fieldList } from '../fields'; -import { createFieldsFetcher } from './_fields_fetcher'; import { formatHitProvider } from './format_hit'; import { flattenHitWrapper } from './flatten_hit'; -import { OnNotification, OnError, IIndexPatternsApiClient, IndexPatternAttributes } from '../types'; import { FieldFormatsStartCommon, FieldFormat } from '../../field_formats'; -import { PatternCache } from './_pattern_cache'; -import { expandShorthand, FieldMappingSpec, MappingObject } from '../../field_mapping'; -import { IndexPatternSpec, TypeMeta, FieldSpec, SourceFilter } from '../types'; +import { IndexPatternSpec, TypeMeta, SourceFilter, IndexPatternFieldMap } from '../types'; import { SerializedFieldFormat } from '../../../../expressions/common'; -import { IndexPatternsService } from '..'; - -const savedObjectType = 'index-pattern'; interface IndexPatternDeps { + spec?: IndexPatternSpec; savedObjectsClient: SavedObjectsClientCommon; - apiClient: IIndexPatternsApiClient; - patternCache: PatternCache; fieldFormats: FieldFormatsStartCommon; - indexPatternsService: IndexPatternsService; - onNotification: OnNotification; - onError: OnError; shortDotsEnable: boolean; metaFields: string[]; } +interface SavedObjectBody { + title?: string; + timeFieldName?: string; + intervalName?: string; + fields?: string; + sourceFilters?: string; + fieldFormatMap?: string; + typeMeta?: string; + type?: string; +} + +type FormatFieldFn = (hit: Record, fieldName: string) => any; + export class IndexPattern implements IIndexPattern { public id?: string; public title: string = ''; - public fieldFormatMap: any; + public fieldFormatMap: Record; public typeMeta?: TypeMeta; - public fields: IIndexPatternFieldList & { toSpec: () => FieldSpec[] }; + public fields: IIndexPatternFieldList & { toSpec: () => IndexPatternFieldMap }; public timeFieldName: string | undefined; public intervalName: string | undefined; public type: string | undefined; - public formatHit: any; - public formatField: any; - public flattenHit: any; + public formatHit: { + (hit: Record, type?: string): any; + formatField: FormatFieldFn; + }; + public formatField: FormatFieldFn; + public flattenHit: (hit: Record, deep?: boolean) => Record; public metaFields: string[]; - + // savedObject version public version: string | undefined; - private savedObjectsClient: SavedObjectsClientCommon; - private patternCache: PatternCache; public sourceFilters?: SourceFilter[]; - // todo make read only, update via method or factor out - public originalBody: { [key: string]: any } = {}; - public fieldsFetcher: any; // probably want to factor out any direct usage and change to private - private indexPatternsService: IndexPatternsService; + private originalSavedObjectBody: SavedObjectBody = {}; private shortDotsEnable: boolean = false; private fieldFormats: FieldFormatsStartCommon; - private onNotification: OnNotification; - private onError: OnError; - - private mapping: MappingObject = expandShorthand({ - title: ES_FIELD_TYPES.TEXT, - timeFieldName: ES_FIELD_TYPES.KEYWORD, - intervalName: ES_FIELD_TYPES.KEYWORD, - fields: 'json', - sourceFilters: 'json', - fieldFormatMap: { - type: ES_FIELD_TYPES.TEXT, - _serialize: (map = {}) => { - const serialized = _.transform(map, this.serializeFieldFormatMap); - return _.isEmpty(serialized) ? undefined : JSON.stringify(serialized); - }, - _deserialize: (map = '{}') => { - return _.mapValues(JSON.parse(map), (mapping) => { - return this.deserializeFieldFormatMap(mapping); - }); - }, - }, - type: ES_FIELD_TYPES.KEYWORD, - typeMeta: 'json', - }); - - constructor( - id: string | undefined, - { - savedObjectsClient, - apiClient, - patternCache, - fieldFormats, - indexPatternsService, - onNotification, - onError, - shortDotsEnable = false, - metaFields = [], - }: IndexPatternDeps - ) { - this.id = id; - this.savedObjectsClient = savedObjectsClient; - this.patternCache = patternCache; - this.fieldFormats = fieldFormats; - this.indexPatternsService = indexPatternsService; - this.onNotification = onNotification; - this.onError = onError; + constructor({ + spec = {}, + fieldFormats, + shortDotsEnable = false, + metaFields = [], + }: IndexPatternDeps) { + // set dependencies + this.fieldFormats = fieldFormats; + // set config this.shortDotsEnable = shortDotsEnable; this.metaFields = metaFields; + // initialize functionality this.fields = fieldList([], this.shortDotsEnable); - this.fieldsFetcher = createFieldsFetcher(this, apiClient, metaFields); this.flattenHit = flattenHitWrapper(this, metaFields); this.formatHit = formatHitProvider( this, fieldFormats.getDefaultInstance(KBN_FIELD_TYPES.STRING) ); this.formatField = this.formatHit.formatField; - } - private unknownFieldErrorNotification( - fieldType: string, - fieldName: string, - indexPatternTitle: string - ) { - const title = i18n.translate('data.indexPatterns.unknownFieldHeader', { - values: { type: fieldType }, - defaultMessage: 'Unknown field type {type}', - }); - const text = i18n.translate('data.indexPatterns.unknownFieldErrorMessage', { - values: { name: fieldName, title: indexPatternTitle }, - defaultMessage: 'Field {name} in indexPattern {title} is using an unknown field type.', - }); - this.onNotification({ title, text, color: 'danger', iconType: 'alert' }); - } - - private serializeFieldFormatMap(flat: any, format: string, field: string | undefined) { - if (format && field) { - flat[field] = format; - } - } - - private deserializeFieldFormatMap(mapping: any) { - try { - return this.fieldFormats.getInstance(mapping.id, mapping.params); - } catch (err) { - if (err instanceof FieldFormatNotFoundError) { - return undefined; - } else { - throw err; - } - } - } - - private isFieldRefreshRequired(specs?: FieldSpec[]): boolean { - if (!specs) { - return true; - } - - return specs.every((spec) => { - // See https://github.com/elastic/kibana/pull/8421 - const hasFieldCaps = 'aggregatable' in spec && 'searchable' in spec; - - // See https://github.com/elastic/kibana/pull/11969 - const hasDocValuesFlag = 'readFromDocValues' in spec; - - return !hasFieldCaps || !hasDocValuesFlag; - }); - } - - private async indexFields(specs?: FieldSpec[]) { - if (!this.id) { - return; - } - - if (this.isFieldRefreshRequired(specs)) { - await this.refreshFields(); - } else { - if (specs) { - try { - this.fields.replaceAll(specs); - } catch (err) { - if (err instanceof FieldTypeUnknownError) { - this.unknownFieldErrorNotification(err.fieldSpec.name, err.fieldSpec.type, this.title); - } else { - throw err; - } - } - } - } - } - - public initFromSpec(spec: IndexPatternSpec) { - // create fieldFormatMap from field list - const fieldFormatMap: Record = {}; - if (_.isArray(spec.fields)) { - spec.fields.forEach((field: FieldSpec) => { - if (field.format) { - fieldFormatMap[field.name as string] = { ...field.format }; - } - }); - } + // set values + this.id = spec.id; + const fieldFormatMap = this.fieldSpecsToFieldFormatMap(spec.fields); this.version = spec.version; @@ -230,53 +110,55 @@ export class IndexPattern implements IIndexPattern { this.timeFieldName = spec.timeFieldName; this.sourceFilters = spec.sourceFilters; - try { - this.fields.replaceAll(spec.fields || []); - } catch (err) { - if (err instanceof FieldTypeUnknownError) { - this.unknownFieldErrorNotification(err.fieldSpec.name, err.fieldSpec.type, this.title); - } else { - throw err; - } - } + this.fields.replaceAll(Object.values(spec.fields || {})); + this.type = spec.type; this.typeMeta = spec.typeMeta; this.fieldFormatMap = _.mapValues(fieldFormatMap, (mapping) => { return this.deserializeFieldFormatMap(mapping); }); - - return this; } - private updateFromElasticSearch(response: any) { - if (!response.found) { - throw new SavedObjectNotFound(savedObjectType, this.id, 'management/kibana/indexPatterns'); - } - - _.forOwn(this.mapping, (fieldMapping: FieldMappingSpec, name: string | undefined) => { - if (!fieldMapping._deserialize || !name) { - return; + /** + * Get last saved saved object fields + */ + getOriginalSavedObjectBody = () => ({ ...this.originalSavedObjectBody }); + + /** + * Reset last saved saved object fields. used after saving + */ + resetOriginalSavedObjectBody = () => { + this.originalSavedObjectBody = this.getAsSavedObjectBody(); + }; + + /** + * Converts field format spec to field format instance + * @param mapping + */ + private deserializeFieldFormatMap(mapping: SerializedFieldFormat>) { + try { + return this.fieldFormats.getInstance(mapping.id as string, mapping.params); + } catch (err) { + if (err instanceof FieldFormatNotFoundError) { + return undefined; + } else { + throw err; } - - response[name] = fieldMapping._deserialize(response[name]); - }); - - this.title = response.title; - this.timeFieldName = response.timeFieldName; - this.intervalName = response.intervalName; - this.sourceFilters = response.sourceFilters; - this.fieldFormatMap = response.fieldFormatMap; - this.type = response.type; - this.typeMeta = response.typeMeta; - - if (!this.title && this.id) { - this.title = this.id; } - this.version = response.version; - - return this.indexFields(response.fields); } + /** + * Extracts FieldFormatMap from FieldSpec map + * @param fldList FieldSpec map + */ + private fieldSpecsToFieldFormatMap = (fldList: IndexPatternSpec['fields'] = {}) => + Object.values(fldList).reduce>((col, fieldSpec) => { + if (fieldSpec.format) { + col[fieldSpec.name] = { ...fieldSpec.format }; + } + return col; + }, {}); + getComputedFields() { const scriptFields: any = {}; if (!this.fields) { @@ -318,37 +200,6 @@ export class IndexPattern implements IIndexPattern { }; } - async init() { - if (!this.id) { - return this; // no id === no elasticsearch document - } - - const savedObject = await this.savedObjectsClient.get( - savedObjectType, - this.id - ); - - const response = { - version: savedObject.version, - found: savedObject.version ? true : false, - title: savedObject.attributes.title, - timeFieldName: savedObject.attributes.timeFieldName, - intervalName: savedObject.attributes.intervalName, - fields: savedObject.attributes.fields, - sourceFilters: savedObject.attributes.sourceFilters, - fieldFormatMap: savedObject.attributes.fieldFormatMap, - typeMeta: savedObject.attributes.typeMeta, - type: savedObject.attributes.type, - }; - // Do this before we attempt to update from ES since that call can potentially perform a save - this.originalBody = this.prepBody(); - await this.updateFromElasticSearch(response); - // Do it after to ensure we have the most up to date information - this.originalBody = this.prepBody(); - - return this; - } - public toSpec(): IndexPatternSpec { return { id: this.id, @@ -359,17 +210,28 @@ export class IndexPattern implements IIndexPattern { sourceFilters: this.sourceFilters, fields: this.fields.toSpec({ getFormatterForField: this.getFormatterForField.bind(this) }), typeMeta: this.typeMeta, + type: this.type, }; } - // Get the source filtering configuration for that index. + /** + * Get the source filtering configuration for that index. + */ getSourceFiltering() { return { excludes: (this.sourceFilters && this.sourceFilters.map((filter: any) => filter.value)) || [], }; } - async addScriptedField(name: string, script: string, fieldType: string = 'string', lang: string) { + /** + * Add scripted field to field list + * + * @param name field name + * @param script script code + * @param fieldType + * @param lang + */ + async addScriptedField(name: string, script: string, fieldType: string = 'string') { const scriptedFields = this.getScriptedFields(); const names = _.map(scriptedFields, 'name'); @@ -377,27 +239,24 @@ export class IndexPattern implements IIndexPattern { throw new DuplicateField(name); } - try { - this.fields.add({ - name, - script, - type: fieldType, - scripted: true, - lang, - aggregatable: true, - searchable: true, - count: 0, - readFromDocValues: false, - }); - } catch (err) { - if (err instanceof FieldTypeUnknownError) { - this.unknownFieldErrorNotification(err.fieldSpec.name, err.fieldSpec.type, this.title); - } else { - throw err; - } - } + this.fields.add({ + name, + script, + type: fieldType, + scripted: true, + lang: 'painless', + aggregatable: true, + searchable: true, + count: 0, + readFromDocValues: false, + }); } + /** + * Remove scripted field from field list + * @param fieldName + */ + removeScriptedField(fieldName: string) { const field = this.fields.getByName(fieldName); if (field) { @@ -405,34 +264,6 @@ export class IndexPattern implements IIndexPattern { } } - async popularizeField(fieldName: string, unit = 1) { - /** - * This function is just used by Discover and it's high likely to be removed in the near future - * It doesn't use the save function to skip the error message that's displayed when - * a user adds several columns in a higher frequency that the changes can be persisted to ES - * resulting in 409 errors - */ - if (!this.id) return; - const field = this.fields.getByName(fieldName); - if (!field) { - return; - } - const count = Math.max((field.count || 0) + unit, 0); - if (field.count === count) { - return; - } - field.count = count; - - try { - const res = await this.savedObjectsClient.update(savedObjectType, this.id, this.prepBody(), { - version: this.version, - }); - this.version = res.version; - } catch (e) { - // no need for an error message here - } - } - getNonScriptedFields() { return [...this.fields.getAll().filter((field) => !field.scripted)]; } @@ -450,13 +281,9 @@ export class IndexPattern implements IIndexPattern { return timeField && timeField.esTypes && timeField.esTypes.indexOf('date_nanos') !== -1; } - isTimeBasedWildcard(): boolean { - return this.isTimeBased() && this.isWildcard(); - } - getTimeField() { if (!this.timeFieldName || !this.fields || !this.fields.getByName) return undefined; - return this.fields.getByName(this.timeFieldName) || undefined; + return this.fields.getByName(this.timeFieldName); } getFieldByName(name: string): IndexPatternField | undefined { @@ -468,24 +295,41 @@ export class IndexPattern implements IIndexPattern { return this.typeMeta?.aggs; } - isWildcard() { - return _.includes(this.title, '*'); - } + /** + * Returns index pattern as saved object body for saving + */ + getAsSavedObjectBody() { + const serializeFieldFormatMap = ( + flat: any, + format: FieldFormat | undefined, + field: string | undefined + ) => { + if (format && field) { + flat[field] = format; + } + }; + const serialized = _.transform(this.fieldFormatMap, serializeFieldFormatMap); + const fieldFormatMap = _.isEmpty(serialized) ? undefined : JSON.stringify(serialized); - prepBody() { return { title: this.title, timeFieldName: this.timeFieldName, intervalName: this.intervalName, - sourceFilters: this.mapping.sourceFilters._serialize!(this.sourceFilters), - fields: this.mapping.fields._serialize!(this.fields), - fieldFormatMap: this.mapping.fieldFormatMap._serialize!(this.fieldFormatMap), + sourceFilters: this.sourceFilters ? JSON.stringify(this.sourceFilters) : undefined, + fields: this.fields ? JSON.stringify(this.fields) : undefined, + fieldFormatMap, type: this.type, - typeMeta: this.mapping.typeMeta._serialize!(this.typeMeta), + typeMeta: this.typeMeta ? JSON.stringify(this.typeMeta) : undefined, }; } - getFormatterForField(field: IndexPatternField | IndexPatternField['spec']): FieldFormat { + /** + * Provide a field, get its formatter + * @param field + */ + getFormatterForField( + field: IndexPatternField | IndexPatternField['spec'] | IFieldType + ): FieldFormat { return ( this.fieldFormatMap[field.name] || this.fieldFormats.getDefaultInstance( @@ -494,81 +338,4 @@ export class IndexPattern implements IIndexPattern { ) ); } - - async create(allowOverride: boolean = false) { - const _create = async (duplicateId?: string) => { - if (duplicateId) { - this.patternCache.clear(duplicateId); - await this.savedObjectsClient.delete(savedObjectType, duplicateId); - } - - const body = this.prepBody(); - const response = await this.savedObjectsClient.create(savedObjectType, body, { id: this.id }); - - this.id = response.id; - return response.id; - }; - - const potentialDuplicateByTitle = await findByTitle(this.savedObjectsClient, this.title); - // If there is potentially duplicate title, just create it - if (!potentialDuplicateByTitle) { - return await _create(); - } - - // We found a duplicate but we aren't allowing override, show the warn modal - if (!allowOverride) { - return false; - } - - return await _create(potentialDuplicateByTitle.id); - } - - async _fetchFields() { - const fields = await this.fieldsFetcher.fetch(this); - const scripted = this.getScriptedFields().map((field) => field.spec); - try { - this.fields.replaceAll([...fields, ...scripted]); - } catch (err) { - if (err instanceof FieldTypeUnknownError) { - this.unknownFieldErrorNotification(err.fieldSpec.name, err.fieldSpec.type, this.title); - } else { - throw err; - } - } - } - - refreshFields() { - return ( - this._fetchFields() - // todo - .then(() => this.indexPatternsService.save(this)) - .catch((err) => { - // https://github.com/elastic/kibana/issues/9224 - // This call will attempt to remap fields from the matching - // ES index which may not actually exist. In that scenario, - // we still want to notify the user that there is a problem - // but we do not want to potentially make any pages unusable - // so do not rethrow the error here - - if (err instanceof IndexPatternMissingIndices) { - this.onNotification({ - title: (err as any).message, - color: 'danger', - iconType: 'alert', - }); - return []; - } - - this.onError(err, { - title: i18n.translate('data.indexPatterns.fetchFieldErrorTitle', { - defaultMessage: 'Error fetching fields for index pattern {title} (ID: {id})', - values: { - id: this.id, - title: this.title, - }, - }), - }); - }) - ); - } } diff --git a/src/plugins/data/common/index_patterns/index_patterns/index_patterns.test.ts b/src/plugins/data/common/index_patterns/index_patterns/index_patterns.test.ts index d3b3a73a4b50f..b22437ebbdb4e 100644 --- a/src/plugins/data/common/index_patterns/index_patterns/index_patterns.test.ts +++ b/src/plugins/data/common/index_patterns/index_patterns/index_patterns.test.ts @@ -18,7 +18,7 @@ */ import { defaults } from 'lodash'; -import { IndexPatternsService } from '.'; +import { IndexPatternsService, IndexPattern } from '.'; import { fieldFormatsMock } from '../../field_formats/mocks'; import { stubbedSavedObjectIndexPattern } from '../../../../../fixtures/stubbed_saved_object_index_pattern'; import { UiSettingsCommon, SavedObjectsClientCommon, SavedObject } from '../types'; @@ -31,7 +31,6 @@ const createFieldsFetcher = jest.fn().mockImplementation(() => ({ })); const fieldFormats = fieldFormatsMock; - let object: any = {}; function setDocsourcePayload(id: string | null, providedPayload: any) { @@ -43,16 +42,18 @@ describe('IndexPatterns', () => { let savedObjectsClient: SavedObjectsClientCommon; beforeEach(() => { + const indexPatternObj = { id: 'id', version: 'a', attributes: { title: 'title' } }; savedObjectsClient = {} as SavedObjectsClientCommon; savedObjectsClient.find = jest.fn( - () => - Promise.resolve([{ id: 'id', attributes: { title: 'title' } }]) as Promise< - Array> - > + () => Promise.resolve([indexPatternObj]) as Promise>> ); savedObjectsClient.delete = jest.fn(() => Promise.resolve({}) as Promise); - savedObjectsClient.get = jest.fn().mockImplementation(() => object); savedObjectsClient.create = jest.fn(); + savedObjectsClient.get = jest.fn().mockImplementation(async (type, id) => ({ + id: object.id, + version: object.version, + attributes: object.attributes, + })); savedObjectsClient.update = jest .fn() .mockImplementation(async (type, id, body, { version }) => { @@ -141,30 +142,73 @@ describe('IndexPatterns', () => { }); // Create a normal index patterns - const pattern = await indexPatterns.make('foo'); + const pattern = await indexPatterns.get('foo'); expect(pattern.version).toBe('fooa'); + indexPatterns.clearCache(); // Create the same one - we're going to handle concurrency - const samePattern = await indexPatterns.make('foo'); + const samePattern = await indexPatterns.get('foo'); expect(samePattern.version).toBe('fooaa'); // This will conflict because samePattern did a save (from refreshFields) // but the resave should work fine pattern.title = 'foo2'; - await indexPatterns.save(pattern); + await indexPatterns.updateSavedObject(pattern); // This should not be able to recover samePattern.title = 'foo3'; let result; try { - await indexPatterns.save(samePattern); + await indexPatterns.updateSavedObject(samePattern); } catch (err) { result = err; } expect(result.res.status).toBe(409); }); + + test('create', async () => { + const title = 'kibana-*'; + indexPatterns.refreshFields = jest.fn(); + + const indexPattern = await indexPatterns.create({ title }, true); + expect(indexPattern).toBeInstanceOf(IndexPattern); + expect(indexPattern.title).toBe(title); + expect(indexPatterns.refreshFields).not.toBeCalled(); + + await indexPatterns.create({ title }); + expect(indexPatterns.refreshFields).toBeCalled(); + }); + + test('createAndSave', async () => { + const title = 'kibana-*'; + indexPatterns.createSavedObject = jest.fn(); + indexPatterns.setDefault = jest.fn(); + await indexPatterns.createAndSave({ title }); + expect(indexPatterns.createSavedObject).toBeCalled(); + expect(indexPatterns.setDefault).toBeCalled(); + }); + + test('savedObjectToSpec', () => { + const savedObject = { + id: 'id', + version: 'version', + attributes: { + title: 'kibana-*', + timeFieldName: '@timestamp', + fields: '[]', + sourceFilters: '[{"value":"item1"},{"value":"item2"}]', + fieldFormatMap: '{"field":{}}', + typeMeta: '{}', + type: '', + }, + type: 'index-pattern', + references: [], + }; + + expect(indexPatterns.savedObjectToSpec(savedObject)).toMatchSnapshot(); + }); }); diff --git a/src/plugins/data/common/index_patterns/index_patterns/index_patterns.ts b/src/plugins/data/common/index_patterns/index_patterns/index_patterns.ts index 47484f8ec75bb..9a86541376cd8 100644 --- a/src/plugins/data/common/index_patterns/index_patterns/index_patterns.ts +++ b/src/plugins/data/common/index_patterns/index_patterns/index_patterns.ts @@ -33,9 +33,17 @@ import { IIndexPatternsApiClient, GetFieldsOptions, IndexPatternSpec, + IndexPatternAttributes, + FieldSpec, + FieldFormatMap, + IndexPatternFieldMap, } from '../types'; import { FieldFormatsStartCommon } from '../../field_formats'; import { UI_SETTINGS, SavedObject } from '../../../common'; +import { SavedObjectNotFound } from '../../../../kibana_utils/common'; +import { IndexPatternMissingIndices } from '../lib'; +import { findByTitle } from '../utils'; +import { DuplicateIndexPatternError } from '../errors'; const indexPatternCache = createIndexPatternCache(); const MAX_ATTEMPTS_TO_RESOLVE_CONFLICTS = 3; @@ -86,6 +94,9 @@ export class IndexPatternsService { ); } + /** + * Refresh cache of index pattern ids and titles + */ private async refreshSavedObjectsCache() { this.savedObjectsCache = await this.savedObjectsClient.find({ type: 'index-pattern', @@ -94,6 +105,10 @@ export class IndexPatternsService { }); } + /** + * Get list of index pattern ids + * @param refresh Force refresh of index pattern list + */ getIds = async (refresh: boolean = false) => { if (!this.savedObjectsCache || refresh) { await this.refreshSavedObjectsCache(); @@ -104,6 +119,10 @@ export class IndexPatternsService { return this.savedObjectsCache.map((obj) => obj?.id); }; + /** + * Get list of index pattern titles + * @param refresh Force refresh of index pattern list + */ getTitles = async (refresh: boolean = false): Promise => { if (!this.savedObjectsCache || refresh) { await this.refreshSavedObjectsCache(); @@ -114,14 +133,29 @@ export class IndexPatternsService { return this.savedObjectsCache.map((obj) => obj?.attributes?.title); }; - getFieldsForTimePattern = (options: GetFieldsOptions = {}) => { - return this.apiClient.getFieldsForTimePattern(options); - }; - - getFieldsForWildcard = (options: GetFieldsOptions = {}) => { - return this.apiClient.getFieldsForWildcard(options); + /** + * Get list of index pattern ids with titles + * @param refresh Force refresh of index pattern list + */ + getIdsWithTitle = async ( + refresh: boolean = false + ): Promise> => { + if (!this.savedObjectsCache || refresh) { + await this.refreshSavedObjectsCache(); + } + if (!this.savedObjectsCache) { + return []; + } + return this.savedObjectsCache.map((obj) => ({ + id: obj?.id, + title: obj?.attributes?.title, + })); }; + /** + * Clear index pattern list cache + * @param id optionally clear a single id + */ clearCache = (id?: string) => { this.savedObjectsCache = null; if (id) { @@ -130,6 +164,7 @@ export class IndexPatternsService { indexPatternCache.clearAll(); } }; + getCache = async () => { if (!this.savedObjectsCache) { await this.refreshSavedObjectsCache(); @@ -137,6 +172,9 @@ export class IndexPatternsService { return this.savedObjectsCache; }; + /** + * Get default index pattern + */ getDefault = async () => { const defaultIndexPatternId = await this.config.get('defaultIndex'); if (defaultIndexPatternId) { @@ -146,47 +184,351 @@ export class IndexPatternsService { return null; }; + /** + * Optionally set default index pattern, unless force = true + * @param id + * @param force + */ + setDefault = async (id: string, force = false) => { + if (force || !this.config.get('defaultIndex')) { + await this.config.set('defaultIndex', id); + } + }; + + private isFieldRefreshRequired(specs?: IndexPatternFieldMap): boolean { + if (!specs) { + return true; + } + + return Object.values(specs).every((spec) => { + // See https://github.com/elastic/kibana/pull/8421 + const hasFieldCaps = 'aggregatable' in spec && 'searchable' in spec; + + // See https://github.com/elastic/kibana/pull/11969 + const hasDocValuesFlag = 'readFromDocValues' in spec; + + return !hasFieldCaps || !hasDocValuesFlag; + }); + } + + /** + * Get field list by providing { pattern } + * @param options + */ + getFieldsForWildcard = async (options: GetFieldsOptions = {}) => { + const metaFields = await this.config.get(UI_SETTINGS.META_FIELDS); + return this.apiClient.getFieldsForWildcard({ + pattern: options.pattern, + metaFields, + type: options.type, + params: options.params || {}, + }); + }; + + /** + * Get field list by providing an index patttern (or spec) + * @param options + */ + getFieldsForIndexPattern = async ( + indexPattern: IndexPattern | IndexPatternSpec, + options: GetFieldsOptions = {} + ) => + this.getFieldsForWildcard({ + pattern: indexPattern.title as string, + ...options, + type: indexPattern.type, + params: indexPattern.typeMeta && indexPattern.typeMeta.params, + }); + + /** + * Refresh field list for a given index pattern + * @param indexPattern + */ + refreshFields = async (indexPattern: IndexPattern) => { + try { + const fields = await this.getFieldsForIndexPattern(indexPattern); + const scripted = indexPattern.getScriptedFields().map((field) => field.spec); + indexPattern.fields.replaceAll([...fields, ...scripted]); + } catch (err) { + if (err instanceof IndexPatternMissingIndices) { + this.onNotification({ title: (err as any).message, color: 'danger', iconType: 'alert' }); + } + + this.onError(err, { + title: i18n.translate('data.indexPatterns.fetchFieldErrorTitle', { + defaultMessage: 'Error fetching fields for index pattern {title} (ID: {id})', + values: { id: indexPattern.id, title: indexPattern.title }, + }), + }); + } + }; + + /** + * Refreshes a field list from a spec before an index pattern instance is created + * @param fields + * @param id + * @param title + * @param options + */ + private refreshFieldSpecMap = async ( + fields: IndexPatternFieldMap, + id: string, + title: string, + options: GetFieldsOptions + ) => { + const scriptdFields = Object.values(fields).filter((field) => field.scripted); + try { + const newFields = await this.getFieldsForWildcard(options); + return this.fieldArrayToMap([...newFields, ...scriptdFields]); + } catch (err) { + if (err instanceof IndexPatternMissingIndices) { + this.onNotification({ title: (err as any).message, color: 'danger', iconType: 'alert' }); + return {}; + } + + this.onError(err, { + title: i18n.translate('data.indexPatterns.fetchFieldErrorTitle', { + defaultMessage: 'Error fetching fields for index pattern {title} (ID: {id})', + values: { id, title }, + }), + }); + } + return fields; + }; + + /** + * Applies a set of formats to a set of fields + * @param fieldSpecs + * @param fieldFormatMap + */ + private addFormatsToFields = (fieldSpecs: FieldSpec[], fieldFormatMap: FieldFormatMap) => { + Object.entries(fieldFormatMap).forEach(([fieldName, value]) => { + const field = fieldSpecs.find((fld: FieldSpec) => fld.name === fieldName); + if (field) { + field.format = value; + } + }); + }; + + /** + * Converts field array to map + * @param fields + */ + fieldArrayToMap = (fields: FieldSpec[]) => + fields.reduce((collector, field) => { + collector[field.name] = field; + return collector; + }, {}); + + /** + * Converts index pattern saved object to index pattern spec + * @param savedObject + */ + + savedObjectToSpec = (savedObject: SavedObject): IndexPatternSpec => { + const { + id, + version, + attributes: { + title, + timeFieldName, + intervalName, + fields, + sourceFilters, + fieldFormatMap, + typeMeta, + type, + }, + } = savedObject; + + const parsedSourceFilters = sourceFilters ? JSON.parse(sourceFilters) : undefined; + const parsedTypeMeta = typeMeta ? JSON.parse(typeMeta) : undefined; + const parsedFieldFormatMap = fieldFormatMap ? JSON.parse(fieldFormatMap) : {}; + const parsedFields: FieldSpec[] = fields ? JSON.parse(fields) : []; + + this.addFormatsToFields(parsedFields, parsedFieldFormatMap); + return { + id, + version, + title, + intervalName, + timeFieldName, + sourceFilters: parsedSourceFilters, + fields: this.fieldArrayToMap(parsedFields), + typeMeta: parsedTypeMeta, + type, + }; + }; + + /** + * Get an index pattern by id. Cache optimized + * @param id + */ + get = async (id: string): Promise => { const cache = indexPatternCache.get(id); if (cache) { return cache; } - const indexPattern = await this.make(id); + const savedObject = await this.savedObjectsClient.get( + savedObjectType, + id + ); + + if (!savedObject.version) { + throw new SavedObjectNotFound(savedObjectType, id, 'management/kibana/indexPatterns'); + } + + const spec = this.savedObjectToSpec(savedObject); + const { title, type, typeMeta } = spec; + const parsedFieldFormats: FieldFormatMap = savedObject.attributes.fieldFormatMap + ? JSON.parse(savedObject.attributes.fieldFormatMap) + : {}; + + const isFieldRefreshRequired = this.isFieldRefreshRequired(spec.fields); + let isSaveRequired = isFieldRefreshRequired; + try { + spec.fields = isFieldRefreshRequired + ? await this.refreshFieldSpecMap(spec.fields || {}, id, spec.title as string, { + pattern: title, + metaFields: await this.config.get(UI_SETTINGS.META_FIELDS), + type, + params: typeMeta && typeMeta.params, + }) + : spec.fields; + } catch (err) { + isSaveRequired = false; + if (err instanceof IndexPatternMissingIndices) { + this.onNotification({ + title: (err as any).message, + color: 'danger', + iconType: 'alert', + }); + } else { + this.onError(err, { + title: i18n.translate('data.indexPatterns.fetchFieldErrorTitle', { + defaultMessage: 'Error fetching fields for index pattern {title} (ID: {id})', + values: { id, title }, + }), + }); + } + } + + Object.entries(parsedFieldFormats).forEach(([fieldName, value]) => { + const field = spec.fields?.[fieldName]; + if (field) { + field.format = value; + } + }); + + const indexPattern = await this.create(spec, true); + indexPatternCache.set(id, indexPattern); + if (isSaveRequired) { + try { + this.updateSavedObject(indexPattern); + } catch (err) { + this.onError(err, { + title: i18n.translate('data.indexPatterns.fetchFieldSaveErrorTitle', { + defaultMessage: + 'Error saving after fetching fields for index pattern {title} (ID: {id})', + values: { + id: indexPattern.id, + title: indexPattern.title, + }, + }), + }); + } + } - return indexPatternCache.set(id, indexPattern); + indexPattern.resetOriginalSavedObjectBody(); + return indexPattern; }; - async specToIndexPattern(spec: IndexPatternSpec) { + /** + * Create a new index pattern instance + * @param spec + * @param skipFetchFields + */ + async create(spec: IndexPatternSpec, skipFetchFields = false): Promise { const shortDotsEnable = await this.config.get(UI_SETTINGS.SHORT_DOTS_ENABLE); const metaFields = await this.config.get(UI_SETTINGS.META_FIELDS); - const indexPattern = new IndexPattern(spec.id, { + const indexPattern = new IndexPattern({ + spec, savedObjectsClient: this.savedObjectsClient, - apiClient: this.apiClient, - patternCache: indexPatternCache, fieldFormats: this.fieldFormats, - indexPatternsService: this, - onNotification: this.onNotification, - onError: this.onError, shortDotsEnable, metaFields, }); - indexPattern.initFromSpec(spec); + if (!skipFetchFields) { + await this.refreshFields(indexPattern); + } + + return indexPattern; + } + + /** + * Create a new index pattern and save it right away + * @param spec + * @param override Overwrite if existing index pattern exists + * @param skipFetchFields + */ + + async createAndSave(spec: IndexPatternSpec, override = false, skipFetchFields = false) { + const indexPattern = await this.create(spec, skipFetchFields); + await this.createSavedObject(indexPattern, override); + await this.setDefault(indexPattern.id as string); + return indexPattern; + } + + /** + * Save a new index pattern + * @param indexPattern + * @param override Overwrite if existing index pattern exists + */ + + async createSavedObject(indexPattern: IndexPattern, override = false) { + const dupe = await findByTitle(this.savedObjectsClient, indexPattern.title); + if (dupe) { + if (override) { + await this.delete(dupe.id); + } else { + throw new DuplicateIndexPatternError(`Duplicate index pattern: ${indexPattern.title}`); + } + } + + const body = indexPattern.getAsSavedObjectBody(); + const response = await this.savedObjectsClient.create(savedObjectType, body, { + id: indexPattern.id, + }); + indexPattern.id = response.id; + indexPatternCache.set(indexPattern.id, indexPattern); return indexPattern; } - async save(indexPattern: IndexPattern, saveAttempts: number = 0): Promise { + /** + * Save existing index pattern. Will attempt to merge differences if there are conflicts + * @param indexPattern + * @param saveAttempts + */ + + async updateSavedObject( + indexPattern: IndexPattern, + saveAttempts: number = 0, + ignoreErrors: boolean = false + ): Promise { if (!indexPattern.id) return; - const shortDotsEnable = await this.config.get(UI_SETTINGS.SHORT_DOTS_ENABLE); - const metaFields = await this.config.get(UI_SETTINGS.META_FIELDS); - const body = indexPattern.prepBody(); + // get the list of attributes + const body = indexPattern.getAsSavedObjectBody(); + const originalBody = indexPattern.getOriginalSavedObjectBody(); + // get changed keys const originalChangedKeys: string[] = []; Object.entries(body).forEach(([key, value]) => { - if (value !== indexPattern.originalBody[key]) { + if (value !== (originalBody as any)[key]) { originalChangedKeys.push(key); } }); @@ -197,92 +539,63 @@ export class IndexPatternsService { indexPattern.id = resp.id; indexPattern.version = resp.version; }) - .catch((err) => { + .catch(async (err) => { if (err?.res?.status === 409 && saveAttempts++ < MAX_ATTEMPTS_TO_RESOLVE_CONFLICTS) { - const samePattern = new IndexPattern(indexPattern.id, { - savedObjectsClient: this.savedObjectsClient, - apiClient: this.apiClient, - patternCache: indexPatternCache, - fieldFormats: this.fieldFormats, - indexPatternsService: this, - onNotification: this.onNotification, - onError: this.onError, - shortDotsEnable, - metaFields, + const samePattern = await this.get(indexPattern.id as string); + // What keys changed from now and what the server returned + const updatedBody = samePattern.getAsSavedObjectBody(); + + // Build a list of changed keys from the server response + // and ensure we ignore the key if the server response + // is the same as the original response (since that is expected + // if we made a change in that key) + + const serverChangedKeys: string[] = []; + Object.entries(updatedBody).forEach(([key, value]) => { + if (value !== (body as any)[key] && value !== (originalBody as any)[key]) { + serverChangedKeys.push(key); + } }); - return samePattern.init().then(() => { - // What keys changed from now and what the server returned - const updatedBody = samePattern.prepBody(); - - // Build a list of changed keys from the server response - // and ensure we ignore the key if the server response - // is the same as the original response (since that is expected - // if we made a change in that key) - - const serverChangedKeys: string[] = []; - Object.entries(updatedBody).forEach(([key, value]) => { - if (value !== (body as any)[key] && value !== indexPattern.originalBody[key]) { - serverChangedKeys.push(key); - } - }); - - let unresolvedCollision = false; - for (const originalKey of originalChangedKeys) { - for (const serverKey of serverChangedKeys) { - if (originalKey === serverKey) { - unresolvedCollision = true; - break; - } + let unresolvedCollision = false; + for (const originalKey of originalChangedKeys) { + for (const serverKey of serverChangedKeys) { + if (originalKey === serverKey) { + unresolvedCollision = true; + break; } } + } - if (unresolvedCollision) { - const title = i18n.translate('data.indexPatterns.unableWriteLabel', { - defaultMessage: - 'Unable to write index pattern! Refresh the page to get the most up to date changes for this index pattern.', - }); - - this.onNotification({ title, color: 'danger' }); - throw err; + if (unresolvedCollision) { + if (ignoreErrors) { + return; } - - // Set the updated response on this object - serverChangedKeys.forEach((key) => { - (indexPattern as any)[key] = (samePattern as any)[key]; + const title = i18n.translate('data.indexPatterns.unableWriteLabel', { + defaultMessage: + 'Unable to write index pattern! Refresh the page to get the most up to date changes for this index pattern.', }); - indexPattern.version = samePattern.version; - // Clear cache - indexPatternCache.clear(indexPattern.id!); + this.onNotification({ title, color: 'danger' }); + throw err; + } - // Try the save again - return this.save(indexPattern, saveAttempts); + // Set the updated response on this object + serverChangedKeys.forEach((key) => { + (indexPattern as any)[key] = (samePattern as any)[key]; }); + indexPattern.version = samePattern.version; + + // Clear cache + indexPatternCache.clear(indexPattern.id!); + + // Try the save again + return this.updateSavedObject(indexPattern, saveAttempts, ignoreErrors); } throw err; }); } - async make(id?: string): Promise { - const shortDotsEnable = await this.config.get(UI_SETTINGS.SHORT_DOTS_ENABLE); - const metaFields = await this.config.get(UI_SETTINGS.META_FIELDS); - - const indexPattern = new IndexPattern(id, { - savedObjectsClient: this.savedObjectsClient, - apiClient: this.apiClient, - patternCache: indexPatternCache, - fieldFormats: this.fieldFormats, - indexPatternsService: this, - onNotification: this.onNotification, - onError: this.onError, - shortDotsEnable, - metaFields, - }); - - return indexPattern.init(); - } - /** * Deletes an index pattern from .kibana index * @param indexPatternId: Id of kibana Index Pattern to delete diff --git a/src/plugins/data/common/index_patterns/types.ts b/src/plugins/data/common/index_patterns/types.ts index 7a230c20f6cd0..cb0c3aa0de38e 100644 --- a/src/plugins/data/common/index_patterns/types.ts +++ b/src/plugins/data/common/index_patterns/types.ts @@ -22,29 +22,23 @@ import { ToastInputFields, ErrorToastOptions } from 'src/core/public/notificatio import type { SavedObject } from 'src/core/server'; import { IFieldType } from './fields'; import { SerializedFieldFormat } from '../../../expressions/common'; -import { KBN_FIELD_TYPES } from '..'; +import { KBN_FIELD_TYPES, IndexPatternField, FieldFormat } from '..'; + +export type FieldFormatMap = Record; export interface IIndexPattern { - [key: string]: any; fields: IFieldType[]; title: string; id?: string; type?: string; timeFieldName?: string; getTimeField?(): IFieldType | undefined; - fieldFormatMap?: Record< - string, - { - id: string; - params: unknown; - } - >; + fieldFormatMap?: Record | undefined>; + getFormatterForField?: ( + field: IndexPatternField | IndexPatternField['spec'] | IFieldType + ) => FieldFormat; } -/** - * Use data plugin interface instead - * @deprecated - */ export interface IndexPatternAttributes { type: string; fields: string; @@ -166,15 +160,18 @@ export interface FieldSpec { indexed?: boolean; } +export type IndexPatternFieldMap = Record; + export interface IndexPatternSpec { id?: string; version?: string; - - title: string; + title?: string; + intervalName?: string; timeFieldName?: string; sourceFilters?: SourceFilter[]; - fields?: FieldSpec[]; + fields?: IndexPatternFieldMap; typeMeta?: TypeMeta; + type?: string; } export interface SourceFilter { diff --git a/src/plugins/data/common/search/aggs/buckets/histogram.ts b/src/plugins/data/common/search/aggs/buckets/histogram.ts index 4b631e1fd7cd7..c3d3f041dd0c7 100644 --- a/src/plugins/data/common/search/aggs/buckets/histogram.ts +++ b/src/plugins/data/common/search/aggs/buckets/histogram.ts @@ -158,6 +158,7 @@ export const getHistogramBucketAgg = ({ maxBucketsUiSettings: getConfig(UI_SETTINGS.HISTOGRAM_MAX_BARS), maxBucketsUserInput: aggConfig.params.maxBars, intervalBase: aggConfig.params.intervalBase, + esTypes: aggConfig.params.field?.spec?.esTypes || [], }); }, }, diff --git a/src/plugins/data/common/search/aggs/buckets/lib/histogram_calculate_interval.test.ts b/src/plugins/data/common/search/aggs/buckets/lib/histogram_calculate_interval.test.ts index d3a95b32cd425..7e5e20e5917aa 100644 --- a/src/plugins/data/common/search/aggs/buckets/lib/histogram_calculate_interval.test.ts +++ b/src/plugins/data/common/search/aggs/buckets/lib/histogram_calculate_interval.test.ts @@ -21,6 +21,7 @@ import { calculateHistogramInterval, CalculateHistogramIntervalParams, } from './histogram_calculate_interval'; +import { ES_FIELD_TYPES } from '../../../../types'; describe('calculateHistogramInterval', () => { describe('auto calculating mode', () => { @@ -36,10 +37,91 @@ describe('calculateHistogramInterval', () => { min: 0, max: 1, }, + esTypes: [], }; }); describe('maxBucketsUserInput is defined', () => { + test('should set 1 as an interval for integer numbers that are less than maxBuckets #1', () => { + const p = { + ...params, + maxBucketsUserInput: 100, + values: { + min: 1, + max: 50, + }, + esTypes: [ES_FIELD_TYPES.INTEGER], + }; + expect(calculateHistogramInterval(p)).toEqual(1); + }); + + test('should set 1 as an interval for integer numbers that are less than maxBuckets #2', () => { + const p = { + ...params, + maxBucketsUiSettings: 1000, + maxBucketsUserInput: 258, + values: { + min: 521, + max: 689, + }, + esTypes: [ES_FIELD_TYPES.INTEGER], + }; + expect(calculateHistogramInterval(p)).toEqual(1); + }); + + test('should set correct interval for integer numbers that are greater than maxBuckets #1', () => { + const p = { + ...params, + maxBucketsUserInput: 100, + values: { + min: 400, + max: 790, + }, + esTypes: [ES_FIELD_TYPES.INTEGER, ES_FIELD_TYPES.SHORT], + }; + expect(calculateHistogramInterval(p)).toEqual(5); + }); + + test('should set correct interval for integer numbers that are greater than maxBuckets #2', () => { + // diff === 3456211; interval === 50000; buckets === 69 + const p = { + ...params, + maxBucketsUserInput: 100, + values: { + min: 567, + max: 3456778, + }, + esTypes: [ES_FIELD_TYPES.LONG], + }; + expect(calculateHistogramInterval(p)).toEqual(50000); + }); + + test('should not set integer interval if the field type is float #1', () => { + const p = { + ...params, + maxBucketsUserInput: 100, + values: { + min: 0, + max: 1, + }, + esTypes: [ES_FIELD_TYPES.FLOAT], + }; + expect(calculateHistogramInterval(p)).toEqual(0.01); + }); + + test('should not set integer interval if the field type is float #2', () => { + const p = { + ...params, + maxBucketsUserInput: 100, + values: { + min: 0, + max: 1, + }, + esTypes: [ES_FIELD_TYPES.INTEGER, ES_FIELD_TYPES.FLOAT], + }; + expect(calculateHistogramInterval(p)).toEqual(0.01); + }); + test('should not set interval which more than largest possible', () => { const p = { ...params, @@ -48,6 +130,7 @@ describe('calculateHistogramInterval', () => { min: 150, max: 250, }, + esTypes: [ES_FIELD_TYPES.SHORT], }; expect(calculateHistogramInterval(p)).toEqual(1); }); @@ -61,6 +144,7 @@ describe('calculateHistogramInterval', () => { min: 0.1, max: 0.9, }, + esTypes: [ES_FIELD_TYPES.FLOAT], }) ).toBe(0.02); }); @@ -74,6 +158,7 @@ describe('calculateHistogramInterval', () => { min: 10.45, max: 1000.05, }, + esTypes: [ES_FIELD_TYPES.FLOAT], }) ).toBe(100); }); @@ -88,6 +173,7 @@ describe('calculateHistogramInterval', () => { min: 0, max: 100, }, + esTypes: [ES_FIELD_TYPES.BYTE], }) ).toEqual(1); }); @@ -100,8 +186,9 @@ describe('calculateHistogramInterval', () => { min: 1, max: 10, }, + esTypes: [ES_FIELD_TYPES.INTEGER], }) - ).toEqual(0.1); + ).toEqual(1); }); test('should set intervals for integer numbers (diff more than maxBucketsUiSettings)', () => { @@ -113,6 +200,7 @@ describe('calculateHistogramInterval', () => { min: 45678, max: 90123, }, + esTypes: [ES_FIELD_TYPES.INTEGER], }) ).toEqual(500); }); @@ -127,6 +215,7 @@ describe('calculateHistogramInterval', () => { min: 1.245, max: 2.9, }, + esTypes: [ES_FIELD_TYPES.FLOAT], }) ).toEqual(0.02); expect( @@ -136,6 +225,7 @@ describe('calculateHistogramInterval', () => { min: 0.5, max: 2.3, }, + esTypes: [ES_FIELD_TYPES.FLOAT], }) ).toEqual(0.02); }); @@ -149,6 +239,7 @@ describe('calculateHistogramInterval', () => { min: 0.1, max: 0.9, }, + esTypes: [ES_FIELD_TYPES.FLOAT], }) ).toBe(0.01); }); diff --git a/src/plugins/data/common/search/aggs/buckets/lib/histogram_calculate_interval.ts b/src/plugins/data/common/search/aggs/buckets/lib/histogram_calculate_interval.ts index 378340e876296..313ecf1000f41 100644 --- a/src/plugins/data/common/search/aggs/buckets/lib/histogram_calculate_interval.ts +++ b/src/plugins/data/common/search/aggs/buckets/lib/histogram_calculate_interval.ts @@ -18,6 +18,7 @@ */ import { isAutoInterval } from '../_interval_options'; +import { ES_FIELD_TYPES } from '../../../../types'; interface IntervalValuesRange { min: number; @@ -28,6 +29,7 @@ export interface CalculateHistogramIntervalParams { interval: string; maxBucketsUiSettings: number; maxBucketsUserInput?: number | ''; + esTypes: ES_FIELD_TYPES[]; intervalBase?: number; values?: IntervalValuesRange; } @@ -77,11 +79,27 @@ const calculateForGivenInterval = ( - The lower power of 10, times 2 - The lower power of 10, times 5 **/ -const calculateAutoInterval = (diff: number, maxBars: number) => { +const calculateAutoInterval = (diff: number, maxBars: number, esTypes: ES_FIELD_TYPES[]) => { const exactInterval = diff / maxBars; - const lowerPower = Math.pow(10, Math.floor(Math.log10(exactInterval))); + // For integer fields that are less than maxBars, we should use 1 as the value of interval + // Elastic has 4 integer data types: long, integer, short, byte + // see: https://www.elastic.co/guide/en/elasticsearch/reference/current/number.html + if ( + diff < maxBars && + esTypes.every((esType) => + [ + ES_FIELD_TYPES.INTEGER, + ES_FIELD_TYPES.LONG, + ES_FIELD_TYPES.SHORT, + ES_FIELD_TYPES.BYTE, + ].includes(esType) + ) + ) { + return 1; + } + const lowerPower = Math.pow(10, Math.floor(Math.log10(exactInterval))); const autoBuckets = diff / lowerPower; if (autoBuckets > maxBars) { @@ -103,6 +121,7 @@ export const calculateHistogramInterval = ({ maxBucketsUserInput, intervalBase, values, + esTypes, }: CalculateHistogramIntervalParams) => { const isAuto = isAutoInterval(interval); let calculatedInterval = isAuto ? 0 : parseFloat(interval); @@ -119,8 +138,10 @@ export const calculateHistogramInterval = ({ calculatedInterval = isAuto ? calculateAutoInterval( diff, + // Mind maxBucketsUserInput can be an empty string, hence we need to ensure it here - Math.min(maxBucketsUiSettings, maxBucketsUserInput || maxBucketsUiSettings) + Math.min(maxBucketsUiSettings, maxBucketsUserInput || maxBucketsUiSettings), + esTypes ) : calculateForGivenInterval(diff, calculatedInterval, maxBucketsUiSettings); } diff --git a/src/plugins/data/common/search/aggs/buckets/shard_delay.test.ts b/src/plugins/data/common/search/aggs/buckets/shard_delay.test.ts new file mode 100644 index 0000000000000..15399ffc43791 --- /dev/null +++ b/src/plugins/data/common/search/aggs/buckets/shard_delay.test.ts @@ -0,0 +1,76 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { AggConfigs } from '../agg_configs'; +import { FieldFormatsGetConfigFn, NumberFormat } from '../../../../common/field_formats'; +import { getShardDelayBucketAgg, SHARD_DELAY_AGG_NAME } from './shard_delay'; + +describe('Shard Delay Agg', () => { + const getConfig = (() => {}) as FieldFormatsGetConfigFn; + const getAggConfigs = () => { + const field = { name: 'bytes' }; + + const indexPattern = { + id: '1234', + title: 'logstash-*', + fields: { + getByName: () => field, + filter: () => [field], + }, + getFormatterForField: () => + new NumberFormat( + { + pattern: '0,0.[000] b', + }, + getConfig + ), + } as any; + + return new AggConfigs( + indexPattern, + [ + { + type: SHARD_DELAY_AGG_NAME, + params: { + duration: 1000, + }, + }, + ], + { + typesRegistry: { + get: getShardDelayBucketAgg, + } as any, + } + ); + }; + + describe('write', () => { + test('writes the delay as the value parameter', () => { + const aggConfigs = getAggConfigs(); + const agg = aggConfigs.aggs[0]; + expect(agg.write(aggConfigs)).toMatchInlineSnapshot(` + Object { + "params": Object { + "value": "5s", + }, + } + `); + }); + }); +}); diff --git a/src/plugins/data/common/search/aggs/buckets/shard_delay.ts b/src/plugins/data/common/search/aggs/buckets/shard_delay.ts new file mode 100644 index 0000000000000..2decf5a74bc85 --- /dev/null +++ b/src/plugins/data/common/search/aggs/buckets/shard_delay.ts @@ -0,0 +1,50 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { BucketAggType } from './bucket_agg_type'; +import { BaseAggParams } from '../types'; +import { aggShardDelayFnName } from './shard_delay_fn'; + +export const SHARD_DELAY_AGG_NAME = 'shard_delay'; + +export interface AggParamsShardDelay extends BaseAggParams { + delay?: number; +} + +export const getShardDelayBucketAgg = () => + new BucketAggType({ + name: SHARD_DELAY_AGG_NAME, + title: 'Shard Delay', + expressionName: aggShardDelayFnName, + createFilter: () => ({ match_all: {} }), + customLabels: false, + params: [ + { + name: 'delay', + type: 'string', + default: '5s', + write(aggConfig, output) { + output.params = { + ...output.params, + value: aggConfig.params.delay, + }; + }, + }, + ], + }); diff --git a/src/plugins/data/common/search/aggs/buckets/shard_delay_fn.test.ts b/src/plugins/data/common/search/aggs/buckets/shard_delay_fn.test.ts new file mode 100644 index 0000000000000..b0ebfb005c218 --- /dev/null +++ b/src/plugins/data/common/search/aggs/buckets/shard_delay_fn.test.ts @@ -0,0 +1,65 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { functionWrapper } from '../test_helpers'; +import { aggShardDelay } from './shard_delay_fn'; + +describe('agg_expression_functions', () => { + describe('aggShardDelay', () => { + const fn = functionWrapper(aggShardDelay()); + + test('correctly serializes', () => { + const actual = fn({ + delay: 1000, + }); + expect(actual).toMatchInlineSnapshot(` + Object { + "type": "agg_type", + "value": Object { + "enabled": true, + "id": undefined, + "params": Object { + "customLabel": undefined, + "delay": 1000, + "json": undefined, + }, + "schema": undefined, + "type": "shard_delay", + }, + } + `); + }); + + test('correctly parses json string argument', () => { + const actual = fn({ + delay: 1000, + json: '{ "foo": true }', + }); + + expect(actual.value.params.json).toEqual({ foo: true }); + + expect(() => { + fn({ + delay: 1000, + json: '/// intentionally malformed json ///', + }); + }).toThrowErrorMatchingInlineSnapshot(`"Unable to parse json argument string"`); + }); + }); +}); diff --git a/src/plugins/data/common/search/aggs/buckets/shard_delay_fn.ts b/src/plugins/data/common/search/aggs/buckets/shard_delay_fn.ts new file mode 100644 index 0000000000000..86de428fa03d7 --- /dev/null +++ b/src/plugins/data/common/search/aggs/buckets/shard_delay_fn.ts @@ -0,0 +1,105 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { i18n } from '@kbn/i18n'; +import { Assign } from '@kbn/utility-types'; +import { ExpressionFunctionDefinition } from 'src/plugins/expressions/common'; +import { AggExpressionType, AggConfigSerialized } from '../'; +import { getParsedValue } from '../utils/get_parsed_value'; +import { AggParamsShardDelay, SHARD_DELAY_AGG_NAME } from './shard_delay'; + +export const aggShardDelayFnName = 'aggShardDelay'; + +type Input = any; +type AggArgs = AggParamsShardDelay & Pick; + +type Arguments = Assign; + +type Output = AggExpressionType; +type FunctionDefinition = ExpressionFunctionDefinition< + typeof aggShardDelayFnName, + Input, + Arguments, + Output +>; + +export const aggShardDelay = (): FunctionDefinition => ({ + name: aggShardDelayFnName, + help: i18n.translate('data.search.aggs.function.buckets.shardDelay.help', { + defaultMessage: 'Generates a serialized agg config for a Shard Delay agg', + }), + type: 'agg_type', + args: { + id: { + types: ['string'], + help: i18n.translate('data.search.aggs.buckets.shardDelay.id.help', { + defaultMessage: 'ID for this aggregation', + }), + }, + enabled: { + types: ['boolean'], + default: true, + help: i18n.translate('data.search.aggs.buckets.shardDelay.enabled.help', { + defaultMessage: 'Specifies whether this aggregation should be enabled', + }), + }, + schema: { + types: ['string'], + help: i18n.translate('data.search.aggs.buckets.shardDelay.schema.help', { + defaultMessage: 'Schema to use for this aggregation', + }), + }, + delay: { + types: ['number'], + help: i18n.translate('data.search.aggs.buckets.shardDelay.delay.help', { + defaultMessage: 'Delay in ms between shards to process.', + }), + }, + json: { + types: ['string'], + help: i18n.translate('data.search.aggs.buckets.shardDelay.json.help', { + defaultMessage: 'Advanced json to include when the agg is sent to Elasticsearch', + }), + }, + customLabel: { + types: ['string'], + help: i18n.translate('data.search.aggs.buckets.shardDelay.customLabel.help', { + defaultMessage: 'Represents a custom label for this aggregation', + }), + }, + }, + fn: (input, args) => { + const { id, enabled, schema, ...rest } = args; + + return { + type: 'agg_type', + value: { + id, + enabled, + schema, + type: SHARD_DELAY_AGG_NAME, + params: { + ...rest, + json: getParsedValue(args, 'json'), + delay: getParsedValue(args, 'delay'), + }, + }, + }; + }, +}); diff --git a/src/plugins/data/common/search/aggs/param_types/field.ts b/src/plugins/data/common/search/aggs/param_types/field.ts index 492294bdf4e5f..a0bc71ac8e156 100644 --- a/src/plugins/data/common/search/aggs/param_types/field.ts +++ b/src/plugins/data/common/search/aggs/param_types/field.ts @@ -90,9 +90,10 @@ export class FieldParamType extends BaseParamType { 'data.search.aggs.paramTypes.field.invalidSavedFieldParameterErrorMessage', { defaultMessage: - 'Saved {fieldParameter} parameter is now invalid. Please select a new field.', + 'Saved field "{fieldParameter}" is invalid for use with the "{aggType}" aggregation. Please select a new field.', values: { - fieldParameter: '"field"', + fieldParameter: fieldName, + aggType: aggConfig?.type?.title, }, } ) diff --git a/src/plugins/data/common/search/es_search/index.ts b/src/plugins/data/common/search/es_search/index.ts index d8f7b5091eb8f..8e8897c7d7517 100644 --- a/src/plugins/data/common/search/es_search/index.ts +++ b/src/plugins/data/common/search/es_search/index.ts @@ -18,3 +18,4 @@ */ export * from './types'; +export * from './utils'; diff --git a/src/plugins/data/common/search/es_search/types.ts b/src/plugins/data/common/search/es_search/types.ts index 81124c1e095f7..b1c3e5cdd3960 100644 --- a/src/plugins/data/common/search/es_search/types.ts +++ b/src/plugins/data/common/search/es_search/types.ts @@ -37,22 +37,8 @@ export type ISearchRequestParams> = { trackTotalHits?: boolean; } & Search; -export interface IEsSearchRequest extends IKibanaSearchRequest { - params?: ISearchRequestParams; +export interface IEsSearchRequest extends IKibanaSearchRequest { indexType?: string; } -export interface IEsSearchResponse extends IKibanaSearchResponse { - /** - * Indicates whether async search is still in flight - */ - isRunning?: boolean; - /** - * Indicates whether the results returned are complete or partial - */ - isPartial?: boolean; - rawResponse: SearchResponse; -} - -export const isEsResponse = (response: any): response is IEsSearchResponse => - response && response.rawResponse; +export type IEsSearchResponse = IKibanaSearchResponse>; diff --git a/src/plugins/data/common/search/es_search/utils.ts b/src/plugins/data/common/search/es_search/utils.ts new file mode 100644 index 0000000000000..ec66a3d3f923e --- /dev/null +++ b/src/plugins/data/common/search/es_search/utils.ts @@ -0,0 +1,41 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { IKibanaSearchResponse } from '..'; + +/** + * @returns true if response had an error while executing in ES + */ +export const isErrorResponse = (response?: IKibanaSearchResponse) => { + return !response || (!response.isRunning && response.isPartial); +}; + +/** + * @returns true if response is completed successfully + */ +export const isCompleteResponse = (response?: IKibanaSearchResponse) => { + return response && !response.isRunning && !response.isPartial; +}; + +/** + * @returns true if request is still running an/d response contains partial results + */ +export const isPartialResponse = (response?: IKibanaSearchResponse) => { + return response && response.isRunning && response.isPartial; +}; diff --git a/src/plugins/data/common/search/index.ts b/src/plugins/data/common/search/index.ts index 061974d860246..2ee0db384cf06 100644 --- a/src/plugins/data/common/search/index.ts +++ b/src/plugins/data/common/search/index.ts @@ -20,6 +20,6 @@ export * from './aggs'; export * from './es_search'; export * from './expressions'; +export * from './search_source'; export * from './tabify'; export * from './types'; -export * from './es_search'; diff --git a/src/plugins/data/public/search/search_source/create_search_source.test.ts b/src/plugins/data/common/search/search_source/create_search_source.test.ts similarity index 96% rename from src/plugins/data/public/search/search_source/create_search_source.test.ts rename to src/plugins/data/common/search/search_source/create_search_source.test.ts index 6b6cfb0c9b1ca..dde5983fe73fb 100644 --- a/src/plugins/data/public/search/search_source/create_search_source.test.ts +++ b/src/plugins/data/common/search/search_source/create_search_source.test.ts @@ -19,9 +19,9 @@ import { createSearchSource as createSearchSourceFactory } from './create_search_source'; import { SearchSourceDependencies } from './search_source'; -import { IIndexPattern } from '../../../common/index_patterns'; +import { IIndexPattern } from '../../index_patterns'; import { IndexPatternsContract } from '../../index_patterns/index_patterns'; -import { Filter } from '../../../common/es_query/filters'; +import { Filter } from '../../es_query/filters'; import { BehaviorSubject } from 'rxjs'; describe('createSearchSource', () => { diff --git a/src/plugins/data/public/search/search_source/create_search_source.ts b/src/plugins/data/common/search/search_source/create_search_source.ts similarity index 100% rename from src/plugins/data/public/search/search_source/create_search_source.ts rename to src/plugins/data/common/search/search_source/create_search_source.ts diff --git a/src/plugins/data/public/search/search_source/extract_references.ts b/src/plugins/data/common/search/search_source/extract_references.ts similarity index 94% rename from src/plugins/data/public/search/search_source/extract_references.ts rename to src/plugins/data/common/search/search_source/extract_references.ts index f9987767a9688..72d93e41305d1 100644 --- a/src/plugins/data/public/search/search_source/extract_references.ts +++ b/src/plugins/data/common/search/search_source/extract_references.ts @@ -17,8 +17,8 @@ * under the License. */ -import { SavedObjectReference } from '../../../../../core/types'; -import { Filter } from '../../../common/es_query/filters'; +import { SavedObjectReference } from 'src/core/types'; +import { Filter } from '../../es_query/filters'; import { SearchSourceFields } from './types'; export const extractReferences = ( diff --git a/src/plugins/data/public/search/fetch/get_search_params.test.ts b/src/plugins/data/common/search/search_source/fetch/get_search_params.test.ts similarity index 93% rename from src/plugins/data/public/search/fetch/get_search_params.test.ts rename to src/plugins/data/common/search/search_source/fetch/get_search_params.test.ts index 5e83e1f57bb6d..8778eb4fd559d 100644 --- a/src/plugins/data/public/search/fetch/get_search_params.test.ts +++ b/src/plugins/data/common/search/search_source/fetch/get_search_params.test.ts @@ -17,8 +17,9 @@ * under the License. */ +import { UI_SETTINGS } from '../../../constants'; +import { GetConfigFn } from '../../../types'; import { getSearchParams } from './get_search_params'; -import { GetConfigFn, UI_SETTINGS } from '../../../common'; function getConfigStub(config: any = {}): GetConfigFn { return (key) => config[key]; diff --git a/src/plugins/data/public/search/fetch/get_search_params.ts b/src/plugins/data/common/search/search_source/fetch/get_search_params.ts similarity index 92% rename from src/plugins/data/public/search/fetch/get_search_params.ts rename to src/plugins/data/common/search/search_source/fetch/get_search_params.ts index ed87c4813951c..556fb4924da56 100644 --- a/src/plugins/data/public/search/fetch/get_search_params.ts +++ b/src/plugins/data/common/search/search_source/fetch/get_search_params.ts @@ -17,7 +17,9 @@ * under the License. */ -import { UI_SETTINGS, ISearchRequestParams, GetConfigFn } from '../../../common'; +import { UI_SETTINGS } from '../../../constants'; +import { GetConfigFn } from '../../../types'; +import { ISearchRequestParams } from '../../index'; import { SearchRequest } from './types'; const sessionId = Date.now(); diff --git a/src/plugins/data/common/search/search_source/fetch/index.ts b/src/plugins/data/common/search/search_source/fetch/index.ts new file mode 100644 index 0000000000000..1b9a9677e4a99 --- /dev/null +++ b/src/plugins/data/common/search/search_source/fetch/index.ts @@ -0,0 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export { getSearchParams, getSearchParamsFromRequest, getPreference } from './get_search_params'; +export { RequestFailure } from './request_error'; +export * from './types'; diff --git a/src/plugins/data/public/search/fetch/request_error.ts b/src/plugins/data/common/search/search_source/fetch/request_error.ts similarity index 95% rename from src/plugins/data/public/search/fetch/request_error.ts rename to src/plugins/data/common/search/search_source/fetch/request_error.ts index efaaafadf404e..ba5eb6f2897a9 100644 --- a/src/plugins/data/public/search/fetch/request_error.ts +++ b/src/plugins/data/common/search/search_source/fetch/request_error.ts @@ -18,7 +18,7 @@ */ import { SearchResponse } from 'elasticsearch'; -import { KbnError } from '../../../../kibana_utils/common'; +import { KbnError } from '../../../../../kibana_utils/common'; import { SearchError } from './types'; /** diff --git a/src/plugins/data/common/search/search_source/fetch/types.ts b/src/plugins/data/common/search/search_source/fetch/types.ts new file mode 100644 index 0000000000000..30055f88012f2 --- /dev/null +++ b/src/plugins/data/common/search/search_source/fetch/types.ts @@ -0,0 +1,54 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { SearchResponse } from 'elasticsearch'; +import { LegacyFetchHandlers } from '../legacy/types'; +import { GetConfigFn } from '../../../types'; + +/** + * @internal + * + * This type is used when flattenning a SearchSource and passing it down to legacy search. + * Once legacy search is removed, this type should become internal to `SearchSource`, + * where `ISearchRequestParams` is used externally instead. + */ +export type SearchRequest = Record; + +export interface FetchHandlers { + getConfig: GetConfigFn; + /** + * Callback which can be used to hook into responses, modify them, or perform + * side effects like displaying UI errors on the client. + */ + onResponse: (request: SearchRequest, response: SearchResponse) => SearchResponse; + /** + * These handlers are only used by the legacy defaultSearchStrategy and can be removed + * once that strategy has been deprecated. + */ + legacy: LegacyFetchHandlers; +} + +export interface SearchError { + name: string; + status: string; + title: string; + message: string; + path: string; + type: string; +} diff --git a/src/plugins/data/public/search/search_source/filter_docvalue_fields.test.ts b/src/plugins/data/common/search/search_source/filter_docvalue_fields.test.ts similarity index 100% rename from src/plugins/data/public/search/search_source/filter_docvalue_fields.test.ts rename to src/plugins/data/common/search/search_source/filter_docvalue_fields.test.ts diff --git a/src/plugins/data/public/search/search_source/filter_docvalue_fields.ts b/src/plugins/data/common/search/search_source/filter_docvalue_fields.ts similarity index 100% rename from src/plugins/data/public/search/search_source/filter_docvalue_fields.ts rename to src/plugins/data/common/search/search_source/filter_docvalue_fields.ts diff --git a/src/plugins/data/common/search/search_source/index.ts b/src/plugins/data/common/search/search_source/index.ts new file mode 100644 index 0000000000000..2ef1b4c3c5199 --- /dev/null +++ b/src/plugins/data/common/search/search_source/index.ts @@ -0,0 +1,28 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export { createSearchSource } from './create_search_source'; +export { injectReferences } from './inject_references'; +export { extractReferences } from './extract_references'; +export { parseSearchSourceJSON } from './parse_json'; +export * from './fetch'; +export * from './legacy'; +export * from './search_source'; +export * from './search_source_service'; +export * from './types'; diff --git a/src/plugins/data/common/search/search_source/inject_references.test.ts b/src/plugins/data/common/search/search_source/inject_references.test.ts new file mode 100644 index 0000000000000..c607f16d24734 --- /dev/null +++ b/src/plugins/data/common/search/search_source/inject_references.test.ts @@ -0,0 +1,120 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { SavedObjectReference } from 'src/core/types'; +import { SearchSourceFields } from './types'; + +import { injectReferences } from './inject_references'; + +describe('injectSearchSourceReferences', () => { + let searchSourceJSON: SearchSourceFields & { indexRefName: string }; + let references: SavedObjectReference[]; + + beforeEach(() => { + searchSourceJSON = { + highlightAll: true, + version: true, + query: { + query: 'play_name:"Henry IV"', + language: 'kuery', + }, + indexRefName: 'kibanaSavedObjectMeta.searchSourceJSON.index', + }; + references = [ + { + name: 'kibanaSavedObjectMeta.searchSourceJSON.index', + type: 'index-pattern', + id: '033af690-fde7-11ea-91f3-fb9e73f9bbe9', + }, + ]; + }); + + test('injects references', () => { + const actual = injectReferences(searchSourceJSON, references); + expect(actual).toMatchInlineSnapshot(` + Object { + "highlightAll": true, + "index": "033af690-fde7-11ea-91f3-fb9e73f9bbe9", + "query": Object { + "language": "kuery", + "query": "play_name:\\"Henry IV\\"", + }, + "version": true, + } + `); + }); + + test('skips injecting references if none exists', () => { + // @ts-expect-error + delete searchSourceJSON.indexRefName; + references = []; + const actual = injectReferences(searchSourceJSON, references); + expect(actual).toMatchInlineSnapshot(` + Object { + "highlightAll": true, + "query": Object { + "language": "kuery", + "query": "play_name:\\"Henry IV\\"", + }, + "version": true, + } + `); + }); + + test('throws an error if there is a broken reference', () => { + searchSourceJSON.indexRefName = 'oops'; + expect(() => injectReferences(searchSourceJSON, references)).toThrowErrorMatchingInlineSnapshot( + `"Could not find reference for oops"` + ); + }); + + test('handles filters', () => { + searchSourceJSON.filter = [ + // @ts-expect-error + { meta: { indexRefName: 'kibanaSavedObjectMeta.searchSourceJSON.index' } }, + ]; + const actual = injectReferences(searchSourceJSON, references); + expect(actual).toMatchInlineSnapshot(` + Object { + "filter": Array [ + Object { + "meta": Object { + "index": "033af690-fde7-11ea-91f3-fb9e73f9bbe9", + }, + }, + ], + "highlightAll": true, + "index": "033af690-fde7-11ea-91f3-fb9e73f9bbe9", + "query": Object { + "language": "kuery", + "query": "play_name:\\"Henry IV\\"", + }, + "version": true, + } + `); + }); + + test('throws an error if there is a broken filter reference', () => { + // @ts-expect-error + searchSourceJSON.filter = [{ meta: { indexRefName: 'oops' } }]; + expect(() => injectReferences(searchSourceJSON, references)).toThrowErrorMatchingInlineSnapshot( + `"Could not find reference for oops"` + ); + }); +}); diff --git a/src/plugins/data/public/search/search_source/inject_references.ts b/src/plugins/data/common/search/search_source/inject_references.ts similarity index 96% rename from src/plugins/data/public/search/search_source/inject_references.ts rename to src/plugins/data/common/search/search_source/inject_references.ts index 07f37c3c11275..81fafc6dcae06 100644 --- a/src/plugins/data/public/search/search_source/inject_references.ts +++ b/src/plugins/data/common/search/search_source/inject_references.ts @@ -17,8 +17,8 @@ * under the License. */ +import { SavedObjectReference } from 'src/core/types'; import { SearchSourceFields } from './types'; -import { SavedObjectReference } from '../../../../../core/types'; export const injectReferences = ( searchSourceFields: SearchSourceFields & { indexRefName: string }, diff --git a/src/plugins/data/public/search/legacy/call_client.test.ts b/src/plugins/data/common/search/search_source/legacy/call_client.test.ts similarity index 100% rename from src/plugins/data/public/search/legacy/call_client.test.ts rename to src/plugins/data/common/search/search_source/legacy/call_client.test.ts diff --git a/src/plugins/data/public/search/legacy/call_client.ts b/src/plugins/data/common/search/search_source/legacy/call_client.ts similarity index 93% rename from src/plugins/data/public/search/legacy/call_client.ts rename to src/plugins/data/common/search/search_source/legacy/call_client.ts index b87affdd59c54..cb6295dd701ee 100644 --- a/src/plugins/data/public/search/legacy/call_client.ts +++ b/src/plugins/data/common/search/search_source/legacy/call_client.ts @@ -18,10 +18,9 @@ */ import { SearchResponse } from 'elasticsearch'; -import { ISearchOptions } from 'src/plugins/data/common'; -import { FetchHandlers } from '../fetch'; +import { FetchHandlers, SearchRequest } from '../fetch'; import { defaultSearchStrategy } from './default_search_strategy'; -import { SearchRequest } from '../index'; +import { ISearchOptions } from '../../index'; export function callClient( searchRequests: SearchRequest[], diff --git a/src/plugins/data/common/search/search_source/legacy/default_search_strategy.test.ts b/src/plugins/data/common/search/search_source/legacy/default_search_strategy.test.ts new file mode 100644 index 0000000000000..3badd456bd72a --- /dev/null +++ b/src/plugins/data/common/search/search_source/legacy/default_search_strategy.test.ts @@ -0,0 +1,71 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { defaultSearchStrategy } from './default_search_strategy'; +import { LegacyFetchHandlers, SearchStrategySearchParams } from './types'; +import { BehaviorSubject } from 'rxjs'; + +const { search } = defaultSearchStrategy; + +describe('defaultSearchStrategy', () => { + describe('search', () => { + let searchArgs: MockedKeys; + + beforeEach(() => { + searchArgs = { + searchRequests: [ + { + index: { title: 'foo' }, + body: {}, + }, + ], + getConfig: jest.fn(), + onResponse: (req, res) => res, + legacy: { + callMsearch: jest.fn().mockResolvedValue(undefined), + loadingCount$: new BehaviorSubject(0) as any, + } as jest.Mocked, + }; + }); + + test('calls callMsearch with the correct arguments', async () => { + await search({ ...searchArgs }); + expect(searchArgs.legacy.callMsearch.mock.calls).toMatchInlineSnapshot(` + Array [ + Array [ + Object { + "body": Object { + "searches": Array [ + Object { + "body": Object {}, + "header": Object { + "index": "foo", + "preference": undefined, + }, + }, + ], + }, + "signal": AbortSignal {}, + }, + ], + ] + `); + }); + }); +}); diff --git a/src/plugins/data/public/search/legacy/default_search_strategy.ts b/src/plugins/data/common/search/search_source/legacy/default_search_strategy.ts similarity index 100% rename from src/plugins/data/public/search/legacy/default_search_strategy.ts rename to src/plugins/data/common/search/search_source/legacy/default_search_strategy.ts diff --git a/src/plugins/data/public/search/legacy/fetch_soon.test.ts b/src/plugins/data/common/search/search_source/legacy/fetch_soon.test.ts similarity index 96% rename from src/plugins/data/public/search/legacy/fetch_soon.test.ts rename to src/plugins/data/common/search/search_source/legacy/fetch_soon.test.ts index 7243ab158009a..81117513917c0 100644 --- a/src/plugins/data/public/search/legacy/fetch_soon.test.ts +++ b/src/plugins/data/common/search/search_source/legacy/fetch_soon.test.ts @@ -17,12 +17,13 @@ * under the License. */ -import { fetchSoon } from './fetch_soon'; -import { callClient } from './call_client'; -import { FetchHandlers } from '../fetch/types'; -import { SearchRequest } from '../index'; import { SearchResponse } from 'elasticsearch'; -import { GetConfigFn, UI_SETTINGS, ISearchOptions } from '../../../common'; +import { UI_SETTINGS } from '../../../constants'; +import { GetConfigFn } from '../../../types'; +import { FetchHandlers, SearchRequest } from '../fetch'; +import { ISearchOptions } from '../../index'; +import { callClient } from './call_client'; +import { fetchSoon } from './fetch_soon'; function getConfigStub(config: any = {}): GetConfigFn { return (key) => config[key]; diff --git a/src/plugins/data/public/search/legacy/fetch_soon.ts b/src/plugins/data/common/search/search_source/legacy/fetch_soon.ts similarity index 95% rename from src/plugins/data/public/search/legacy/fetch_soon.ts rename to src/plugins/data/common/search/search_source/legacy/fetch_soon.ts index 1c0573aa895d7..01ffc3876f6af 100644 --- a/src/plugins/data/public/search/legacy/fetch_soon.ts +++ b/src/plugins/data/common/search/search_source/legacy/fetch_soon.ts @@ -18,10 +18,10 @@ */ import { SearchResponse } from 'elasticsearch'; +import { UI_SETTINGS } from '../../../constants'; +import { FetchHandlers, SearchRequest } from '../fetch'; +import { ISearchOptions } from '../../index'; import { callClient } from './call_client'; -import { FetchHandlers } from '../fetch/types'; -import { SearchRequest } from '../index'; -import { UI_SETTINGS, ISearchOptions } from '../../../common'; /** * This function introduces a slight delay in the request process to allow multiple requests to queue diff --git a/src/plugins/data/common/search/search_source/legacy/index.ts b/src/plugins/data/common/search/search_source/legacy/index.ts new file mode 100644 index 0000000000000..26587b09ffd9e --- /dev/null +++ b/src/plugins/data/common/search/search_source/legacy/index.ts @@ -0,0 +1,21 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export { fetchSoon } from './fetch_soon'; +export * from './types'; diff --git a/src/plugins/data/common/search/search_source/legacy/types.ts b/src/plugins/data/common/search/search_source/legacy/types.ts new file mode 100644 index 0000000000000..8ac713a658932 --- /dev/null +++ b/src/plugins/data/common/search/search_source/legacy/types.ts @@ -0,0 +1,67 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { BehaviorSubject } from 'rxjs'; +import { ApiResponse } from '@elastic/elasticsearch'; +import { SearchResponse } from 'elasticsearch'; +import { FetchHandlers, SearchRequest } from '../fetch'; + +interface MsearchHeaders { + index: string; + preference?: number | string; +} + +interface MsearchRequest { + header: MsearchHeaders; + body: any; +} + +// @internal +export interface MsearchRequestBody { + searches: MsearchRequest[]; +} + +// @internal +export interface MsearchResponse { + body: ApiResponse<{ responses: Array> }>; +} + +// @internal +export interface LegacyFetchHandlers { + callMsearch: (params: { + body: MsearchRequestBody; + signal: AbortSignal; + }) => Promise; + loadingCount$: BehaviorSubject; +} + +export interface SearchStrategySearchParams extends FetchHandlers { + searchRequests: SearchRequest[]; +} + +// @deprecated +export interface SearchStrategyProvider { + id: string; + search: (params: SearchStrategySearchParams) => SearchStrategyResponse; +} + +export interface SearchStrategyResponse { + searching: Promise>>; + abort: () => void; +} diff --git a/src/plugins/data/public/search/search_source/migrate_legacy_query.ts b/src/plugins/data/common/search/search_source/migrate_legacy_query.ts similarity index 96% rename from src/plugins/data/public/search/search_source/migrate_legacy_query.ts rename to src/plugins/data/common/search/search_source/migrate_legacy_query.ts index 8d9b50d5a66b2..f271280170166 100644 --- a/src/plugins/data/public/search/search_source/migrate_legacy_query.ts +++ b/src/plugins/data/common/search/search_source/migrate_legacy_query.ts @@ -18,7 +18,7 @@ */ import { has } from 'lodash'; -import { Query } from 'src/plugins/data/public'; +import { Query } from '../../query/types'; /** * Creates a standardized query object from old queries that were either strings or pure ES query DSL diff --git a/src/plugins/data/common/search/search_source/mocks.ts b/src/plugins/data/common/search/search_source/mocks.ts new file mode 100644 index 0000000000000..d4c0707f950bb --- /dev/null +++ b/src/plugins/data/common/search/search_source/mocks.ts @@ -0,0 +1,62 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { BehaviorSubject } from 'rxjs'; +import { uiSettingsServiceMock } from '../../../../../core/public/mocks'; + +import { SearchSource } from './search_source'; +import { ISearchStartSearchSource, ISearchSource, SearchSourceFields } from './types'; + +export const searchSourceInstanceMock: MockedKeys = { + setPreferredSearchStrategyId: jest.fn(), + setFields: jest.fn().mockReturnThis(), + setField: jest.fn().mockReturnThis(), + getId: jest.fn(), + getFields: jest.fn(), + getField: jest.fn(), + getOwnField: jest.fn(), + create: jest.fn().mockReturnThis(), + createCopy: jest.fn().mockReturnThis(), + createChild: jest.fn().mockReturnThis(), + setParent: jest.fn(), + getParent: jest.fn().mockReturnThis(), + fetch: jest.fn().mockResolvedValue({}), + onRequestStart: jest.fn(), + getSearchRequestBody: jest.fn(), + destroy: jest.fn(), + history: [], + getSerializedFields: jest.fn(), + serialize: jest.fn(), +}; + +export const searchSourceCommonMock: jest.Mocked = { + create: jest.fn().mockReturnValue(searchSourceInstanceMock), + createEmpty: jest.fn().mockReturnValue(searchSourceInstanceMock), +}; + +export const createSearchSourceMock = (fields?: SearchSourceFields) => + new SearchSource(fields, { + getConfig: uiSettingsServiceMock.createStartContract().get, + search: jest.fn(), + onResponse: jest.fn().mockImplementation((req, res) => res), + legacy: { + callMsearch: jest.fn(), + loadingCount$: new BehaviorSubject(0), + }, + }); diff --git a/src/plugins/data/public/search/search_source/normalize_sort_request.test.ts b/src/plugins/data/common/search/search_source/normalize_sort_request.test.ts similarity index 98% rename from src/plugins/data/public/search/search_source/normalize_sort_request.test.ts rename to src/plugins/data/common/search/search_source/normalize_sort_request.test.ts index 10004b87ca690..1899efbf3598d 100644 --- a/src/plugins/data/public/search/search_source/normalize_sort_request.test.ts +++ b/src/plugins/data/common/search/search_source/normalize_sort_request.test.ts @@ -19,7 +19,7 @@ import { normalizeSortRequest } from './normalize_sort_request'; import { SortDirection } from './types'; -import { IIndexPattern } from '../..'; +import { IIndexPattern } from '../../index_patterns'; describe('SearchSource#normalizeSortRequest', function () { const scriptedField = { diff --git a/src/plugins/data/public/search/search_source/normalize_sort_request.ts b/src/plugins/data/common/search/search_source/normalize_sort_request.ts similarity index 98% rename from src/plugins/data/public/search/search_source/normalize_sort_request.ts rename to src/plugins/data/common/search/search_source/normalize_sort_request.ts index 3ec0a13282d3e..e41c4482df9c9 100644 --- a/src/plugins/data/public/search/search_source/normalize_sort_request.ts +++ b/src/plugins/data/common/search/search_source/normalize_sort_request.ts @@ -17,7 +17,7 @@ * under the License. */ -import { IIndexPattern } from '../..'; +import { IIndexPattern } from '../../index_patterns'; import { EsQuerySortValue, SortOptions } from './types'; export function normalizeSortRequest( diff --git a/src/plugins/data/public/search/search_source/parse_json.ts b/src/plugins/data/common/search/search_source/parse_json.ts similarity index 100% rename from src/plugins/data/public/search/search_source/parse_json.ts rename to src/plugins/data/common/search/search_source/parse_json.ts diff --git a/src/plugins/data/public/search/search_source/search_source.test.ts b/src/plugins/data/common/search/search_source/search_source.test.ts similarity index 94% rename from src/plugins/data/public/search/search_source/search_source.test.ts rename to src/plugins/data/common/search/search_source/search_source.test.ts index d9a9fb2f4fef3..00e06663e998e 100644 --- a/src/plugins/data/public/search/search_source/search_source.test.ts +++ b/src/plugins/data/common/search/search_source/search_source.test.ts @@ -17,13 +17,13 @@ * under the License. */ -import { Observable, BehaviorSubject } from 'rxjs'; -import { GetConfigFn } from 'src/plugins/data/common'; -import { SearchSource, SearchSourceDependencies } from './search_source'; -import { IndexPattern, SortDirection } from '../..'; -import { fetchSoon } from '../legacy'; +import { BehaviorSubject } from 'rxjs'; +import { IndexPattern } from '../../index_patterns'; +import { GetConfigFn } from '../../types'; +import { fetchSoon } from './legacy'; +import { SearchSource, SearchSourceDependencies, SortDirection } from './'; -jest.mock('../legacy', () => ({ +jest.mock('./legacy', () => ({ fetchSoon: jest.fn().mockResolvedValue({}), })); @@ -53,16 +53,7 @@ describe('SearchSource', () => { let searchSourceDependencies: SearchSourceDependencies; beforeEach(() => { - mockSearchMethod = jest.fn(() => { - return new Observable((subscriber) => { - setTimeout(() => { - subscriber.next({ - rawResponse: '', - }); - subscriber.complete(); - }, 100); - }); - }); + mockSearchMethod = jest.fn().mockResolvedValue({ rawResponse: '' }); searchSourceDependencies = { getConfig: jest.fn(), diff --git a/src/plugins/data/public/search/search_source/search_source.ts b/src/plugins/data/common/search/search_source/search_source.ts similarity index 93% rename from src/plugins/data/public/search/search_source/search_source.ts rename to src/plugins/data/common/search/search_source/search_source.ts index 4afee223454e4..1a6b770cf2ca8 100644 --- a/src/plugins/data/public/search/search_source/search_source.ts +++ b/src/plugins/data/common/search/search_source/search_source.ts @@ -71,23 +71,18 @@ import { setWith } from '@elastic/safer-lodash-set'; import { uniqueId, uniq, extend, pick, difference, omit, isObject, keys, isFunction } from 'lodash'; -import { map } from 'rxjs/operators'; import { normalizeSortRequest } from './normalize_sort_request'; import { filterDocvalueFields } from './filter_docvalue_fields'; import { fieldWildcardFilter } from '../../../../kibana_utils/common'; -import { IIndexPattern, ISearchGeneric } from '../..'; -import { SearchSourceOptions, SearchSourceFields } from './types'; -import { FetchHandlers, RequestFailure, getSearchParamsFromRequest, SearchRequest } from '../fetch'; - -import { - getEsQueryConfig, - buildEsQuery, - Filter, - UI_SETTINGS, - ISearchOptions, -} from '../../../common'; +import { IIndexPattern } from '../../index_patterns'; +import { IEsSearchRequest, IEsSearchResponse, ISearchOptions } from '../..'; +import { IKibanaSearchRequest, IKibanaSearchResponse } from '../types'; +import { ISearchSource, SearchSourceOptions, SearchSourceFields } from './types'; +import { FetchHandlers, RequestFailure, getSearchParamsFromRequest, SearchRequest } from './fetch'; + +import { getEsQueryConfig, buildEsQuery, Filter, UI_SETTINGS } from '../../../common'; import { getHighlightRequest } from '../../../common/field_formats'; -import { fetchSoon } from '../legacy'; +import { fetchSoon } from './legacy'; import { extractReferences } from './extract_references'; /** @internal */ @@ -107,7 +102,15 @@ export const searchSourceRequiredUiSettings = [ ]; export interface SearchSourceDependencies extends FetchHandlers { - search: ISearchGeneric; + // Types are nearly identical to ISearchGeneric, except we are making + // search options required here and returning a promise instead of observable. + search: < + SearchStrategyRequest extends IKibanaSearchRequest = IEsSearchRequest, + SearchStrategyResponse extends IKibanaSearchResponse = IEsSearchResponse + >( + request: SearchStrategyRequest, + options: ISearchOptions + ) => Promise; } /** @public **/ @@ -263,7 +266,7 @@ export class SearchSource { if (getConfig(UI_SETTINGS.COURIER_BATCH_SEARCHES)) { response = await this.legacyFetch(searchRequest, options); } else { - response = await this.fetch$(searchRequest, options).toPromise(); + response = await this.fetchSearch(searchRequest, options); } // TODO: Remove casting when https://github.com/elastic/elasticsearch-js/issues/1287 is resolved @@ -307,17 +310,17 @@ export class SearchSource { /** * Run a search using the search service - * @return {Observable>} + * @return {Promise>} */ - private fetch$(searchRequest: SearchRequest, options: ISearchOptions) { + private fetchSearch(searchRequest: SearchRequest, options: ISearchOptions) { const { search, getConfig, onResponse } = this.dependencies; const params = getSearchParamsFromRequest(searchRequest, { getConfig, }); - return search({ params, indexType: searchRequest.indexType }, options).pipe( - map(({ rawResponse }) => onResponse(searchRequest, rawResponse)) + return search({ params, indexType: searchRequest.indexType }, options).then(({ rawResponse }) => + onResponse(searchRequest, rawResponse) ); } @@ -557,9 +560,3 @@ export class SearchSource { return [filterField]; } } - -/** - * search source interface - * @public - */ -export type ISearchSource = Pick; diff --git a/src/plugins/data/common/search/search_source/search_source_service.test.ts b/src/plugins/data/common/search/search_source/search_source_service.test.ts new file mode 100644 index 0000000000000..bbbaac11bbe91 --- /dev/null +++ b/src/plugins/data/common/search/search_source/search_source_service.test.ts @@ -0,0 +1,50 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { BehaviorSubject } from 'rxjs'; +import { IndexPatternsContract } from '../../index_patterns/index_patterns'; +import { SearchSourceService, SearchSourceDependencies } from './'; + +describe('SearchSource service', () => { + let dependencies: jest.Mocked; + + beforeEach(() => { + jest.resetModules(); + dependencies = { + getConfig: jest.fn(), + search: jest.fn(), + onResponse: jest.fn(), + legacy: { + callMsearch: jest.fn(), + loadingCount$: new BehaviorSubject(0), + }, + }; + }); + + describe('start()', () => { + test('exposes proper contract', () => { + const start = new SearchSourceService().start( + (jest.fn() as unknown) as jest.Mocked, + dependencies + ); + + expect(Object.keys(start)).toEqual(['create', 'createEmpty']); + }); + }); +}); diff --git a/src/plugins/data/common/search/search_source/search_source_service.ts b/src/plugins/data/common/search/search_source/search_source_service.ts new file mode 100644 index 0000000000000..40981402419c7 --- /dev/null +++ b/src/plugins/data/common/search/search_source/search_source_service.ts @@ -0,0 +1,42 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { createSearchSource, SearchSource, SearchSourceDependencies } from './'; +import { IndexPatternsContract } from '../../index_patterns/index_patterns'; + +export class SearchSourceService { + public setup() {} + + public start(indexPatterns: IndexPatternsContract, dependencies: SearchSourceDependencies) { + return { + /** + * creates searchsource based on serialized search source fields + */ + create: createSearchSource(indexPatterns, dependencies), + /** + * creates an enpty search source + */ + createEmpty: () => { + return new SearchSource({}, dependencies); + }, + }; + } + + public stop() {} +} diff --git a/src/plugins/data/common/search/search_source/types.ts b/src/plugins/data/common/search/search_source/types.ts new file mode 100644 index 0000000000000..bbfc308e0459d --- /dev/null +++ b/src/plugins/data/common/search/search_source/types.ts @@ -0,0 +1,146 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { NameList } from 'elasticsearch'; +import { Filter, IndexPattern, Query } from '../..'; +import { SearchSource } from './search_source'; + +/** + * search source interface + * @public + */ +export type ISearchSource = Pick; + +/** + * high level search service + * @public + */ +export interface ISearchStartSearchSource { + /** + * creates {@link SearchSource} based on provided serialized {@link SearchSourceFields} + * @param fields + */ + create: (fields?: SearchSourceFields) => Promise; + /** + * creates empty {@link SearchSource} + */ + createEmpty: () => ISearchSource; +} + +export type EsQuerySearchAfter = [string | number, string | number]; + +export enum SortDirection { + asc = 'asc', + desc = 'desc', +} + +export interface SortDirectionNumeric { + order: SortDirection; + numeric_type?: 'double' | 'long' | 'date' | 'date_nanos'; +} + +export type EsQuerySortValue = Record; + +/** + * search source fields + */ +export interface SearchSourceFields { + type?: string; + /** + * {@link Query} + */ + query?: Query; + /** + * {@link Filter} + */ + filter?: Filter[] | Filter | (() => Filter[] | Filter | undefined); + /** + * {@link EsQuerySortValue} + */ + sort?: EsQuerySortValue | EsQuerySortValue[]; + highlight?: any; + highlightAll?: boolean; + /** + * {@link AggConfigs} + */ + aggs?: any; + from?: number; + size?: number; + source?: NameList; + version?: boolean; + fields?: NameList; + /** + * {@link IndexPatternService} + */ + index?: IndexPattern; + searchAfter?: EsQuerySearchAfter; + timeout?: string; + terminate_after?: number; +} + +export interface SearchSourceOptions { + callParentStartHandlers?: boolean; +} + +export interface SortOptions { + mode?: 'min' | 'max' | 'sum' | 'avg' | 'median'; + type?: 'double' | 'long' | 'date' | 'date_nanos'; + nested?: object; + unmapped_type?: string; + distance_type?: 'arc' | 'plane'; + unit?: string; + ignore_unmapped?: boolean; + _script?: object; +} + +export interface Request { + docvalue_fields: string[]; + _source: unknown; + query: unknown; + script_fields: unknown; + sort: unknown; + stored_fields: string[]; +} + +export interface ResponseWithShardFailure { + _shards: { + failed: number; + failures: ShardFailure[]; + skipped: number; + successful: number; + total: number; + }; +} + +export interface ShardFailure { + index: string; + node: string; + reason: { + caused_by: { + reason: string; + type: string; + }; + reason: string; + lang?: string; + script?: string; + script_stack?: string[]; + type: string; + }; + shard: number; +} diff --git a/src/plugins/data/common/search/types.ts b/src/plugins/data/common/search/types.ts index 7600bd9db6094..c3943af5c6ff7 100644 --- a/src/plugins/data/common/search/types.ts +++ b/src/plugins/data/common/search/types.ts @@ -17,7 +17,23 @@ * under the License. */ -export interface IKibanaSearchResponse { +import { Observable } from 'rxjs'; +import { IEsSearchRequest, IEsSearchResponse, ISearchOptions } from '../../common/search'; + +export type ISearch = ( + request: IKibanaSearchRequest, + options?: ISearchOptions +) => Observable; + +export type ISearchGeneric = < + SearchStrategyRequest extends IKibanaSearchRequest = IEsSearchRequest, + SearchStrategyResponse extends IKibanaSearchResponse = IEsSearchResponse +>( + request: SearchStrategyRequest, + options?: ISearchOptions +) => Observable; + +export interface IKibanaSearchResponse { /** * Some responses may contain a unique id to identify the request this response came from. */ @@ -34,16 +50,25 @@ export interface IKibanaSearchResponse { * that represents how progress is indicated. */ loaded?: number; + + /** + * Indicates whether search is still in flight + */ + isRunning?: boolean; + + /** + * Indicates whether the results returned are complete or partial + */ + isPartial?: boolean; + + rawResponse: RawResponse; } -export interface IKibanaSearchRequest { +export interface IKibanaSearchRequest { /** * An id can be used to uniquely identify this request. */ id?: string; - /** - * Optionally tell search strategies to output debug information. - */ - debug?: boolean; + params?: Params; } diff --git a/src/plugins/data/config.ts b/src/plugins/data/config.ts index 09cb2cb2afeca..83a384a049a75 100644 --- a/src/plugins/data/config.ts +++ b/src/plugins/data/config.ts @@ -28,6 +28,16 @@ export const configSchema = schema.object({ enabled: schema.boolean({ defaultValue: true }), }), }), + search: schema.object({ + aggs: schema.object({ + shardDelay: schema.object({ + // Whether or not to register the shard_delay (which is only available in snapshot versions + // of Elasticsearch) agg type/expression function to make it available in the UI for either + // functional or manual testing + enabled: schema.boolean({ defaultValue: false }), + }), + }), + }), }); export type ConfigSchema = TypeOf; diff --git a/src/plugins/data/public/index.ts b/src/plugins/data/public/index.ts index 5038af9409316..9d417684b1651 100644 --- a/src/plugins/data/public/index.ts +++ b/src/plugins/data/public/index.ts @@ -50,7 +50,7 @@ import { COMPARE_ALL_OPTIONS, } from '../common'; -import { FilterLabel } from './ui/filter_bar'; +import { FilterLabel } from './ui'; import { generateFilters, @@ -230,6 +230,8 @@ import { formatHitProvider, } from './index_patterns'; +export type { IndexPatternsService } from './index_patterns'; + // Index patterns namespace: export const indexPatterns = { ILLEGAL_CHARACTERS_KEY, @@ -262,9 +264,12 @@ export { UI_SETTINGS, TypeMeta as IndexPatternTypeMeta, AggregationRestrictions as IndexPatternAggRestrictions, + IndexPatternSpec, fieldList, } from '../common'; +export { DuplicateIndexPatternError } from '../common/index_patterns/errors'; + /* * Autocomplete query suggestions: */ @@ -360,8 +365,6 @@ export { ISearchGeneric, ISearchSource, parseSearchSourceJSON, - RequestTimeoutError, - SearchError, SearchInterceptor, SearchInterceptorDeps, SearchRequest, @@ -370,11 +373,16 @@ export { // expression functions and types EsdslExpressionFunctionDefinition, EsRawResponseExpressionTypeDefinition, + // errors + SearchError, + SearchTimeoutError, + TimeoutErrorMode, + PainlessError, } from './search'; export type { SearchSource } from './search'; -export { ISearchOptions } from '../common'; +export { ISearchOptions, isErrorResponse, isCompleteResponse, isPartialResponse } from '../common'; // Search namespace export const search = { @@ -413,9 +421,9 @@ export { SearchBar, SearchBarProps, StatefulSearchBarProps, - FilterBar, + IndexPatternSelectProps, QueryStringInput, - IndexPatternSelect, + QueryStringInputProps, } from './ui'; /** diff --git a/src/plugins/data/public/index_patterns/index_pattern.stub.ts b/src/plugins/data/public/index_patterns/index_pattern.stub.ts new file mode 100644 index 0000000000000..e5c6c008e3e28 --- /dev/null +++ b/src/plugins/data/public/index_patterns/index_pattern.stub.ts @@ -0,0 +1,132 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import sinon from 'sinon'; + +import { CoreSetup } from 'src/core/public'; +import { FieldFormat as FieldFormatImpl } from '../../common/field_formats'; +import { IFieldType, FieldSpec } from '../../common/index_patterns'; +import { FieldFormatsStart } from '../field_formats'; +import { IndexPattern, indexPatterns, KBN_FIELD_TYPES, fieldList } from '../'; +import { getFieldFormatsRegistry } from '../test_utils'; +import { setFieldFormats } from '../services'; + +setFieldFormats(({ + getDefaultInstance: () => + ({ + getConverterFor: () => (value: any) => value, + convert: (value: any) => JSON.stringify(value), + } as FieldFormatImpl), +} as unknown) as FieldFormatsStart); + +export function getStubIndexPattern( + pattern: string, + getConfig: (cfg: any) => any, + timeField: string | null, + fields: FieldSpec[] | IFieldType[], + core: CoreSetup +): IndexPattern { + return (new StubIndexPattern( + pattern, + getConfig, + timeField, + fields, + core + ) as unknown) as IndexPattern; +} + +export class StubIndexPattern { + id: string; + title: string; + popularizeField: Function; + timeFieldName: string | null; + isTimeBased: () => boolean; + getConfig: (cfg: any) => any; + getNonScriptedFields: Function; + getScriptedFields: Function; + getFieldByName: Function; + getSourceFiltering: Function; + metaFields: string[]; + fieldFormatMap: Record; + getComputedFields: Function; + flattenHit: Function; + formatHit: Record; + fieldsFetcher: Record; + formatField: Function; + getFormatterForField: () => { convert: Function }; + _reindexFields: Function; + stubSetFieldFormat: Function; + fields?: FieldSpec[]; + + constructor( + pattern: string, + getConfig: (cfg: any) => any, + timeField: string | null, + fields: FieldSpec[] | IFieldType[], + core: CoreSetup + ) { + const registeredFieldFormats = getFieldFormatsRegistry(core); + + this.id = pattern; + this.title = pattern; + this.popularizeField = sinon.stub(); + this.timeFieldName = timeField; + this.isTimeBased = () => Boolean(this.timeFieldName); + this.getConfig = getConfig; + this.getNonScriptedFields = sinon.spy(IndexPattern.prototype.getNonScriptedFields); + this.getScriptedFields = sinon.spy(IndexPattern.prototype.getScriptedFields); + this.getFieldByName = sinon.spy(IndexPattern.prototype.getFieldByName); + this.getSourceFiltering = sinon.stub(); + this.metaFields = ['_id', '_type', '_source']; + this.fieldFormatMap = {}; + + this.getComputedFields = IndexPattern.prototype.getComputedFields.bind(this); + this.flattenHit = indexPatterns.flattenHitWrapper( + (this as unknown) as IndexPattern, + this.metaFields + ); + this.formatHit = indexPatterns.formatHitProvider( + (this as unknown) as IndexPattern, + registeredFieldFormats.getDefaultInstance(KBN_FIELD_TYPES.STRING) + ); + this.fieldsFetcher = { apiClient: { baseUrl: '' } }; + this.formatField = this.formatHit.formatField; + this.getFormatterForField = () => ({ + convert: () => '', + }); + + this._reindexFields = function () { + this.fields = fieldList((this.fields || fields) as FieldSpec[], false); + }; + + this.stubSetFieldFormat = function ( + fieldName: string, + id: string, + params: Record + ) { + const FieldFormat = registeredFieldFormats.getType(id); + this.fieldFormatMap[fieldName] = new FieldFormat!(params); + this._reindexFields(); + }; + + this._reindexFields(); + + return this; + } +} diff --git a/src/plugins/data/public/mocks.ts b/src/plugins/data/public/mocks.ts index 0eb0e3b658045..1b83eb569b1a1 100644 --- a/src/plugins/data/public/mocks.ts +++ b/src/plugins/data/public/mocks.ts @@ -78,7 +78,7 @@ const createStartContract = (): Start => { }; }; -export { createSearchSourceMock } from './search/mocks'; +export { createSearchSourceMock } from '../common/search/search_source/mocks'; export { getCalculateAutoTimeExpression } from '../common/search/aggs'; export const dataPluginMock = { diff --git a/src/plugins/data/public/plugin.ts b/src/plugins/data/public/plugin.ts index 3b18e0fbed537..5abf4d3648af7 100644 --- a/src/plugins/data/public/plugin.ts +++ b/src/plugins/data/public/plugin.ts @@ -96,7 +96,7 @@ export class DataPublicPlugin private readonly storage: IStorageWrapper; constructor(initializerContext: PluginInitializerContext) { - this.searchService = new SearchService(); + this.searchService = new SearchService(initializerContext); this.queryService = new QueryService(); this.fieldFormatsService = new FieldFormatsService(); this.autocomplete = new AutocompleteService(initializerContext); diff --git a/src/plugins/data/public/public.api.md b/src/plugins/data/public/public.api.md index 26e72a82d4bb5..0477fb68b3c1e 100644 --- a/src/plugins/data/public/public.api.md +++ b/src/plugins/data/public/public.api.md @@ -5,13 +5,13 @@ ```ts import { $Values } from '@kbn/utility-types'; -import _ from 'lodash'; import { Action } from 'history'; -import { ApiResponse } from '@elastic/elasticsearch/lib/Transport'; +import { ApiResponse } from '@elastic/elasticsearch'; +import { ApiResponse as ApiResponse_2 } from '@elastic/elasticsearch/lib/Transport'; +import { ApplicationStart } from 'kibana/public'; import { Assign } from '@kbn/utility-types'; import { BehaviorSubject } from 'rxjs'; import Boom from 'boom'; -import { Component } from 'react'; import { CoreSetup } from 'src/core/public'; import { CoreSetup as CoreSetup_2 } from 'kibana/public'; import { CoreStart } from 'kibana/public'; @@ -63,12 +63,12 @@ import { RequestStatistics } from 'src/plugins/inspector/common'; import { Required } from '@kbn/utility-types'; import * as Rx from 'rxjs'; import { SavedObject } from 'src/core/server'; -import { SavedObject as SavedObject_3 } from 'src/core/public'; +import { SavedObject as SavedObject_2 } from 'src/core/public'; +import { SavedObjectReference as SavedObjectReference_2 } from 'src/core/types'; import { SavedObjectsClientContract } from 'src/core/public'; import { Search } from '@elastic/elasticsearch/api/requestParams'; import { SearchResponse } from 'elasticsearch'; import { SerializedFieldFormat as SerializedFieldFormat_2 } from 'src/plugins/expressions/common'; -import { Subscription } from 'rxjs'; import { ToastInputFields } from 'src/core/public/notifications'; import { ToastsSetup } from 'kibana/public'; import { TransportRequestOptions } from '@elastic/elasticsearch/lib/Transport'; @@ -445,14 +445,19 @@ export interface DataPublicPluginStartActions { // // @public export interface DataPublicPluginStartUi { - // Warning: (ae-forgotten-export) The symbol "IndexPatternSelectProps" needs to be exported by the entry point index.d.ts - // // (undocumented) IndexPatternSelect: React.ComponentType; // (undocumented) SearchBar: React.ComponentType; } +// Warning: (ae-missing-release-tag) "DuplicateIndexPatternError" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export class DuplicateIndexPatternError extends Error { + constructor(message: string); +} + // @public (undocumented) export enum ES_FIELD_TYPES { // (undocumented) @@ -538,7 +543,7 @@ export type EsdslExpressionFunctionDefinition = ExpressionFunctionDefinition JSX.Element; FILTERS: typeof FILTERS; FilterStateStore: typeof FilterStateStore; buildEmptyFilter: (isPinned: boolean, index?: string | undefined) => import("../common").Filter; @@ -651,13 +656,12 @@ export type ExistsFilter = Filter & { // @public (undocumented) export const expandShorthand: (sh: Record) => MappingObject; -// Warning: (ae-forgotten-export) The symbol "SavedObjectReference" needs to be exported by the entry point index.d.ts // Warning: (ae-missing-release-tag) "extractReferences" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) export const extractSearchSourceReferences: (state: SearchSourceFields) => [SearchSourceFields & { indexRefName?: string; -}, SavedObjectReference[]]; +}, SavedObjectReference_2[]]; // Warning: (ae-missing-release-tag) "FieldFormat" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // @@ -797,14 +801,6 @@ export type Filter = { query?: any; }; -// Warning: (ae-forgotten-export) The symbol "Props" needs to be exported by the entry point index.d.ts -// Warning: (ae-missing-release-tag) "FilterBar" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) -export const FilterBar: React.ComponentClass, any> & { - WrappedComponent: React.ComponentType; -}; - // Warning: (ae-missing-release-tag) "FilterManager" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) @@ -911,22 +907,15 @@ export interface IDataPluginServices extends Partial { // Warning: (ae-missing-release-tag) "IEsSearchRequest" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) -export interface IEsSearchRequest extends IKibanaSearchRequest { +export interface IEsSearchRequest extends IKibanaSearchRequest { // (undocumented) indexType?: string; - // (undocumented) - params?: ISearchRequestParams; } // Warning: (ae-missing-release-tag) "IEsSearchResponse" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) -export interface IEsSearchResponse extends IKibanaSearchResponse { - isPartial?: boolean; - isRunning?: boolean; - // (undocumented) - rawResponse: SearchResponse; -} +export type IEsSearchResponse = IKibanaSearchResponse>; // Warning: (ae-missing-release-tag) "IFieldFormat" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // @@ -1004,16 +993,15 @@ export interface IFieldType { // // @public (undocumented) export interface IIndexPattern { + // Warning: (ae-forgotten-export) The symbol "SerializedFieldFormat" needs to be exported by the entry point index.d.ts + // // (undocumented) - [key: string]: any; - // (undocumented) - fieldFormatMap?: Record; + fieldFormatMap?: Record | undefined>; // (undocumented) fields: IFieldType[]; // (undocumented) + getFormatterForField?: (field: IndexPatternField | IndexPatternField['spec'] | IFieldType) => FieldFormat; + // (undocumented) getTimeField?(): IFieldType | undefined; // (undocumented) id?: string; @@ -1043,10 +1031,12 @@ export interface IIndexPatternFieldList extends Array { removeAll(): void; // (undocumented) replaceAll(specs: FieldSpec[]): void; + // Warning: (ae-forgotten-export) The symbol "IndexPatternFieldMap" needs to be exported by the entry point index.d.ts + // // (undocumented) toSpec(options?: { getFormatterForField?: IndexPattern['getFormatterForField']; - }): FieldSpec[]; + }): IndexPatternFieldMap; // (undocumented) update(field: FieldSpec): void; } @@ -1054,17 +1044,22 @@ export interface IIndexPatternFieldList extends Array { // Warning: (ae-missing-release-tag) "IKibanaSearchRequest" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) -export interface IKibanaSearchRequest { - debug?: boolean; +export interface IKibanaSearchRequest { id?: string; + // (undocumented) + params?: Params; } // Warning: (ae-missing-release-tag) "IKibanaSearchResponse" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) -export interface IKibanaSearchResponse { +export interface IKibanaSearchResponse { id?: string; + isPartial?: boolean; + isRunning?: boolean; loaded?: number; + // (undocumented) + rawResponse: RawResponse; total?: number; } @@ -1079,27 +1074,23 @@ export type IMetricAggType = MetricAggType; // @public (undocumented) export class IndexPattern implements IIndexPattern { // Warning: (ae-forgotten-export) The symbol "IndexPatternDeps" needs to be exported by the entry point index.d.ts - constructor(id: string | undefined, { savedObjectsClient, apiClient, patternCache, fieldFormats, indexPatternsService, onNotification, onError, shortDotsEnable, metaFields, }: IndexPatternDeps); - // (undocumented) - addScriptedField(name: string, script: string, fieldType: string | undefined, lang: string): Promise; + constructor({ spec, fieldFormats, shortDotsEnable, metaFields, }: IndexPatternDeps); + addScriptedField(name: string, script: string, fieldType?: string): Promise; // (undocumented) - create(allowOverride?: boolean): Promise; - // (undocumented) - _fetchFields(): Promise; - // (undocumented) - fieldFormatMap: any; + fieldFormatMap: Record; // (undocumented) fields: IIndexPatternFieldList & { - toSpec: () => FieldSpec[]; + toSpec: () => IndexPatternFieldMap; }; // (undocumented) - fieldsFetcher: any; - // (undocumented) - flattenHit: any; + flattenHit: (hit: Record, deep?: boolean) => Record; // (undocumented) - formatField: any; + formatField: FormatFieldFn; // (undocumented) - formatHit: any; + formatHit: { + (hit: Record, type?: string): any; + formatField: FormatFieldFn; + }; // (undocumented) getAggregationRestrictions(): Record> | undefined; + getAsSavedObjectBody(): { + title: string; + timeFieldName: string | undefined; + intervalName: string | undefined; + sourceFilters: string | undefined; + fields: string | undefined; + fieldFormatMap: string | undefined; + type: string | undefined; + typeMeta: string | undefined; + }; // (undocumented) getComputedFields(): { storedFields: string[]; @@ -1120,13 +1121,21 @@ export class IndexPattern implements IIndexPattern { }; // (undocumented) getFieldByName(name: string): IndexPatternField | undefined; - // (undocumented) - getFormatterForField(field: IndexPatternField | IndexPatternField['spec']): FieldFormat; + getFormatterForField(field: IndexPatternField | IndexPatternField['spec'] | IFieldType): FieldFormat; // (undocumented) getNonScriptedFields(): IndexPatternField[]; + getOriginalSavedObjectBody: () => { + title?: string | undefined; + timeFieldName?: string | undefined; + intervalName?: string | undefined; + fields?: string | undefined; + sourceFilters?: string | undefined; + fieldFormatMap?: string | undefined; + typeMeta?: string | undefined; + type?: string | undefined; + }; // (undocumented) getScriptedFields(): IndexPatternField[]; - // (undocumented) getSourceFiltering(): { excludes: any[]; }; @@ -1135,44 +1144,15 @@ export class IndexPattern implements IIndexPattern { // (undocumented) id?: string; // (undocumented) - init(): Promise; - // Warning: (ae-forgotten-export) The symbol "IndexPatternSpec" needs to be exported by the entry point index.d.ts - // - // (undocumented) - initFromSpec(spec: IndexPatternSpec): this; - // (undocumented) intervalName: string | undefined; // (undocumented) isTimeBased(): boolean; // (undocumented) - isTimeBasedWildcard(): boolean; - // (undocumented) isTimeNanosBased(): boolean; // (undocumented) - isWildcard(): boolean; - // (undocumented) metaFields: string[]; - // (undocumented) - originalBody: { - [key: string]: any; - }; - // (undocumented) - popularizeField(fieldName: string, unit?: number): Promise; - // (undocumented) - prepBody(): { - title: string; - timeFieldName: string | undefined; - intervalName: string | undefined; - sourceFilters: string | undefined; - fields: string | undefined; - fieldFormatMap: string | undefined; - type: string | undefined; - typeMeta: string | undefined; - }; - // (undocumented) - refreshFields(): Promise; - // (undocumented) removeScriptedField(fieldName: string): void; + resetOriginalSavedObjectBody: () => void; // Warning: (ae-forgotten-export) The symbol "SourceFilter" needs to be exported by the entry point index.d.ts // // (undocumented) @@ -1205,7 +1185,7 @@ export type IndexPatternAggRestrictions = Record | undefined; set conflictDescriptions(conflictDescriptions: Record | undefined); - // (undocumented) get count(): number; set count(count: number); // (undocumented) @@ -1244,14 +1222,12 @@ export class IndexPatternField implements IFieldType { get esTypes(): string[] | undefined; // (undocumented) get filterable(): boolean; - // (undocumented) get lang(): string | undefined; set lang(lang: string | undefined); // (undocumented) get name(): string; // (undocumented) get readFromDocValues(): boolean; - // (undocumented) get script(): string | undefined; set script(script: string | undefined); // (undocumented) @@ -1282,24 +1258,7 @@ export class IndexPatternField implements IFieldType { // (undocumented) toSpec({ getFormatterForField, }?: { getFormatterForField?: IndexPattern['getFormatterForField']; - }): { - count: number; - script: string | undefined; - lang: string | undefined; - conflictDescriptions: Record | undefined; - name: string; - type: string; - esTypes: string[] | undefined; - scripted: boolean; - searchable: boolean; - aggregatable: boolean; - readFromDocValues: boolean; - subType: import("../types").IFieldSubType | undefined; - format: { - id: any; - params: any; - } | undefined; - }; + }): FieldSpec; // (undocumented) get type(): string; // (undocumented) @@ -1323,37 +1282,80 @@ export const indexPatterns: { formatHitProvider: typeof formatHitProvider; }; -// Warning: (ae-forgotten-export) The symbol "IndexPatternsService" needs to be exported by the entry point index.d.ts // Warning: (ae-missing-release-tag) "IndexPatternsContract" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) export type IndexPatternsContract = PublicMethodsOf; -// Warning: (ae-missing-release-tag) "IndexPatternSelect" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// Warning: (ae-missing-release-tag) "IndexPatternSelectProps" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type IndexPatternSelectProps = Required, 'isLoading' | 'onSearchChange' | 'options' | 'selectedOptions' | 'onChange'>, 'placeholder'> & { + onChange: (indexPatternId?: string) => void; + indexPatternId: string; + fieldTypes?: string[]; + onNoIndexPatterns?: () => void; +}; + +// Warning: (ae-missing-release-tag) "IndexPatternSpec" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) -export class IndexPatternSelect extends Component { - constructor(props: IndexPatternSelectProps); +export interface IndexPatternSpec { // (undocumented) - componentDidMount(): void; + fields?: IndexPatternFieldMap; // (undocumented) - componentWillUnmount(): void; + id?: string; // (undocumented) - debouncedFetch: ((searchValue: string) => Promise) & _.Cancelable; + intervalName?: string; // (undocumented) - fetchOptions: (searchValue?: string) => void; + sourceFilters?: SourceFilter[]; // (undocumented) - fetchSelectedIndexPattern: (indexPatternId: string) => Promise; + timeFieldName?: string; // (undocumented) - onChange: (selectedOptions: any) => void; + title?: string; // (undocumented) - render(): JSX.Element; - // Warning: (ae-forgotten-export) The symbol "IndexPatternSelectState" needs to be exported by the entry point index.d.ts + type?: string; + // (undocumented) + typeMeta?: IndexPatternTypeMeta; + // (undocumented) + version?: string; +} + +// Warning: (ae-missing-release-tag) "IndexPatternsService" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export class IndexPatternsService { + // Warning: (ae-forgotten-export) The symbol "IndexPatternsServiceDeps" needs to be exported by the entry point index.d.ts + constructor({ uiSettings, savedObjectsClient, apiClient, fieldFormats, onNotification, onError, onRedirectNoIndexPattern, }: IndexPatternsServiceDeps); + clearCache: (id?: string | undefined) => void; + create(spec: IndexPatternSpec, skipFetchFields?: boolean): Promise; + createAndSave(spec: IndexPatternSpec, override?: boolean, skipFetchFields?: boolean): Promise; + createSavedObject(indexPattern: IndexPattern, override?: boolean): Promise; + delete(indexPatternId: string): Promise<{}>; + // Warning: (ae-forgotten-export) The symbol "EnsureDefaultIndexPattern" needs to be exported by the entry point index.d.ts // // (undocumented) - state: IndexPatternSelectState; + ensureDefaultIndexPattern: EnsureDefaultIndexPattern; + fieldArrayToMap: (fields: FieldSpec[]) => Record; + get: (id: string) => Promise; + // Warning: (ae-forgotten-export) The symbol "IndexPatternSavedObjectAttrs" needs to be exported by the entry point index.d.ts + // // (undocumented) - UNSAFE_componentWillReceiveProps(nextProps: IndexPatternSelectProps): void; + getCache: () => Promise[] | null | undefined>; + getDefault: () => Promise; + getFieldsForIndexPattern: (indexPattern: IndexPattern | IndexPatternSpec, options?: GetFieldsOptions) => Promise; + // Warning: (ae-forgotten-export) The symbol "GetFieldsOptions" needs to be exported by the entry point index.d.ts + getFieldsForWildcard: (options?: GetFieldsOptions) => Promise; + getIds: (refresh?: boolean) => Promise; + getIdsWithTitle: (refresh?: boolean) => Promise>; + getTitles: (refresh?: boolean) => Promise; + refreshFields: (indexPattern: IndexPattern) => Promise; + savedObjectToSpec: (savedObject: SavedObject) => IndexPatternSpec; + setDefault: (id: string, force?: boolean) => Promise; + updateSavedObject(indexPattern: IndexPattern, saveAttempts?: number, ignoreErrors?: boolean): Promise; } // Warning: (ae-missing-release-tag) "TypeMeta" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) @@ -1371,7 +1373,7 @@ export interface IndexPatternTypeMeta { // @public (undocumented) export const injectSearchSourceReferences: (searchSourceFields: SearchSourceFields & { indexRefName: string; -}, references: SavedObjectReference[]) => SearchSourceFields; +}, references: SavedObjectReference_2[]) => SearchSourceFields; // Warning: (ae-missing-release-tag) "InputTimeRange" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // @@ -1381,6 +1383,11 @@ export type InputTimeRange = TimeRange | { to: Moment; }; +// Warning: (ae-missing-release-tag) "isCompleteResponse" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export const isCompleteResponse: (response?: IKibanaSearchResponse | undefined) => boolean | undefined; + // Warning: (ae-missing-release-tag) "ISearch" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) @@ -1389,7 +1396,7 @@ export type ISearch = (request: IKibanaSearchRequest, options?: ISearchOptions) // Warning: (ae-missing-release-tag) "ISearchGeneric" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) -export type ISearchGeneric = (request: SearchStrategyRequest, options?: ISearchOptions) => Observable; +export type ISearchGeneric = (request: SearchStrategyRequest, options?: ISearchOptions) => Observable; // Warning: (ae-missing-release-tag) "ISearchOptions" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // @@ -1425,6 +1432,8 @@ export interface ISearchStart { aggs: AggsStart; search: ISearchGeneric; searchSource: ISearchStartSearchSource; + // (undocumented) + showError: (e: Error) => void; } // @public @@ -1433,6 +1442,11 @@ export interface ISearchStartSearchSource { createEmpty: () => ISearchSource; } +// Warning: (ae-missing-release-tag) "isErrorResponse" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export const isErrorResponse: (response?: IKibanaSearchResponse | undefined) => boolean | undefined; + // Warning: (ae-missing-release-tag) "isFilter" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) @@ -1443,6 +1457,11 @@ export const isFilter: (x: unknown) => x is Filter; // @public (undocumented) export const isFilters: (x: unknown) => x is Filter[]; +// Warning: (ae-missing-release-tag) "isPartialResponse" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export const isPartialResponse: (response?: IKibanaSearchResponse | undefined) => boolean | undefined; + // Warning: (ae-missing-release-tag) "isQuery" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) @@ -1581,6 +1600,19 @@ export interface OptionedValueProp { value: string; } +// Warning: (ae-forgotten-export) The symbol "KbnError" needs to be exported by the entry point index.d.ts +// Warning: (ae-missing-release-tag) "PainlessError" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export class PainlessError extends KbnError { + // Warning: (ae-forgotten-export) The symbol "EsError" needs to be exported by the entry point index.d.ts + constructor(err: EsError, request: IKibanaSearchRequest); + // (undocumented) + getErrorMessage(application: ApplicationStart): JSX.Element; + // (undocumented) + painlessStack?: string; +} + // Warning: (ae-forgotten-export) The symbol "parseEsInterval" needs to be exported by the entry point index.d.ts // Warning: (ae-missing-release-tag) "ParsedInterval" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // @@ -1676,11 +1708,54 @@ export interface QueryStateChange extends QueryStateChangePartial { globalFilters?: boolean; } -// Warning: (ae-forgotten-export) The symbol "Props" needs to be exported by the entry point index.d.ts // Warning: (ae-missing-release-tag) "QueryStringInput" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) -export const QueryStringInput: React.FC>; +export const QueryStringInput: (props: QueryStringInputProps) => JSX.Element; + +// Warning: (ae-missing-release-tag) "QueryStringInputProps" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export interface QueryStringInputProps { + // (undocumented) + bubbleSubmitEvent?: boolean; + // (undocumented) + className?: string; + // (undocumented) + dataTestSubj?: string; + // (undocumented) + disableAutoFocus?: boolean; + // (undocumented) + indexPatterns: Array; + // (undocumented) + isInvalid?: boolean; + // (undocumented) + languageSwitcherPopoverAnchorPosition?: PopoverAnchorPosition; + // (undocumented) + onBlur?: () => void; + // (undocumented) + onChange?: (query: Query) => void; + // (undocumented) + onChangeQueryInputFocus?: (isFocused: boolean) => void; + // (undocumented) + onSubmit?: (query: Query) => void; + // Warning: (ae-forgotten-export) The symbol "PersistedLog" needs to be exported by the entry point index.d.ts + // + // (undocumented) + persistedLog?: PersistedLog; + // (undocumented) + placeholder?: string; + // (undocumented) + prepend?: any; + // (undocumented) + query: Query; + // (undocumented) + screenTitle?: string; + // Warning: (ae-forgotten-export) The symbol "SuggestionsListSize" needs to be exported by the entry point index.d.ts + // + // (undocumented) + size?: SuggestionsListSize; +} // @public (undocumented) export type QuerySuggestion = QuerySuggestionBasic | QuerySuggestionField; @@ -1803,13 +1878,6 @@ export interface RefreshInterval { value: number; } -// Warning: (ae-missing-release-tag) "RequestTimeoutError" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public -export class RequestTimeoutError extends Error { - constructor(message?: string); -} - // Warning: (ae-missing-release-tag) "SavedQuery" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) @@ -1933,24 +2001,27 @@ export class SearchInterceptor { protected application: CoreStart['application']; // (undocumented) protected readonly deps: SearchInterceptorDeps; + // (undocumented) + protected getTimeoutMode(): TimeoutErrorMode; + // (undocumented) + protected handleSearchError(e: any, request: IKibanaSearchRequest, timeoutSignal: AbortSignal, appAbortSignal?: AbortSignal): Error; // @internal protected pendingCount$: BehaviorSubject; // @internal (undocumented) - protected runSearch(request: IEsSearchRequest, signal: AbortSignal, strategy?: string): Observable; - search(request: IEsSearchRequest, options?: ISearchOptions): Observable; + protected runSearch(request: IKibanaSearchRequest, signal: AbortSignal, strategy?: string): Observable; + search(request: IKibanaSearchRequest, options?: ISearchOptions): Observable; // @internal (undocumented) protected setupAbortSignal({ abortSignal, timeout, }: { abortSignal?: AbortSignal; timeout?: number; }): { combinedSignal: AbortSignal; + timeoutSignal: AbortSignal; cleanup: () => void; }; // (undocumented) - protected showTimeoutError: ((e: Error) => void) & import("lodash").Cancelable; - // @internal - protected timeoutSubscriptions: Subscription; -} + showError(e: Error): void; + } // Warning: (ae-missing-release-tag) "SearchInterceptorDeps" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // @@ -2063,6 +2134,17 @@ export interface SearchSourceFields { version?: boolean; } +// Warning: (ae-missing-release-tag) "SearchTimeoutError" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export class SearchTimeoutError extends KbnError { + constructor(err: Error, mode: TimeoutErrorMode); + // (undocumented) + getErrorMessage(application: ApplicationStart): JSX.Element; + // (undocumented) + mode: TimeoutErrorMode; + } + // Warning: (ae-missing-release-tag) "SortDirection" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) @@ -2135,6 +2217,18 @@ export class TimeHistory { // @public (undocumented) export type TimeHistoryContract = PublicMethodsOf; +// Warning: (ae-missing-release-tag) "TimeoutErrorMode" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export enum TimeoutErrorMode { + // (undocumented) + CHANGE = 2, + // (undocumented) + CONTACT = 1, + // (undocumented) + UPGRADE = 0 +} + // Warning: (ae-missing-release-tag) "TimeRange" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) @@ -2189,9 +2283,9 @@ export const UI_SETTINGS: { // src/plugins/data/common/es_query/filters/meta_filter.ts:54:3 - (ae-forgotten-export) The symbol "FilterMeta" needs to be exported by the entry point index.d.ts // src/plugins/data/common/es_query/filters/phrase_filter.ts:33:3 - (ae-forgotten-export) The symbol "PhraseFilterMeta" needs to be exported by the entry point index.d.ts // src/plugins/data/common/es_query/filters/phrases_filter.ts:31:3 - (ae-forgotten-export) The symbol "PhrasesFilterMeta" needs to be exported by the entry point index.d.ts +// src/plugins/data/common/index_patterns/index_patterns/index_pattern.ts:70:5 - (ae-forgotten-export) The symbol "FormatFieldFn" needs to be exported by the entry point index.d.ts // src/plugins/data/common/search/aggs/types.ts:98:51 - (ae-forgotten-export) The symbol "AggTypesRegistryStart" needs to be exported by the entry point index.d.ts // src/plugins/data/public/field_formats/field_formats_service.ts:67:3 - (ae-forgotten-export) The symbol "FormatFactory" needs to be exported by the entry point index.d.ts -// src/plugins/data/public/index.ts:66:23 - (ae-forgotten-export) The symbol "FilterLabel" needs to be exported by the entry point index.d.ts // src/plugins/data/public/index.ts:66:23 - (ae-forgotten-export) The symbol "FILTERS" needs to be exported by the entry point index.d.ts // src/plugins/data/public/index.ts:66:23 - (ae-forgotten-export) The symbol "getDisplayValueFromFilter" needs to be exported by the entry point index.d.ts // src/plugins/data/public/index.ts:66:23 - (ae-forgotten-export) The symbol "generateFilters" needs to be exported by the entry point index.d.ts @@ -2217,27 +2311,27 @@ export const UI_SETTINGS: { // src/plugins/data/public/index.ts:178:26 - (ae-forgotten-export) The symbol "UrlFormat" needs to be exported by the entry point index.d.ts // src/plugins/data/public/index.ts:178:26 - (ae-forgotten-export) The symbol "StringFormat" needs to be exported by the entry point index.d.ts // src/plugins/data/public/index.ts:178:26 - (ae-forgotten-export) The symbol "TruncateFormat" needs to be exported by the entry point index.d.ts -// src/plugins/data/public/index.ts:234:27 - (ae-forgotten-export) The symbol "isFilterable" needs to be exported by the entry point index.d.ts -// src/plugins/data/public/index.ts:234:27 - (ae-forgotten-export) The symbol "isNestedField" needs to be exported by the entry point index.d.ts -// src/plugins/data/public/index.ts:234:27 - (ae-forgotten-export) The symbol "validateIndexPattern" needs to be exported by the entry point index.d.ts -// src/plugins/data/public/index.ts:234:27 - (ae-forgotten-export) The symbol "getFromSavedObject" needs to be exported by the entry point index.d.ts -// src/plugins/data/public/index.ts:234:27 - (ae-forgotten-export) The symbol "flattenHitWrapper" needs to be exported by the entry point index.d.ts -// src/plugins/data/public/index.ts:234:27 - (ae-forgotten-export) The symbol "formatHitProvider" needs to be exported by the entry point index.d.ts -// src/plugins/data/public/index.ts:380:20 - (ae-forgotten-export) The symbol "getRequestInspectorStats" needs to be exported by the entry point index.d.ts -// src/plugins/data/public/index.ts:380:20 - (ae-forgotten-export) The symbol "getResponseInspectorStats" needs to be exported by the entry point index.d.ts -// src/plugins/data/public/index.ts:380:20 - (ae-forgotten-export) The symbol "tabifyAggResponse" needs to be exported by the entry point index.d.ts -// src/plugins/data/public/index.ts:380:20 - (ae-forgotten-export) The symbol "tabifyGetColumns" needs to be exported by the entry point index.d.ts -// src/plugins/data/public/index.ts:382:1 - (ae-forgotten-export) The symbol "CidrMask" needs to be exported by the entry point index.d.ts -// src/plugins/data/public/index.ts:383:1 - (ae-forgotten-export) The symbol "dateHistogramInterval" needs to be exported by the entry point index.d.ts -// src/plugins/data/public/index.ts:392:1 - (ae-forgotten-export) The symbol "InvalidEsCalendarIntervalError" needs to be exported by the entry point index.d.ts -// src/plugins/data/public/index.ts:393:1 - (ae-forgotten-export) The symbol "InvalidEsIntervalFormatError" needs to be exported by the entry point index.d.ts -// src/plugins/data/public/index.ts:394:1 - (ae-forgotten-export) The symbol "Ipv4Address" needs to be exported by the entry point index.d.ts -// src/plugins/data/public/index.ts:395:1 - (ae-forgotten-export) The symbol "isDateHistogramBucketAggConfig" needs to be exported by the entry point index.d.ts -// src/plugins/data/public/index.ts:399:1 - (ae-forgotten-export) The symbol "isValidEsInterval" needs to be exported by the entry point index.d.ts -// src/plugins/data/public/index.ts:400:1 - (ae-forgotten-export) The symbol "isValidInterval" needs to be exported by the entry point index.d.ts -// src/plugins/data/public/index.ts:403:1 - (ae-forgotten-export) The symbol "parseInterval" needs to be exported by the entry point index.d.ts -// src/plugins/data/public/index.ts:404:1 - (ae-forgotten-export) The symbol "propFilter" needs to be exported by the entry point index.d.ts -// src/plugins/data/public/index.ts:407:1 - (ae-forgotten-export) The symbol "toAbsoluteDates" needs to be exported by the entry point index.d.ts +// src/plugins/data/public/index.ts:236:27 - (ae-forgotten-export) The symbol "isFilterable" needs to be exported by the entry point index.d.ts +// src/plugins/data/public/index.ts:236:27 - (ae-forgotten-export) The symbol "isNestedField" needs to be exported by the entry point index.d.ts +// src/plugins/data/public/index.ts:236:27 - (ae-forgotten-export) The symbol "validateIndexPattern" needs to be exported by the entry point index.d.ts +// src/plugins/data/public/index.ts:236:27 - (ae-forgotten-export) The symbol "getFromSavedObject" needs to be exported by the entry point index.d.ts +// src/plugins/data/public/index.ts:236:27 - (ae-forgotten-export) The symbol "flattenHitWrapper" needs to be exported by the entry point index.d.ts +// src/plugins/data/public/index.ts:236:27 - (ae-forgotten-export) The symbol "formatHitProvider" needs to be exported by the entry point index.d.ts +// src/plugins/data/public/index.ts:388:20 - (ae-forgotten-export) The symbol "getRequestInspectorStats" needs to be exported by the entry point index.d.ts +// src/plugins/data/public/index.ts:388:20 - (ae-forgotten-export) The symbol "getResponseInspectorStats" needs to be exported by the entry point index.d.ts +// src/plugins/data/public/index.ts:388:20 - (ae-forgotten-export) The symbol "tabifyAggResponse" needs to be exported by the entry point index.d.ts +// src/plugins/data/public/index.ts:388:20 - (ae-forgotten-export) The symbol "tabifyGetColumns" needs to be exported by the entry point index.d.ts +// src/plugins/data/public/index.ts:390:1 - (ae-forgotten-export) The symbol "CidrMask" needs to be exported by the entry point index.d.ts +// src/plugins/data/public/index.ts:391:1 - (ae-forgotten-export) The symbol "dateHistogramInterval" needs to be exported by the entry point index.d.ts +// src/plugins/data/public/index.ts:400:1 - (ae-forgotten-export) The symbol "InvalidEsCalendarIntervalError" needs to be exported by the entry point index.d.ts +// src/plugins/data/public/index.ts:401:1 - (ae-forgotten-export) The symbol "InvalidEsIntervalFormatError" needs to be exported by the entry point index.d.ts +// src/plugins/data/public/index.ts:402:1 - (ae-forgotten-export) The symbol "Ipv4Address" needs to be exported by the entry point index.d.ts +// src/plugins/data/public/index.ts:403:1 - (ae-forgotten-export) The symbol "isDateHistogramBucketAggConfig" needs to be exported by the entry point index.d.ts +// src/plugins/data/public/index.ts:407:1 - (ae-forgotten-export) The symbol "isValidEsInterval" needs to be exported by the entry point index.d.ts +// src/plugins/data/public/index.ts:408:1 - (ae-forgotten-export) The symbol "isValidInterval" needs to be exported by the entry point index.d.ts +// src/plugins/data/public/index.ts:411:1 - (ae-forgotten-export) The symbol "parseInterval" needs to be exported by the entry point index.d.ts +// src/plugins/data/public/index.ts:412:1 - (ae-forgotten-export) The symbol "propFilter" needs to be exported by the entry point index.d.ts +// src/plugins/data/public/index.ts:415:1 - (ae-forgotten-export) The symbol "toAbsoluteDates" needs to be exported by the entry point index.d.ts // src/plugins/data/public/query/state_sync/connect_to_query_state.ts:45:5 - (ae-forgotten-export) The symbol "FilterStateStore" needs to be exported by the entry point index.d.ts // (No @packageDocumentation comment for this package) diff --git a/src/plugins/data/public/query/timefilter/timefilter.test.ts b/src/plugins/data/public/query/timefilter/timefilter.test.ts index 1280664ac8389..6c1a4eff786f6 100644 --- a/src/plugins/data/public/query/timefilter/timefilter.test.ts +++ b/src/plugins/data/public/query/timefilter/timefilter.test.ts @@ -54,6 +54,10 @@ function clearNowTimeStub() { delete global.nowTime; } +test('isTimeTouched is initially set to false', () => { + expect(timefilter.isTimeTouched()).toBe(false); +}); + describe('setTime', () => { let update: sinon.SinonSpy; let fetch: sinon.SinonSpy; @@ -84,6 +88,10 @@ describe('setTime', () => { }); }); + test('should update isTimeTouched', () => { + expect(timefilter.isTimeTouched()).toBe(true); + }); + test('should not add unexpected object keys to time state', () => { const unexpectedKey = 'unexpectedKey'; timefilter.setTime({ diff --git a/src/plugins/data/public/query/timefilter/timefilter.ts b/src/plugins/data/public/query/timefilter/timefilter.ts index 5eb1546fa015f..01b82087cf354 100644 --- a/src/plugins/data/public/query/timefilter/timefilter.ts +++ b/src/plugins/data/public/query/timefilter/timefilter.ts @@ -41,6 +41,8 @@ export class Timefilter { private fetch$ = new Subject(); private _time: TimeRange; + // Denotes whether setTime has been called, can be used to determine if the constructor defaults are being used. + private _isTimeTouched: boolean = false; private _refreshInterval!: RefreshInterval; private _history: TimeHistoryContract; @@ -68,6 +70,10 @@ export class Timefilter { return this._isAutoRefreshSelectorEnabled; } + public isTimeTouched() { + return this._isTimeTouched; + } + public getEnabledUpdated$ = () => { return this.enabledUpdated$.asObservable(); }; @@ -112,6 +118,7 @@ export class Timefilter { from: newTime.from, to: newTime.to, }; + this._isTimeTouched = true; this._history.add(this._time); this.timeUpdate$.next(); this.fetch$.next(); diff --git a/src/plugins/data/public/query/timefilter/timefilter_service.mock.ts b/src/plugins/data/public/query/timefilter/timefilter_service.mock.ts index 7863000b1ace4..060257a880528 100644 --- a/src/plugins/data/public/query/timefilter/timefilter_service.mock.ts +++ b/src/plugins/data/public/query/timefilter/timefilter_service.mock.ts @@ -26,6 +26,7 @@ const createSetupContractMock = () => { const timefilterMock: jest.Mocked = { isAutoRefreshSelectorEnabled: jest.fn(), isTimeRangeSelectorEnabled: jest.fn(), + isTimeTouched: jest.fn(), getEnabledUpdated$: jest.fn(), getTimeUpdate$: jest.fn(), getRefreshIntervalUpdate$: jest.fn(), diff --git a/src/plugins/data/public/search/README.md b/src/plugins/data/public/search/README.md deleted file mode 100644 index 0a123ffa3f1e9..0000000000000 --- a/src/plugins/data/public/search/README.md +++ /dev/null @@ -1,23 +0,0 @@ -# search - -The `search` service provides you with APIs to query Elasticsearch. - -The services are split into two parts: (1) low-level API; and (2) high-level API. - -## Low-level API - -With low level API you work directly with elasticsearch DSL - -```typescript -const results = await data.search.search(request, params); -``` - -## High-level API - -Using high-level API you work with Kibana abstractions around Elasticsearch DSL: filters, queries, and aggregations. Provided by the *Search Source* service. - -```typescript -const search = data.search.searchSource.createEmpty(); -search.setField('query', data.query.queryString); -const results = await search.fetch(); -``` diff --git a/src/plugins/data/public/search/aggs/aggs_service.ts b/src/plugins/data/public/search/aggs/aggs_service.ts index d535f97fefdf8..4b088ddfe314f 100644 --- a/src/plugins/data/public/search/aggs/aggs_service.ts +++ b/src/plugins/data/public/search/aggs/aggs_service.ts @@ -21,17 +21,16 @@ import { Subscription } from 'rxjs'; import { IUiSettingsClient } from 'src/core/public'; import { ExpressionsServiceSetup } from 'src/plugins/expressions/common'; +import { FieldFormatsStart } from '../../field_formats'; +import { getForceNow } from '../../query/timefilter/lib/get_force_now'; +import { calculateBounds, TimeRange } from '../../../common'; import { aggsRequiredUiSettings, AggsCommonStartDependencies, AggsCommonService, AggConfigs, AggTypesDependencies, - calculateBounds, - TimeRange, -} from '../../../common'; -import { FieldFormatsStart } from '../../field_formats'; -import { getForceNow } from '../../query/timefilter/lib/get_force_now'; +} from '../../../common/search/aggs'; import { AggsSetup, AggsStart } from './types'; /** diff --git a/src/plugins/data/public/search/errors/index.ts b/src/plugins/data/public/search/errors/index.ts new file mode 100644 index 0000000000000..6082e758a8bad --- /dev/null +++ b/src/plugins/data/public/search/errors/index.ts @@ -0,0 +1,21 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export * from './painless_error'; +export * from './timeout_error'; diff --git a/src/plugins/data/public/search/errors/painless_error.tsx b/src/plugins/data/public/search/errors/painless_error.tsx new file mode 100644 index 0000000000000..244f205469a2f --- /dev/null +++ b/src/plugins/data/public/search/errors/painless_error.tsx @@ -0,0 +1,89 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React from 'react'; +import { i18n } from '@kbn/i18n'; +import { EuiButton, EuiSpacer, EuiText, EuiCodeBlock } from '@elastic/eui'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { ApplicationStart } from 'kibana/public'; +import { KbnError } from '../../../../kibana_utils/common'; +import { EsError, isEsError } from './types'; +import { IKibanaSearchRequest } from '..'; + +export class PainlessError extends KbnError { + painlessStack?: string; + constructor(err: EsError, request: IKibanaSearchRequest) { + const rootCause = getRootCause(err as EsError); + + super( + i18n.translate('data.painlessError.painlessScriptedFieldErrorMessage', { + defaultMessage: "Error executing Painless script: '{script}'.", + values: { script: rootCause?.script }, + }) + ); + this.painlessStack = rootCause?.script_stack ? rootCause?.script_stack.join('\n') : undefined; + } + + public getErrorMessage(application: ApplicationStart) { + function onClick() { + application.navigateToApp('management', { + path: `/kibana/indexPatterns`, + }); + } + + return ( + <> + {this.message} + + + {this.painlessStack ? ( + + {this.painlessStack} + + ) : null} + + + + + + + ); + } +} + +function getFailedShards(err: EsError) { + const failedShards = + err.body?.attributes?.error?.failed_shards || + err.body?.attributes?.error?.caused_by?.failed_shards; + return failedShards ? failedShards[0] : undefined; +} + +function getRootCause(err: EsError) { + return getFailedShards(err)?.reason; +} + +export function isPainlessError(err: Error | EsError) { + if (!isEsError(err)) return false; + + const rootCause = getRootCause(err as EsError); + if (!rootCause) return false; + + const { lang } = rootCause; + return lang === 'painless'; +} diff --git a/src/plugins/data/public/search/errors/timeout_error.test.tsx b/src/plugins/data/public/search/errors/timeout_error.test.tsx new file mode 100644 index 0000000000000..ad3384c389fbf --- /dev/null +++ b/src/plugins/data/public/search/errors/timeout_error.test.tsx @@ -0,0 +1,62 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { SearchTimeoutError, TimeoutErrorMode } from './timeout_error'; + +import { coreMock } from '../../../../../core/public/mocks'; +const startMock = coreMock.createStart(); + +import { mount } from 'enzyme'; +import { AbortError } from 'src/plugins/data/common'; + +describe('SearchTimeoutError', () => { + beforeEach(() => { + jest.clearAllMocks(); + startMock.application.navigateToApp.mockImplementation(jest.fn()); + }); + + it('Should navigate to upgrade', () => { + const e = new SearchTimeoutError(new AbortError(), TimeoutErrorMode.UPGRADE); + const component = mount(e.getErrorMessage(startMock.application)); + + expect(component.find('EuiButton').length).toBe(1); + component.find('EuiButton').simulate('click'); + expect(startMock.application.navigateToUrl).toHaveBeenCalledWith( + 'https://www.elastic.co/subscriptions' + ); + }); + + it('Should create contact admin message', () => { + const e = new SearchTimeoutError(new AbortError(), TimeoutErrorMode.CONTACT); + const component = mount(e.getErrorMessage(startMock.application)); + + expect(component.find('EuiButton').length).toBe(0); + }); + + it('Should navigate to settings', () => { + const e = new SearchTimeoutError(new AbortError(), TimeoutErrorMode.CHANGE); + const component = mount(e.getErrorMessage(startMock.application)); + + expect(component.find('EuiButton').length).toBe(1); + component.find('EuiButton').simulate('click'); + expect(startMock.application.navigateToApp).toHaveBeenCalledWith('management', { + path: '/kibana/settings', + }); + }); +}); diff --git a/src/plugins/data/public/search/errors/timeout_error.tsx b/src/plugins/data/public/search/errors/timeout_error.tsx new file mode 100644 index 0000000000000..007689dd0269d --- /dev/null +++ b/src/plugins/data/public/search/errors/timeout_error.tsx @@ -0,0 +1,114 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React from 'react'; +import { i18n } from '@kbn/i18n'; +import { EuiButton, EuiSpacer, EuiText } from '@elastic/eui'; +import { ApplicationStart } from 'kibana/public'; +import { KbnError } from '../../../../kibana_utils/common'; + +export enum TimeoutErrorMode { + UPGRADE, + CONTACT, + CHANGE, +} + +/** + * Request Failure - When an entire multi request fails + * @param {Error} err - the Error that came back + */ +export class SearchTimeoutError extends KbnError { + public mode: TimeoutErrorMode; + constructor(err: Error, mode: TimeoutErrorMode) { + super(`Request timeout: ${JSON.stringify(err?.message)}`); + this.mode = mode; + } + + private getMessage() { + switch (this.mode) { + case TimeoutErrorMode.UPGRADE: + return i18n.translate('data.search.upgradeLicense', { + defaultMessage: + 'Your query has timed out. With our free Basic tier, your queries never time out.', + }); + case TimeoutErrorMode.CONTACT: + return i18n.translate('data.search.timeoutContactAdmin', { + defaultMessage: + 'Your query has timed out. Contact your system administrator to increase the run time.', + }); + case TimeoutErrorMode.CHANGE: + return i18n.translate('data.search.timeoutIncreaseSetting', { + defaultMessage: + 'Your query has timed out. Increase run time with the search timeout advanced setting.', + }); + } + } + + private getActionText() { + switch (this.mode) { + case TimeoutErrorMode.UPGRADE: + return i18n.translate('data.search.upgradeLicenseActionText', { + defaultMessage: 'Upgrade now', + }); + break; + case TimeoutErrorMode.CHANGE: + return i18n.translate('data.search.timeoutIncreaseSettingActionText', { + defaultMessage: 'Edit setting', + }); + break; + } + } + + private onClick(application: ApplicationStart) { + switch (this.mode) { + case TimeoutErrorMode.UPGRADE: + application.navigateToUrl('https://www.elastic.co/subscriptions'); + break; + case TimeoutErrorMode.CHANGE: + application.navigateToApp('management', { + path: `/kibana/settings`, + }); + break; + } + } + + public getErrorMessage(application: ApplicationStart) { + const actionText = this.getActionText(); + return ( + <> + {this.getMessage()} + {actionText && ( + <> + + + this.onClick(application)} + size="s" + data-test-subj="searchTimeoutError" + > + {actionText} + + + + )} + + ); + } +} diff --git a/src/plugins/data/public/search/errors/types.ts b/src/plugins/data/public/search/errors/types.ts new file mode 100644 index 0000000000000..4182209eb68a5 --- /dev/null +++ b/src/plugins/data/public/search/errors/types.ts @@ -0,0 +1,73 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +interface FailedShard { + shard: number; + index: string; + node: string; + reason: { + type: string; + reason: string; + script_stack: string[]; + script: string; + lang: string; + position: { + offset: number; + start: number; + end: number; + }; + caused_by: { + type: string; + reason: string; + }; + }; +} + +export interface EsError { + body: { + statusCode: number; + error: string; + message: string; + attributes?: { + error?: { + root_cause?: [ + { + lang: string; + script: string; + } + ]; + type: string; + reason: string; + failed_shards: FailedShard[]; + caused_by: { + type: string; + reason: string; + phase: string; + grouped: boolean; + failed_shards: FailedShard[]; + script_stack: string[]; + }; + }; + }; + }; +} + +export function isEsError(e: any): e is EsError { + return !!e.body?.attributes; +} diff --git a/src/plugins/data/public/search/expressions/esaggs.ts b/src/plugins/data/public/search/expressions/esaggs.ts index 50fbb114b39fd..1021ef0f91d52 100644 --- a/src/plugins/data/public/search/expressions/esaggs.ts +++ b/src/plugins/data/public/search/expressions/esaggs.ts @@ -20,7 +20,6 @@ import { get, hasIn } from 'lodash'; import { i18n } from '@kbn/i18n'; import { KibanaDatatable, KibanaDatatableColumn } from 'src/plugins/expressions/public'; -import { calculateObjectHash } from '../../../../../plugins/kibana_utils/public'; import { PersistedState } from '../../../../../plugins/visualizations/public'; import { Adapters } from '../../../../../plugins/inspector/public'; @@ -38,6 +37,7 @@ import { getRequestInspectorStats, getResponseInspectorStats, IAggConfigs, + ISearchSource, tabifyAggResponse, } from '../../../common/search'; @@ -48,7 +48,6 @@ import { getQueryService, getSearchService, } from '../../services'; -import { ISearchSource } from '../search_source'; import { buildTabularInspectorData } from './build_tabular_inspector_data'; import { serializeAggConfig } from './utils'; @@ -60,7 +59,6 @@ export interface RequestHandlerParams { indexPattern?: IIndexPattern; query?: Query; filters?: Filter[]; - forceFetch: boolean; filterManager: FilterManager; uiState?: PersistedState; partialRows?: boolean; @@ -80,7 +78,6 @@ const handleCourierRequest = async ({ indexPattern, query, filters, - forceFetch, partialRows, metricsAtAllLevels, inspectorAdapters, @@ -137,46 +134,35 @@ const handleCourierRequest = async ({ requestSearchSource.setField('filter', filters); requestSearchSource.setField('query', query); - const reqBody = await requestSearchSource.getSearchRequestBody(); - - const queryHash = calculateObjectHash(reqBody); - // We only need to reexecute the query, if forceFetch was true or the hash of the request body has changed - // since the last request - const shouldQuery = forceFetch || (searchSource as any).lastQuery !== queryHash; - - if (shouldQuery) { - inspectorAdapters.requests.reset(); - const request = inspectorAdapters.requests.start( - i18n.translate('data.functions.esaggs.inspector.dataRequest.title', { - defaultMessage: 'Data', + inspectorAdapters.requests.reset(); + const request = inspectorAdapters.requests.start( + i18n.translate('data.functions.esaggs.inspector.dataRequest.title', { + defaultMessage: 'Data', + }), + { + description: i18n.translate('data.functions.esaggs.inspector.dataRequest.description', { + defaultMessage: + 'This request queries Elasticsearch to fetch the data for the visualization.', }), - { - description: i18n.translate('data.functions.esaggs.inspector.dataRequest.description', { - defaultMessage: - 'This request queries Elasticsearch to fetch the data for the visualization.', - }), - } - ); - request.stats(getRequestInspectorStats(requestSearchSource)); - - try { - const response = await requestSearchSource.fetch({ abortSignal }); - - (searchSource as any).lastQuery = queryHash; - - request.stats(getResponseInspectorStats(response, searchSource)).ok({ json: response }); - - (searchSource as any).rawResponse = response; - } catch (e) { - // Log any error during request to the inspector - request.error({ json: e }); - throw e; - } finally { - // Add the request body no matter if things went fine or not - requestSearchSource.getSearchRequestBody().then((req: unknown) => { - request.json(req); - }); } + ); + request.stats(getRequestInspectorStats(requestSearchSource)); + + try { + const response = await requestSearchSource.fetch({ abortSignal }); + + request.stats(getResponseInspectorStats(response, searchSource)).ok({ json: response }); + + (searchSource as any).rawResponse = response; + } catch (e) { + // Log any error during request to the inspector + request.error({ json: e }); + throw e; + } finally { + // Add the request body no matter if things went fine or not + requestSearchSource.getSearchRequestBody().then((req: unknown) => { + request.json(req); + }); } // Note that rawResponse is not deeply cloned here, so downstream applications using courier @@ -207,19 +193,11 @@ const handleCourierRequest = async ({ : undefined, }; - const tabifyCacheHash = calculateObjectHash({ tabifyAggs: aggs, ...tabifyParams }); - // We only need to reexecute tabify, if either we did a new request or some input params to tabify changed - const shouldCalculateNewTabify = - shouldQuery || (searchSource as any).lastTabifyHash !== tabifyCacheHash; - - if (shouldCalculateNewTabify) { - (searchSource as any).lastTabifyHash = tabifyCacheHash; - (searchSource as any).tabifiedResponse = tabifyAggResponse( - aggs, - (searchSource as any).finalResponse, - tabifyParams - ); - } + (searchSource as any).tabifiedResponse = tabifyAggResponse( + aggs, + (searchSource as any).finalResponse, + tabifyParams + ); inspectorAdapters.data.setTabularLoader( () => @@ -294,7 +272,6 @@ export const esaggs = (): EsaggsExpressionFunctionDefinition => ({ query: get(input, 'query', undefined) as any, filters: get(input, 'filters', undefined), timeFields: args.timeFields, - forceFetch: true, metricsAtAllLevels: args.metricsAtAllLevels, partialRows: args.partialRows, inspectorAdapters: inspectorAdapters as Adapters, diff --git a/src/plugins/data/public/search/fetch/handle_response.tsx b/src/plugins/data/public/search/fetch/handle_response.tsx index 14e9b59f49bfb..93b1fc1373528 100644 --- a/src/plugins/data/public/search/fetch/handle_response.tsx +++ b/src/plugins/data/public/search/fetch/handle_response.tsx @@ -21,7 +21,7 @@ import React from 'react'; import { i18n } from '@kbn/i18n'; import { EuiSpacer } from '@elastic/eui'; import { SearchResponse } from 'elasticsearch'; -import { ShardFailureOpenModalButton } from '../../ui'; +import { ShardFailureOpenModalButton } from '../../ui/shard_failure_modal'; import { toMountPoint } from '../../../../kibana_react/public'; import { getNotifications } from '../../services'; import { SearchRequest } from '..'; diff --git a/src/plugins/data/public/search/fetch/index.ts b/src/plugins/data/public/search/fetch/index.ts index 4b8511edfc26f..340a795d37bfb 100644 --- a/src/plugins/data/public/search/fetch/index.ts +++ b/src/plugins/data/public/search/fetch/index.ts @@ -17,8 +17,4 @@ * under the License. */ -export * from './types'; -export { getSearchParams, getSearchParamsFromRequest, getPreference } from './get_search_params'; - -export { RequestFailure } from './request_error'; export { handleResponse } from './handle_response'; diff --git a/src/plugins/data/public/search/fetch/types.ts b/src/plugins/data/public/search/fetch/types.ts deleted file mode 100644 index cdf10d8f1a1b0..0000000000000 --- a/src/plugins/data/public/search/fetch/types.ts +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { SearchResponse } from 'elasticsearch'; -import { GetConfigFn } from '../../../common'; -import { LegacyFetchHandlers } from '../legacy/types'; - -/** - * @internal - * - * This type is used when flattenning a SearchSource and passing it down to legacy search. - * Once legacy search is removed, this type should become internal to `SearchSource`, - * where `ISearchRequestParams` is used externally instead. - */ -export type SearchRequest = Record; - -export interface FetchHandlers { - getConfig: GetConfigFn; - /** - * Callback which can be used to hook into responses, modify them, or perform - * side effects like displaying UI errors on the client. - */ - onResponse: (request: SearchRequest, response: SearchResponse) => SearchResponse; - /** - * These handlers are only used by the legacy defaultSearchStrategy and can be removed - * once that strategy has been deprecated. - */ - legacy: LegacyFetchHandlers; -} - -export interface SearchError { - name: string; - status: string; - title: string; - message: string; - path: string; - type: string; -} diff --git a/src/plugins/data/public/search/index.ts b/src/plugins/data/public/search/index.ts index c1af9699acbb2..86804a819cb0e 100644 --- a/src/plugins/data/public/search/index.ts +++ b/src/plugins/data/public/search/index.ts @@ -19,34 +19,31 @@ export * from './expressions'; +export { ISearchSetup, ISearchStart, ISearchStartSearchSource, SearchEnhancements } from './types'; + export { + ES_SEARCH_STRATEGY, + EsQuerySortValue, + extractReferences as extractSearchSourceReferences, + getSearchParamsFromRequest, + IEsSearchRequest, + IEsSearchResponse, + IKibanaSearchRequest, + IKibanaSearchResponse, + injectReferences as injectSearchSourceReferences, ISearch, ISearchGeneric, - ISearchSetup, - ISearchStart, - ISearchStartSearchSource, - SearchEnhancements, -} from './types'; - -export { IEsSearchResponse, IEsSearchRequest, ES_SEARCH_STRATEGY } from '../../common/search'; - -export { getEsPreference } from './es_search'; - -export { IKibanaSearchResponse, IKibanaSearchRequest } from '../../common/search'; - -export { SearchError, getSearchParamsFromRequest, SearchRequest } from './fetch'; - -export { ISearchSource, + parseSearchSourceJSON, + SearchError, + SearchRequest, SearchSource, SearchSourceDependencies, SearchSourceFields, - EsQuerySortValue, SortDirection, - extractReferences as extractSearchSourceReferences, - injectReferences as injectSearchSourceReferences, - parseSearchSourceJSON, -} from './search_source'; +} from '../../common/search'; + +export { getEsPreference } from './es_search'; export { SearchInterceptor, SearchInterceptorDeps } from './search_interceptor'; -export { RequestTimeoutError } from './request_timeout_error'; +export * from './errors'; diff --git a/src/plugins/data/public/search/legacy/call_msearch.test.ts b/src/plugins/data/public/search/legacy/call_msearch.test.ts new file mode 100644 index 0000000000000..da39bf521fe3d --- /dev/null +++ b/src/plugins/data/public/search/legacy/call_msearch.test.ts @@ -0,0 +1,54 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { HttpStart } from 'src/core/public'; +import { coreMock } from '../../../../../core/public/mocks'; +import { getCallMsearch } from './call_msearch'; + +describe('callMsearch', () => { + const msearchMock = jest.fn().mockResolvedValue({ body: { responses: [] } }); + let http: jest.Mocked; + + beforeEach(() => { + msearchMock.mockClear(); + http = coreMock.createStart().http; + http.post.mockResolvedValue(msearchMock); + }); + + test('calls http.post with the correct arguments', async () => { + const searches = [{ header: { index: 'foo' }, body: {} }]; + const callMsearch = getCallMsearch({ http }); + await callMsearch({ + body: { searches }, + signal: new AbortController().signal, + }); + + expect(http.post.mock.calls).toMatchInlineSnapshot(` + Array [ + Array [ + "/internal/_msearch", + Object { + "body": "{\\"searches\\":[{\\"header\\":{\\"index\\":\\"foo\\"},\\"body\\":{}}]}", + "signal": AbortSignal {}, + }, + ], + ] + `); + }); +}); diff --git a/src/plugins/data/public/search/legacy/call_msearch.ts b/src/plugins/data/public/search/legacy/call_msearch.ts index fd4f8a07919f8..6b2b9b4da020b 100644 --- a/src/plugins/data/public/search/legacy/call_msearch.ts +++ b/src/plugins/data/public/search/legacy/call_msearch.ts @@ -18,7 +18,7 @@ */ import { HttpStart } from 'src/core/public'; -import { LegacyFetchHandlers } from './types'; +import { LegacyFetchHandlers } from '../../../common/search/search_source'; /** * Wrapper for calling the internal msearch endpoint from the client. diff --git a/src/plugins/data/public/search/legacy/default_search_strategy.test.ts b/src/plugins/data/public/search/legacy/default_search_strategy.test.ts deleted file mode 100644 index ad59e5c6c9625..0000000000000 --- a/src/plugins/data/public/search/legacy/default_search_strategy.test.ts +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { HttpStart } from 'src/core/public'; -import { coreMock } from '../../../../../core/public/mocks'; -import { getCallMsearch } from './call_msearch'; -import { defaultSearchStrategy } from './default_search_strategy'; -import { LegacyFetchHandlers, SearchStrategySearchParams } from './types'; -import { BehaviorSubject } from 'rxjs'; - -const { search } = defaultSearchStrategy; - -const msearchMock = jest.fn().mockResolvedValue({ body: { responses: [] } }); - -describe('defaultSearchStrategy', function () { - describe('search', function () { - let searchArgs: MockedKeys; - let http: jest.Mocked; - - beforeEach(() => { - msearchMock.mockClear(); - - http = coreMock.createStart().http; - http.post.mockResolvedValue(msearchMock); - - searchArgs = { - searchRequests: [ - { - index: { title: 'foo' }, - }, - ], - getConfig: jest.fn(), - onResponse: (req, res) => res, - legacy: { - callMsearch: getCallMsearch({ http }), - loadingCount$: new BehaviorSubject(0) as any, - } as jest.Mocked, - }; - }); - - test('calls http.post with the correct arguments', async () => { - await search({ ...searchArgs }); - expect(http.post.mock.calls).toMatchInlineSnapshot(` - Array [ - Array [ - "/internal/_msearch", - Object { - "body": "{\\"searches\\":[{\\"header\\":{\\"index\\":\\"foo\\"}}]}", - "signal": AbortSignal {}, - }, - ], - ] - `); - }); - }); -}); diff --git a/src/plugins/data/public/search/legacy/index.ts b/src/plugins/data/public/search/legacy/index.ts index 74e516f407e8c..08e5eab788e76 100644 --- a/src/plugins/data/public/search/legacy/index.ts +++ b/src/plugins/data/public/search/legacy/index.ts @@ -17,4 +17,4 @@ * under the License. */ -export { fetchSoon } from './fetch_soon'; +export * from './call_msearch'; diff --git a/src/plugins/data/public/search/legacy/types.ts b/src/plugins/data/public/search/legacy/types.ts deleted file mode 100644 index 740bc22a7485c..0000000000000 --- a/src/plugins/data/public/search/legacy/types.ts +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { BehaviorSubject } from 'rxjs'; -import { SearchResponse } from 'elasticsearch'; -import { FetchHandlers } from '../fetch'; -import { SearchRequest } from '..'; - -// @internal -export interface LegacyFetchHandlers { - callMsearch: (params: { - body: SearchRequest; - signal: AbortSignal; - }) => Promise>>; - loadingCount$: BehaviorSubject; -} - -export interface SearchStrategySearchParams extends FetchHandlers { - searchRequests: SearchRequest[]; -} - -// @deprecated -export interface SearchStrategyProvider { - id: string; - search: (params: SearchStrategySearchParams) => SearchStrategyResponse; -} - -export interface SearchStrategyResponse { - searching: Promise>>; - abort: () => void; -} diff --git a/src/plugins/data/public/search/mocks.ts b/src/plugins/data/public/search/mocks.ts index f4ed7d8b122b9..8bad4cd269b3f 100644 --- a/src/plugins/data/public/search/mocks.ts +++ b/src/plugins/data/public/search/mocks.ts @@ -18,10 +18,8 @@ */ import { searchAggsSetupMock, searchAggsStartMock } from './aggs/mocks'; +import { searchSourceMock } from './search_source/mocks'; import { ISearchSetup, ISearchStart } from './types'; -import { searchSourceMock, createSearchSourceMock } from './search_source/mocks'; - -export * from './search_source/mocks'; function createSetupContract(): jest.Mocked { return { @@ -34,7 +32,8 @@ function createStartContract(): jest.Mocked { return { aggs: searchAggsStartMock(), search: jest.fn(), - searchSource: searchSourceMock, + showError: jest.fn(), + searchSource: searchSourceMock.createStartContract(), }; } @@ -42,5 +41,3 @@ export const searchServiceMock = { createSetupContract, createStartContract, }; - -export { createSearchSourceMock }; diff --git a/src/plugins/data/public/search/request_timeout_error.ts b/src/plugins/data/public/search/request_timeout_error.ts deleted file mode 100644 index 92894deb4f0ff..0000000000000 --- a/src/plugins/data/public/search/request_timeout_error.ts +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -/** - * Class used to signify that a request timed out. Useful for applications to conditionally handle - * this type of error differently than other errors. - */ -export class RequestTimeoutError extends Error { - constructor(message = 'Request timed out') { - super(message); - this.message = message; - this.name = 'RequestTimeoutError'; - } -} diff --git a/src/plugins/data/public/search/search_interceptor.test.ts b/src/plugins/data/public/search/search_interceptor.test.ts index 7bfa6f0ab1bc5..ade15adc1c3a3 100644 --- a/src/plugins/data/public/search/search_interceptor.test.ts +++ b/src/plugins/data/public/search/search_interceptor.test.ts @@ -22,6 +22,7 @@ import { coreMock } from '../../../../core/public/mocks'; import { IEsSearchRequest } from '../../common/search'; import { SearchInterceptor } from './search_interceptor'; import { AbortError } from '../../common'; +import { SearchTimeoutError, PainlessError } from './errors'; let searchInterceptor: SearchInterceptor; let mockCoreSetup: MockedKeys; @@ -53,8 +54,8 @@ describe('SearchInterceptor', () => { expect(result).toBe(mockResponse); }); - test('Observable should fail if fetch has an error', async () => { - const mockResponse: any = { result: 500 }; + test('Observable should fail if fetch has an internal error', async () => { + const mockResponse: any = { result: 500, message: 'Internal Error' }; mockCoreSetup.http.fetch.mockRejectedValueOnce(mockResponse); const mockRequest: IEsSearchRequest = { params: {}, @@ -68,64 +69,83 @@ describe('SearchInterceptor', () => { } }); - test('Observable should fail if fetch times out (test merged signal)', async () => { - mockCoreSetup.http.fetch.mockImplementationOnce((options: any) => { - return new Promise((resolve, reject) => { - options.signal.addEventListener('abort', () => { - reject(new AbortError()); - }); - - setTimeout(resolve, 5000); - }); - }); + test('Should throw SearchTimeoutError on server timeout AND show toast', async (done) => { + const mockResponse: any = { + result: 500, + body: { + message: 'Request timed out', + }, + }; + mockCoreSetup.http.fetch.mockRejectedValueOnce(mockResponse); const mockRequest: IEsSearchRequest = { params: {}, }; const response = searchInterceptor.search(mockRequest); - const next = jest.fn(); - const error = (e: any) => { - expect(next).not.toBeCalled(); - expect(e).toBeInstanceOf(AbortError); - }; - response.subscribe({ next, error }); - - jest.advanceTimersByTime(5000); - - await flushPromises(); + try { + await response.toPromise(); + } catch (e) { + expect(e).toBeInstanceOf(SearchTimeoutError); + expect(mockCoreSetup.notifications.toasts.addDanger).toBeCalledTimes(1); + done(); + } }); - test('Should not timeout if requestTimeout is undefined', async () => { - searchInterceptor = new SearchInterceptor({ - startServices: mockCoreSetup.getStartServices(), - uiSettings: mockCoreSetup.uiSettings, - http: mockCoreSetup.http, - toasts: mockCoreSetup.notifications.toasts, - }); - mockCoreSetup.http.fetch.mockImplementationOnce((options: any) => { - return new Promise((resolve, reject) => { - options.signal.addEventListener('abort', () => { - reject(new AbortError()); - }); - - setTimeout(resolve, 5000); - }); - }); + test('Search error should be debounced', async (done) => { + const mockResponse: any = { + result: 500, + body: { + message: 'Request timed out', + }, + }; + mockCoreSetup.http.fetch.mockRejectedValue(mockResponse); const mockRequest: IEsSearchRequest = { params: {}, }; - const response = searchInterceptor.search(mockRequest); + try { + await searchInterceptor.search(mockRequest).toPromise(); + } catch (e) { + expect(e).toBeInstanceOf(SearchTimeoutError); + try { + await searchInterceptor.search(mockRequest).toPromise(); + } catch (e2) { + expect(mockCoreSetup.notifications.toasts.addDanger).toBeCalledTimes(1); + done(); + } + } + }); - expect.assertions(1); - const next = jest.fn(); - const complete = () => { - expect(next).toBeCalled(); + test('Should throw Painless error on server error with OSS format', async (done) => { + const mockResponse: any = { + result: 500, + body: { + attributes: { + error: { + failed_shards: [ + { + reason: { + lang: 'painless', + script_stack: ['a', 'b'], + reason: 'banana', + }, + }, + ], + }, + }, + }, }; - response.subscribe({ next, complete }); - - jest.advanceTimersByTime(5000); + mockCoreSetup.http.fetch.mockRejectedValueOnce(mockResponse); + const mockRequest: IEsSearchRequest = { + params: {}, + }; + const response = searchInterceptor.search(mockRequest); - await flushPromises(); + try { + await response.toPromise(); + } catch (e) { + expect(e).toBeInstanceOf(PainlessError); + done(); + } }); test('Observable should fail if user aborts (test merged signal)', async () => { diff --git a/src/plugins/data/public/search/search_interceptor.ts b/src/plugins/data/public/search/search_interceptor.ts index 888e12a4285b1..2e42635a7f811 100644 --- a/src/plugins/data/public/search/search_interceptor.ts +++ b/src/plugins/data/public/search/search_interceptor.ts @@ -17,29 +17,21 @@ * under the License. */ -import { trimEnd, debounce } from 'lodash'; -import { - BehaviorSubject, - throwError, - timer, - Subscription, - defer, - from, - Observable, - NEVER, -} from 'rxjs'; +import { get, trimEnd, debounce } from 'lodash'; +import { BehaviorSubject, throwError, timer, defer, from, Observable, NEVER } from 'rxjs'; import { catchError, finalize } from 'rxjs/operators'; import { CoreStart, CoreSetup, ToastsSetup } from 'kibana/public'; -import { i18n } from '@kbn/i18n'; import { getCombinedSignal, AbortError, - IEsSearchRequest, - IEsSearchResponse, + IKibanaSearchRequest, + IKibanaSearchResponse, ISearchOptions, ES_SEARCH_STRATEGY, } from '../../common'; import { SearchUsageCollector } from './collectors'; +import { SearchTimeoutError, PainlessError, isPainlessError, TimeoutErrorMode } from './errors'; +import { toMountPoint } from '../../../kibana_react/public'; export interface SearchInterceptorDeps { http: CoreSetup['http']; @@ -62,12 +54,6 @@ export class SearchInterceptor { */ protected pendingCount$ = new BehaviorSubject(0); - /** - * The subscriptions from scheduling the automatic timeout for each request. - * @internal - */ - protected timeoutSubscriptions: Subscription = new Subscription(); - /** * @internal */ @@ -84,14 +70,49 @@ export class SearchInterceptor { }); } + /* + * @returns `TimeoutErrorMode` indicating what action should be taken in case of a request timeout based on license and permissions. + * @internal + */ + protected getTimeoutMode() { + return TimeoutErrorMode.UPGRADE; + } + + /* + * @returns `Error` a search service specific error or the original error, if a specific error can't be recognized. + * @internal + */ + protected handleSearchError( + e: any, + request: IKibanaSearchRequest, + timeoutSignal: AbortSignal, + appAbortSignal?: AbortSignal + ): Error { + if (timeoutSignal.aborted || get(e, 'body.message') === 'Request timed out') { + // Handle a client or a server side timeout + const err = new SearchTimeoutError(e, this.getTimeoutMode()); + + // Show the timeout error here, so that it's shown regardless of how an application chooses to handle errors. + this.showTimeoutError(err); + return err; + } else if (appAbortSignal?.aborted) { + // In the case an application initiated abort, throw the existing AbortError. + return e; + } else if (isPainlessError(e)) { + return new PainlessError(e, request); + } else { + return e; + } + } + /** * @internal */ protected runSearch( - request: IEsSearchRequest, + request: IKibanaSearchRequest, signal: AbortSignal, strategy?: string - ): Observable { + ): Observable { const { id, ...searchRequest } = request; const path = trimEnd(`/internal/search/${strategy || ES_SEARCH_STRATEGY}/${id || ''}`, '/'); const body = JSON.stringify(searchRequest); @@ -105,41 +126,6 @@ export class SearchInterceptor { ); } - /** - * Searches using the given `search` method. Overrides the `AbortSignal` with one that will abort - * either when `cancelPending` is called, when the request times out, or when the original - * `AbortSignal` is aborted. Updates `pendingCount$` when the request is started/finalized. - */ - public search( - request: IEsSearchRequest, - options?: ISearchOptions - ): Observable { - // Defer the following logic until `subscribe` is actually called - return defer(() => { - if (options?.abortSignal?.aborted) { - return throwError(new AbortError()); - } - - const { combinedSignal, cleanup } = this.setupAbortSignal({ - abortSignal: options?.abortSignal, - }); - this.pendingCount$.next(this.pendingCount$.getValue() + 1); - - return this.runSearch(request, combinedSignal, options?.strategy).pipe( - catchError((e: any) => { - if (e.body?.attributes?.error === 'Request timed out') { - this.showTimeoutError(e); - } - return throwError(e); - }), - finalize(() => { - this.pendingCount$.next(this.pendingCount$.getValue() - 1); - cleanup(); - }) - ); - }); - } - /** * @internal */ @@ -156,9 +142,7 @@ export class SearchInterceptor { const timeout$ = timeout ? timer(timeout) : NEVER; const subscription = timeout$.subscribe(() => { timeoutController.abort(); - this.showTimeoutError(new AbortError()); }); - this.timeoutSubscriptions.add(subscription); // Get a combined `AbortSignal` that will be aborted whenever the first of the following occurs: // 1. The user manually aborts (via `cancelPending`) @@ -172,34 +156,95 @@ export class SearchInterceptor { const combinedSignal = getCombinedSignal(signals); const cleanup = () => { - this.timeoutSubscriptions.remove(subscription); + subscription.unsubscribe(); }; combinedSignal.addEventListener('abort', cleanup); return { combinedSignal, + timeoutSignal, cleanup, }; } - // Right now we are debouncing but we will hook this up with background sessions to show only one - // error notification per session. - protected showTimeoutError = debounce( - (e: Error) => { - this.deps.toasts.addError(e, { + /** + * Right now we are throttling but we will hook this up with background sessions to show only one + * error notification per session. + * @internal + */ + private showTimeoutError = debounce( + (e: SearchTimeoutError) => { + this.deps.toasts.addDanger({ title: 'Timed out', - toastMessage: i18n.translate('data.search.upgradeLicense', { - defaultMessage: - 'One or more queries timed out. With our free Basic tier, your queries never time out.', - }), + text: toMountPoint(e.getErrorMessage(this.application)), }); }, - 60000, - { - leading: true, - } + 30000, + { leading: true, trailing: false } ); + + /** + * Searches using the given `search` method. Overrides the `AbortSignal` with one that will abort + * either when `cancelPending` is called, when the request times out, or when the original + * `AbortSignal` is aborted. Updates `pendingCount$` when the request is started/finalized. + * + * @param request + * @options + * @returns `Observalbe` emitting the search response or an error. + */ + public search( + request: IKibanaSearchRequest, + options?: ISearchOptions + ): Observable { + // Defer the following logic until `subscribe` is actually called + return defer(() => { + if (options?.abortSignal?.aborted) { + return throwError(new AbortError()); + } + + const { timeoutSignal, combinedSignal, cleanup } = this.setupAbortSignal({ + abortSignal: options?.abortSignal, + }); + this.pendingCount$.next(this.pendingCount$.getValue() + 1); + + return this.runSearch(request, combinedSignal, options?.strategy).pipe( + catchError((e: any) => { + return throwError( + this.handleSearchError(e, request, timeoutSignal, options?.abortSignal) + ); + }), + finalize(() => { + this.pendingCount$.next(this.pendingCount$.getValue() - 1); + cleanup(); + }) + ); + }); + } + + /* + * + */ + public showError(e: Error) { + if (e instanceof AbortError) return; + + if (e instanceof SearchTimeoutError) { + // The SearchTimeoutError is shown by the interceptor in getSearchError (regardless of how the app chooses to handle errors) + return; + } + + if (e instanceof PainlessError) { + this.deps.toasts.addDanger({ + title: 'Search Error', + text: toMountPoint(e.getErrorMessage(this.application)), + }); + return; + } + + this.deps.toasts.addError(e, { + title: 'Search Error', + }); + } } export type ISearchInterceptor = PublicMethodsOf; diff --git a/src/plugins/data/public/search/search_service.test.ts b/src/plugins/data/public/search/search_service.test.ts index 738f1e8ffbca0..b59fa6fa16bf6 100644 --- a/src/plugins/data/public/search/search_service.test.ts +++ b/src/plugins/data/public/search/search_service.test.ts @@ -26,11 +26,15 @@ describe('Search service', () => { let searchService: SearchService; let mockCoreSetup: MockedKeys; let mockCoreStart: MockedKeys; + const initializerContext = coreMock.createPluginInitializerContext(); + initializerContext.config.get = jest.fn().mockReturnValue({ + search: { aggs: { shardDelay: { enabled: false } } }, + }); beforeEach(() => { - searchService = new SearchService(); mockCoreSetup = coreMock.createSetup(); mockCoreStart = coreMock.createStart(); + searchService = new SearchService(initializerContext); }); describe('setup()', () => { @@ -48,6 +52,7 @@ describe('Search service', () => { describe('start()', () => { it('exposes proper contract', async () => { const start = searchService.start(mockCoreStart, { + fieldFormats: {}, indexPatterns: {}, } as any); expect(start).toHaveProperty('aggs'); diff --git a/src/plugins/data/public/search/search_service.ts b/src/plugins/data/public/search/search_service.ts index c41e1f78ee74e..2d582b30bcd14 100644 --- a/src/plugins/data/public/search/search_service.ts +++ b/src/plugins/data/public/search/search_service.ts @@ -17,21 +17,35 @@ * under the License. */ -import { Plugin, CoreSetup, CoreStart } from 'src/core/public'; +import { Plugin, CoreSetup, CoreStart, PluginInitializerContext } from 'src/core/public'; import { BehaviorSubject } from 'rxjs'; import { ISearchSetup, ISearchStart, SearchEnhancements } from './types'; import { handleResponse } from './fetch'; -import { getCallMsearch } from './legacy/call_msearch'; -import { createSearchSource, SearchSource, SearchSourceDependencies } from './search_source'; +import { + IEsSearchRequest, + IEsSearchResponse, + IKibanaSearchRequest, + IKibanaSearchResponse, + ISearchGeneric, + ISearchOptions, + SearchSourceService, + SearchSourceDependencies, +} from '../../common/search'; +import { getCallMsearch } from './legacy'; import { AggsService, AggsStartDependencies } from './aggs'; import { IndexPatternsContract } from '../index_patterns/index_patterns'; import { ISearchInterceptor, SearchInterceptor } from './search_interceptor'; -import { ISearchGeneric } from './types'; import { SearchUsageCollector, createUsageCollector } from './collectors'; import { UsageCollectionSetup } from '../../../usage_collection/public'; import { esdsl, esRawResponse } from './expressions'; import { ExpressionsSetup } from '../../../expressions/public'; +import { ConfigSchema } from '../../config'; +import { + SHARD_DELAY_AGG_NAME, + getShardDelayBucketAgg, +} from '../../common/search/aggs/buckets/shard_delay'; +import { aggShardDelay } from '../../common/search/aggs/buckets/shard_delay_fn'; /** @internal */ export interface SearchServiceSetupDependencies { @@ -47,9 +61,12 @@ export interface SearchServiceStartDependencies { export class SearchService implements Plugin { private readonly aggsService = new AggsService(); + private readonly searchSourceService = new SearchSourceService(); private searchInterceptor!: ISearchInterceptor; private usageCollector?: SearchUsageCollector; + constructor(private initializerContext: PluginInitializerContext) {} + public setup( { http, getStartServices, notifications, uiSettings }: CoreSetup, { expressions, usageCollection }: SearchServiceSetupDependencies @@ -71,11 +88,18 @@ export class SearchService implements Plugin { expressions.registerFunction(esdsl); expressions.registerType(esRawResponse); + const aggs = this.aggsService.setup({ + registerFunction: expressions.registerFunction, + uiSettings, + }); + + if (this.initializerContext.config.get().search.aggs.shardDelay.enabled) { + aggs.types.registerBucket(SHARD_DELAY_AGG_NAME, getShardDelayBucketAgg); + expressions.registerFunction(aggShardDelay); + } + return { - aggs: this.aggsService.setup({ - registerFunction: expressions.registerFunction, - uiSettings, - }), + aggs, usageCollector: this.usageCollector!, __enhance: (enhancements: SearchEnhancements) => { this.searchInterceptor = enhancements.searchInterceptor; @@ -96,7 +120,15 @@ export class SearchService implements Plugin { const searchSourceDependencies: SearchSourceDependencies = { getConfig: uiSettings.get.bind(uiSettings), - search, + search: < + SearchStrategyRequest extends IKibanaSearchRequest = IEsSearchRequest, + SearchStrategyResponse extends IKibanaSearchResponse = IEsSearchResponse + >( + request: SearchStrategyRequest, + options: ISearchOptions + ) => { + return search(request, options).toPromise() as Promise; + }, onResponse: handleResponse, legacy: { callMsearch: getCallMsearch({ http }), @@ -107,22 +139,15 @@ export class SearchService implements Plugin { return { aggs: this.aggsService.start({ fieldFormats, uiSettings }), search, - searchSource: { - /** - * creates searchsource based on serialized search source fields - */ - create: createSearchSource(indexPatterns, searchSourceDependencies), - /** - * creates an enpty search source - */ - createEmpty: () => { - return new SearchSource({}, searchSourceDependencies); - }, + showError: (e: Error) => { + this.searchInterceptor.showError(e); }, + searchSource: this.searchSourceService.start(indexPatterns, searchSourceDependencies), }; } public stop() { this.aggsService.stop(); + this.searchSourceService.stop(); } } diff --git a/src/plugins/data/public/search/search_source/index.ts b/src/plugins/data/public/search/search_source/index.ts deleted file mode 100644 index 48c0338f7e981..0000000000000 --- a/src/plugins/data/public/search/search_source/index.ts +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -export { SearchSource, ISearchSource, SearchSourceDependencies } from './search_source'; -export { createSearchSource } from './create_search_source'; -export { SortDirection, EsQuerySortValue, SearchSourceFields } from './types'; -export { injectReferences } from './inject_references'; -export { extractReferences } from './extract_references'; -export { parseSearchSourceJSON } from './parse_json'; diff --git a/src/plugins/data/public/search/search_source/mocks.ts b/src/plugins/data/public/search/search_source/mocks.ts index f582861e37c15..bc382f09947c5 100644 --- a/src/plugins/data/public/search/search_source/mocks.ts +++ b/src/plugins/data/public/search/search_source/mocks.ts @@ -17,46 +17,13 @@ * under the License. */ -import { BehaviorSubject } from 'rxjs'; -import { uiSettingsServiceMock } from '../../../../../core/public/mocks'; +import { searchSourceCommonMock } from '../../../common/search/search_source/mocks'; +import { ISearchStart } from '../types'; -import { ISearchSource, SearchSource } from './search_source'; -import { SearchSourceFields } from './types'; - -export const searchSourceInstanceMock: MockedKeys = { - setPreferredSearchStrategyId: jest.fn(), - setFields: jest.fn().mockReturnThis(), - setField: jest.fn().mockReturnThis(), - getId: jest.fn(), - getFields: jest.fn(), - getField: jest.fn(), - getOwnField: jest.fn(), - create: jest.fn().mockReturnThis(), - createCopy: jest.fn().mockReturnThis(), - createChild: jest.fn().mockReturnThis(), - setParent: jest.fn(), - getParent: jest.fn().mockReturnThis(), - fetch: jest.fn().mockResolvedValue({}), - onRequestStart: jest.fn(), - getSearchRequestBody: jest.fn(), - destroy: jest.fn(), - history: [], - getSerializedFields: jest.fn(), - serialize: jest.fn(), -}; +function createStartContract(): jest.Mocked { + return searchSourceCommonMock; +} export const searchSourceMock = { - create: jest.fn().mockReturnValue(searchSourceInstanceMock), - createEmpty: jest.fn().mockReturnValue(searchSourceInstanceMock), + createStartContract, }; - -export const createSearchSourceMock = (fields?: SearchSourceFields) => - new SearchSource(fields, { - getConfig: uiSettingsServiceMock.createStartContract().get, - search: jest.fn(), - onResponse: jest.fn().mockImplementation((req, res) => res), - legacy: { - callMsearch: jest.fn(), - loadingCount$: new BehaviorSubject(0), - }, - }); diff --git a/src/plugins/data/public/search/search_source/types.ts b/src/plugins/data/public/search/search_source/types.ts deleted file mode 100644 index 0882aa9a2ceec..0000000000000 --- a/src/plugins/data/public/search/search_source/types.ts +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -import { NameList } from 'elasticsearch'; -import { IndexPattern, Query } from '../..'; -import { Filter } from '../../../common'; - -export type EsQuerySearchAfter = [string | number, string | number]; - -export enum SortDirection { - asc = 'asc', - desc = 'desc', -} - -export interface SortDirectionNumeric { - order: SortDirection; - numeric_type?: 'double' | 'long' | 'date' | 'date_nanos'; -} - -export type EsQuerySortValue = Record; - -/** - * search source fields - */ -export interface SearchSourceFields { - type?: string; - /** - * {@link Query} - */ - query?: Query; - /** - * {@link Filter} - */ - filter?: Filter[] | Filter | (() => Filter[] | Filter | undefined); - /** - * {@link EsQuerySortValue} - */ - sort?: EsQuerySortValue | EsQuerySortValue[]; - highlight?: any; - highlightAll?: boolean; - /** - * {@link AggConfigs} - */ - aggs?: any; - from?: number; - size?: number; - source?: NameList; - version?: boolean; - fields?: NameList; - /** - * {@link IndexPatternService} - */ - index?: IndexPattern; - searchAfter?: EsQuerySearchAfter; - timeout?: string; - terminate_after?: number; -} - -export interface SearchSourceOptions { - callParentStartHandlers?: boolean; -} - -export { ISearchSource } from './search_source'; - -export interface SortOptions { - mode?: 'min' | 'max' | 'sum' | 'avg' | 'median'; - type?: 'double' | 'long' | 'date' | 'date_nanos'; - nested?: object; - unmapped_type?: string; - distance_type?: 'arc' | 'plane'; - unit?: string; - ignore_unmapped?: boolean; - _script?: object; -} - -export interface Request { - docvalue_fields: string[]; - _source: unknown; - query: unknown; - script_fields: unknown; - sort: unknown; - stored_fields: string[]; -} - -export interface ResponseWithShardFailure { - _shards: { - failed: number; - failures: ShardFailure[]; - skipped: number; - successful: number; - total: number; - }; -} - -export interface ShardFailure { - index: string; - node: string; - reason: { - caused_by: { - reason: string; - type: string; - }; - reason: string; - lang?: string; - script?: string; - script_stack?: string[]; - type: string; - }; - shard: number; -} diff --git a/src/plugins/data/public/search/types.ts b/src/plugins/data/public/search/types.ts index 83a542269046f..85ef7aa4d97cb 100644 --- a/src/plugins/data/public/search/types.ts +++ b/src/plugins/data/public/search/types.ts @@ -17,38 +17,20 @@ * under the License. */ -import { Observable } from 'rxjs'; import { PackageInfo } from 'kibana/server'; import { ISearchInterceptor } from './search_interceptor'; -import { ISearchSource, SearchSourceFields } from './search_source'; import { SearchUsageCollector } from './collectors'; import { AggsSetup, AggsSetupDependencies, AggsStartDependencies, AggsStart } from './aggs'; -import { - IKibanaSearchRequest, - IKibanaSearchResponse, - IEsSearchRequest, - IEsSearchResponse, - ISearchOptions, -} from '../../common/search'; +import { ISearchGeneric, ISearchStartSearchSource } from '../../common/search'; import { IndexPatternsContract } from '../../common/index_patterns/index_patterns'; import { UsageCollectionSetup } from '../../../usage_collection/public'; -export type ISearch = ( - request: IKibanaSearchRequest, - options?: ISearchOptions -) => Observable; - -export type ISearchGeneric = < - SearchStrategyRequest extends IEsSearchRequest = IEsSearchRequest, - SearchStrategyResponse extends IEsSearchResponse = IEsSearchResponse ->( - request: SearchStrategyRequest, - options?: ISearchOptions -) => Observable; +export { ISearchStartSearchSource }; export interface SearchEnhancements { searchInterceptor: ISearchInterceptor; } + /** * The setup contract exposed by the Search plugin exposes the search strategy extension * point. @@ -62,21 +44,6 @@ export interface ISearchSetup { __enhance: (enhancements: SearchEnhancements) => void; } -/** - * high level search service - * @public - */ -export interface ISearchStartSearchSource { - /** - * creates {@link SearchSource} based on provided serialized {@link SearchSourceFields} - * @param fields - */ - create: (fields?: SearchSourceFields) => Promise; - /** - * creates empty {@link SearchSource} - */ - createEmpty: () => ISearchSource; -} /** * search service * @public @@ -93,6 +60,8 @@ export interface ISearchStart { * {@link ISearchGeneric} */ search: ISearchGeneric; + + showError: (e: Error) => void; /** * high level search * {@link ISearchStartSearchSource} diff --git a/src/plugins/data/public/test_utils.ts b/src/plugins/data/public/test_utils.ts index f04b20e96fa1d..03dc572d0bc80 100644 --- a/src/plugins/data/public/test_utils.ts +++ b/src/plugins/data/public/test_utils.ts @@ -18,3 +18,4 @@ */ export { getFieldFormatsRegistry } from './field_formats/field_formats_registry.stub'; +export { getStubIndexPattern, StubIndexPattern } from './index_patterns/index_pattern.stub'; diff --git a/src/plugins/data/public/types.ts b/src/plugins/data/public/types.ts index 7b5d79aff24ef..21a03a49fe058 100644 --- a/src/plugins/data/public/types.ts +++ b/src/plugins/data/public/types.ts @@ -27,9 +27,8 @@ import { FieldFormatsSetup, FieldFormatsStart } from './field_formats'; import { createFiltersFromRangeSelectAction, createFiltersFromValueClickAction } from './actions'; import { ISearchSetup, ISearchStart, SearchEnhancements } from './search'; import { QuerySetup, QueryStart } from './query'; -import { IndexPatternSelectProps } from './ui/index_pattern_select'; import { IndexPatternsContract } from './index_patterns'; -import { StatefulSearchBarProps } from './ui/search_bar/create_search_bar'; +import { IndexPatternSelectProps, StatefulSearchBarProps } from './ui'; import { UsageCollectionSetup } from '../../usage_collection/public'; export interface DataPublicPluginEnhancements { diff --git a/src/plugins/data/public/ui/apply_filters/apply_filter_popover_content.tsx b/src/plugins/data/public/ui/apply_filters/apply_filter_popover_content.tsx index 33928e4f87afc..d7fb6e4c64922 100644 --- a/src/plugins/data/public/ui/apply_filters/apply_filter_popover_content.tsx +++ b/src/plugins/data/public/ui/apply_filters/apply_filter_popover_content.tsx @@ -46,7 +46,9 @@ interface State { isFilterSelected: boolean[]; } -export class ApplyFiltersPopoverContent extends Component { +// Needed for React.lazy +// eslint-disable-next-line import/no-default-export +export default class ApplyFiltersPopoverContent extends Component { public static defaultProps = { filters: [], }; diff --git a/src/plugins/data/public/ui/apply_filters/apply_filters_popover.tsx b/src/plugins/data/public/ui/apply_filters/apply_filters_popover.tsx index cffcad66cbc24..80e1a26163b72 100644 --- a/src/plugins/data/public/ui/apply_filters/apply_filters_popover.tsx +++ b/src/plugins/data/public/ui/apply_filters/apply_filters_popover.tsx @@ -18,12 +18,20 @@ */ import React from 'react'; -import { ApplyFiltersPopoverContent } from './apply_filter_popover_content'; +import { EuiLoadingContent, EuiDelayRender } from '@elastic/eui'; import { IIndexPattern, Filter } from '../..'; type CancelFnType = () => void; type SubmitFnType = (filters: Filter[]) => void; +const Fallback = () => ( + + + +); + +const LazyApplyFiltersPopoverContent = React.lazy(() => import('./apply_filter_popover_content')); + export const applyFiltersPopover = ( filters: Filter[], indexPatterns: IIndexPattern[], @@ -31,11 +39,13 @@ export const applyFiltersPopover = ( onSubmit: SubmitFnType ) => { return ( - + }> + + ); }; diff --git a/src/plugins/data/public/ui/filter_bar/_global_filter_item.scss b/src/plugins/data/public/ui/filter_bar/_global_filter_item.scss index 73ec14de82b43..b79b7c038f9cc 100644 --- a/src/plugins/data/public/ui/filter_bar/_global_filter_item.scss +++ b/src/plugins/data/public/ui/filter_bar/_global_filter_item.scss @@ -33,8 +33,6 @@ } .globalFilterItem-isError, .globalFilterItem-isWarning { - text-decoration: none; - .globalFilterLabel__value { font-weight: $euiFontWeightBold; } diff --git a/src/plugins/data/public/ui/filter_bar/filter_editor/index.tsx b/src/plugins/data/public/ui/filter_bar/filter_editor/index.tsx index 0e2bcc7581950..7bd4facc9caa9 100644 --- a/src/plugins/data/public/ui/filter_bar/filter_editor/index.tsx +++ b/src/plugins/data/public/ui/filter_bar/filter_editor/index.tsx @@ -106,7 +106,11 @@ class FilterEditorUI extends Component { - + {this.state.isCustomEditorOpen ? ( { - geo.coordinates in US - -`; - -exports[`negated alias 1`] = ` - - - NOT - - geo.coordinates in US - -`; diff --git a/src/plugins/data/public/ui/filter_bar/filter_editor/lib/filter_label.test.js b/src/plugins/data/public/ui/filter_bar/filter_editor/lib/filter_label.test.js deleted file mode 100644 index 55df544ad010b..0000000000000 --- a/src/plugins/data/public/ui/filter_bar/filter_editor/lib/filter_label.test.js +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import React from 'react'; -import { FilterLabel } from './filter_label'; -import { shallow } from 'enzyme'; -import { phraseFilter } from '../../../../stubs'; - -test('alias', () => { - const filter = { - ...phraseFilter, - meta: { - ...phraseFilter.meta, - alias: 'geo.coordinates in US', - }, - }; - const component = shallow(); - expect(component).toMatchSnapshot(); -}); - -test('negated alias', () => { - const filter = { - ...phraseFilter, - meta: { - ...phraseFilter.meta, - alias: 'geo.coordinates in US', - negate: true, - }, - }; - const component = shallow(); - expect(component).toMatchSnapshot(); -}); diff --git a/src/plugins/data/public/ui/filter_bar/filter_editor/lib/filter_label.test.tsx b/src/plugins/data/public/ui/filter_bar/filter_editor/lib/filter_label.test.tsx new file mode 100644 index 0000000000000..7065a05193e6d --- /dev/null +++ b/src/plugins/data/public/ui/filter_bar/filter_editor/lib/filter_label.test.tsx @@ -0,0 +1,154 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React from 'react'; +import FilterLabel from './filter_label'; +import { render } from '@testing-library/react'; +import { phraseFilter } from '../../../../stubs'; + +test('alias', () => { + const filter = { + ...phraseFilter, + meta: { + ...phraseFilter.meta, + alias: 'geo.coordinates in US', + }, + }; + const { container } = render(); + expect(container).toMatchInlineSnapshot(` +
+ + geo.coordinates in US +
+ `); +}); + +test('negated alias', () => { + const filter = { + ...phraseFilter, + meta: { + ...phraseFilter.meta, + alias: 'geo.coordinates in US', + negate: true, + }, + }; + const { container } = render(); + expect(container).toMatchInlineSnapshot(` +
+ + NOT + + geo.coordinates in US +
+ `); +}); + +test('alias with warning status', () => { + const filter = { + ...phraseFilter, + meta: { + ...phraseFilter.meta, + alias: 'geo.coordinates in US', + negate: true, + }, + }; + const { container } = render( + + ); + expect(container).toMatchInlineSnapshot(` +
+ + NOT + + geo.coordinates in US + : + + Warning + +
+ `); +}); + +test('alias with error status', () => { + const filter = { + ...phraseFilter, + meta: { + ...phraseFilter.meta, + alias: 'geo.coordinates in US', + negate: true, + }, + }; + const { container } = render( + + ); + expect(container).toMatchInlineSnapshot(` +
+ + NOT + + geo.coordinates in US + : + + Error + +
+ `); +}); + +test('warning', () => { + const { container } = render(); + expect(container).toMatchInlineSnapshot(` +
+ + machine.os + : + + Warning + +
+ `); +}); + +test('error', () => { + const { container } = render(); + expect(container).toMatchInlineSnapshot(` +
+ + machine.os + : + + Error + +
+ `); +}); diff --git a/src/plugins/data/public/ui/filter_bar/filter_editor/lib/filter_label.tsx b/src/plugins/data/public/ui/filter_bar/filter_editor/lib/filter_label.tsx index 070631354d8b8..c27d7422dc911 100644 --- a/src/plugins/data/public/ui/filter_bar/filter_editor/lib/filter_label.tsx +++ b/src/plugins/data/public/ui/filter_bar/filter_editor/lib/filter_label.tsx @@ -22,13 +22,18 @@ import { EuiTextColor } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { existsOperator, isOneOfOperator } from './filter_operators'; import { Filter, FILTERS } from '../../../../../common'; +import type { FilterLabelStatus } from '../../filter_item'; -interface Props { +// @internal +export interface FilterLabelProps { filter: Filter; valueLabel?: string; + filterLabelStatus?: FilterLabelStatus; } -export function FilterLabel({ filter, valueLabel }: Props) { +// Needed for React.lazy +// eslint-disable-next-line import/no-default-export +export default function FilterLabel({ filter, valueLabel, filterLabelStatus }: FilterLabelProps) { const prefixText = filter.meta.negate ? ` ${i18n.translate('data.filter.filterBar.negatedFilterPrefix', { defaultMessage: 'NOT ', @@ -50,6 +55,7 @@ export function FilterLabel({ filter, valueLabel }: Props) { {prefix} {filter.meta.alias} + {filterLabelStatus && <>: {getValue(valueLabel)}} ); } diff --git a/src/plugins/data/public/ui/filter_bar/filter_item.tsx b/src/plugins/data/public/ui/filter_bar/filter_item.tsx index 078fc8c9e1a8f..cbff20115f8ea 100644 --- a/src/plugins/data/public/ui/filter_bar/filter_item.tsx +++ b/src/plugins/data/public/ui/filter_bar/filter_item.tsx @@ -49,7 +49,7 @@ interface Props { interface LabelOptions { title: string; - status: string; + status: FilterLabelStatus; message?: string; } @@ -57,6 +57,11 @@ const FILTER_ITEM_OK = ''; const FILTER_ITEM_WARNING = 'warn'; const FILTER_ITEM_ERROR = 'error'; +export type FilterLabelStatus = + | typeof FILTER_ITEM_OK + | typeof FILTER_ITEM_WARNING + | typeof FILTER_ITEM_ERROR; + export function FilterItem(props: Props) { const [isPopoverOpen, setIsPopoverOpen] = useState(false); const [indexPatternExists, setIndexPatternExists] = useState(undefined); @@ -260,7 +265,7 @@ export function FilterItem(props: Props) { } function getValueLabel(): LabelOptions { - const label = { + const label: LabelOptions = { title: '', message: '', status: FILTER_ITEM_OK, @@ -326,6 +331,7 @@ export function FilterItem(props: Props) { props.onRemove()} diff --git a/src/plugins/data/public/ui/filter_bar/filter_view/index.tsx b/src/plugins/data/public/ui/filter_bar/filter_view/index.tsx index f9328875cc910..d61b722fd1b87 100644 --- a/src/plugins/data/public/ui/filter_bar/filter_view/index.tsx +++ b/src/plugins/data/public/ui/filter_bar/filter_view/index.tsx @@ -20,12 +20,14 @@ import { EuiBadge, useInnerText } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import React, { FC } from 'react'; -import { FilterLabel } from '../filter_editor/lib/filter_label'; +import { FilterLabel } from '../'; import { Filter, isFilterPinned } from '../../../../common'; +import type { FilterLabelStatus } from '../filter_item'; interface Props { filter: Filter; valueLabel: string; + filterLabelStatus: FilterLabelStatus; errorMessage?: string; [propName: string]: any; } @@ -36,6 +38,7 @@ export const FilterView: FC = ({ onClick, valueLabel, errorMessage, + filterLabelStatus, ...rest }: Props) => { const [ref, innerText] = useInnerText(); @@ -65,7 +68,7 @@ export const FilterView: FC = ({ iconType="cross" iconSide="right" closeButtonProps={{ - // Removing tab focus on close button because the same option can be optained through the context menu + // Removing tab focus on close button because the same option can be obtained through the context menu // Also, we may want to add a `DEL` keyboard press functionality tabIndex: -1, }} @@ -80,7 +83,11 @@ export const FilterView: FC = ({ {...rest} > - + ); diff --git a/src/plugins/data/public/ui/filter_bar/index.ts b/src/plugins/data/public/ui/filter_bar/index.ts deleted file mode 100644 index b975317d46630..0000000000000 --- a/src/plugins/data/public/ui/filter_bar/index.ts +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -export { FilterBar } from './filter_bar'; -export { FilterLabel } from './filter_editor/lib/filter_label'; diff --git a/src/plugins/data/public/ui/filter_bar/index.tsx b/src/plugins/data/public/ui/filter_bar/index.tsx new file mode 100644 index 0000000000000..b4296bb6615d4 --- /dev/null +++ b/src/plugins/data/public/ui/filter_bar/index.tsx @@ -0,0 +1,35 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React from 'react'; +import { EuiLoadingContent, EuiDelayRender } from '@elastic/eui'; +import type { FilterLabelProps } from './filter_editor/lib/filter_label'; + +const Fallback = () => ( + + + +); + +const LazyFilterLabel = React.lazy(() => import('./filter_editor/lib/filter_label')); +export const FilterLabel = (props: FilterLabelProps) => ( + }> + + +); diff --git a/src/plugins/data/public/ui/index.ts b/src/plugins/data/public/ui/index.ts index 35b1bc50ddb1e..87f515afbee41 100644 --- a/src/plugins/data/public/ui/index.ts +++ b/src/plugins/data/public/ui/index.ts @@ -17,17 +17,8 @@ * under the License. */ -export { SuggestionsComponent } from './typeahead'; -export { IndexPatternSelect } from './index_pattern_select'; -export { FilterBar } from './filter_bar'; -export { QueryStringInput } from './query_string_input/query_string_input'; +export { IndexPatternSelectProps } from './index_pattern_select'; +export { FilterLabel } from './filter_bar'; +export { QueryStringInput, QueryStringInputProps } from './query_string_input'; export { SearchBar, SearchBarProps, StatefulSearchBarProps } from './search_bar'; - -// @internal -export { ShardFailureOpenModalButton, ShardFailureRequest } from './shard_failure_modal'; - -// @internal -export { SavedQueryManagementComponent } from './saved_query_management'; - -// @internal -export { SaveQueryForm, SavedQueryMeta } from './saved_query_form'; +export { SuggestionsComponent } from './typeahead'; diff --git a/src/plugins/data/public/ui/index_pattern_select/create_index_pattern_select.tsx b/src/plugins/data/public/ui/index_pattern_select/create_index_pattern_select.tsx new file mode 100644 index 0000000000000..a48c2dabf1506 --- /dev/null +++ b/src/plugins/data/public/ui/index_pattern_select/create_index_pattern_select.tsx @@ -0,0 +1,31 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import _ from 'lodash'; +import React from 'react'; + +import { SavedObjectsClientContract } from 'src/core/public'; +import { IndexPatternSelect, IndexPatternSelectProps } from './'; + +// Takes in stateful runtime dependencies and pre-wires them to the component +export function createIndexPatternSelect(savedObjectsClient: SavedObjectsClientContract) { + return (props: IndexPatternSelectProps) => ( + + ); +} diff --git a/src/plugins/data/public/ui/index_pattern_select/index.ts b/src/plugins/data/public/ui/index_pattern_select/index.ts deleted file mode 100644 index 30dcb43557507..0000000000000 --- a/src/plugins/data/public/ui/index_pattern_select/index.ts +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -export * from './index_pattern_select'; diff --git a/src/plugins/data/public/ui/index_pattern_select/index.tsx b/src/plugins/data/public/ui/index_pattern_select/index.tsx new file mode 100644 index 0000000000000..f0db37eb963fd --- /dev/null +++ b/src/plugins/data/public/ui/index_pattern_select/index.tsx @@ -0,0 +1,38 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React from 'react'; +import { EuiLoadingContent, EuiDelayRender } from '@elastic/eui'; +import type { IndexPatternSelectInternalProps } from './index_pattern_select'; + +const Fallback = () => ( + + + +); + +const LazyIndexPatternSelect = React.lazy(() => import('./index_pattern_select')); +export const IndexPatternSelect = (props: IndexPatternSelectInternalProps) => ( + }> + + +); + +export * from './create_index_pattern_select'; +export type { IndexPatternSelectProps } from './index_pattern_select'; diff --git a/src/plugins/data/public/ui/index_pattern_select/index_pattern_select.tsx b/src/plugins/data/public/ui/index_pattern_select/index_pattern_select.tsx index f187dcb804c79..1e0e8934778ad 100644 --- a/src/plugins/data/public/ui/index_pattern_select/index_pattern_select.tsx +++ b/src/plugins/data/public/ui/index_pattern_select/index_pattern_select.tsx @@ -23,17 +23,23 @@ import React, { Component } from 'react'; import { Required } from '@kbn/utility-types'; import { EuiComboBox, EuiComboBoxProps } from '@elastic/eui'; -import { SavedObjectsClientContract, SimpleSavedObject } from '../../../../../core/public'; +import { SavedObjectsClientContract, SimpleSavedObject } from 'src/core/public'; import { getTitle } from '../../../common/index_patterns/lib'; export type IndexPatternSelectProps = Required< - // Omit, 'isLoading' | 'onSearchChange' | 'options' | 'selectedOptions' | 'append' | 'prepend' | 'sortMatchesBy'>, - Omit, 'isLoading' | 'onSearchChange' | 'options' | 'selectedOptions'>, - 'onChange' | 'placeholder' + Omit< + EuiComboBoxProps, + 'isLoading' | 'onSearchChange' | 'options' | 'selectedOptions' | 'onChange' + >, + 'placeholder' > & { + onChange: (indexPatternId?: string) => void; indexPatternId: string; fieldTypes?: string[]; onNoIndexPatterns?: () => void; +}; + +export type IndexPatternSelectInternalProps = IndexPatternSelectProps & { savedObjectsClient: SavedObjectsClientContract; }; @@ -59,18 +65,13 @@ const getIndexPatterns = async ( return resp.savedObjects; }; -// Takes in stateful runtime dependencies and pre-wires them to the component -export function createIndexPatternSelect(savedObjectsClient: SavedObjectsClientContract) { - return (props: Omit) => ( - - ); -} - -export class IndexPatternSelect extends Component { +// Needed for React.lazy +// eslint-disable-next-line import/no-default-export +export default class IndexPatternSelect extends Component { private isMounted: boolean = false; state: IndexPatternSelectState; - constructor(props: IndexPatternSelectProps) { + constructor(props: IndexPatternSelectInternalProps) { super(props); this.state = { @@ -92,7 +93,7 @@ export class IndexPatternSelect extends Component { this.fetchSelectedIndexPattern(this.props.indexPatternId); } - UNSAFE_componentWillReceiveProps(nextProps: IndexPatternSelectProps) { + UNSAFE_componentWillReceiveProps(nextProps: IndexPatternSelectInternalProps) { if (nextProps.indexPatternId !== this.props.indexPatternId) { this.fetchSelectedIndexPattern(nextProps.indexPatternId); } diff --git a/src/plugins/data/public/ui/query_string_input/index.tsx b/src/plugins/data/public/ui/query_string_input/index.tsx new file mode 100644 index 0000000000000..5bc5bd5097969 --- /dev/null +++ b/src/plugins/data/public/ui/query_string_input/index.tsx @@ -0,0 +1,45 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React from 'react'; +import { EuiLoadingContent, EuiDelayRender } from '@elastic/eui'; +import { withKibana } from '../../../../kibana_react/public'; +import type { QueryBarTopRowProps } from './query_bar_top_row'; +import type { QueryStringInputProps } from './query_string_input'; + +const Fallback = () => ( + + + +); + +const LazyQueryBarTopRow = React.lazy(() => import('./query_bar_top_row')); +export const QueryBarTopRow = (props: QueryBarTopRowProps) => ( + }> + + +); + +const LazyQueryStringInputUI = withKibana(React.lazy(() => import('./query_string_input'))); +export const QueryStringInput = (props: QueryStringInputProps) => ( + }> + + +); +export type { QueryStringInputProps }; diff --git a/src/plugins/data/public/ui/query_string_input/no_data_popover.tsx b/src/plugins/data/public/ui/query_string_input/no_data_popover.tsx index 561c33519f96f..7d5282a0545bc 100644 --- a/src/plugins/data/public/ui/query_string_input/no_data_popover.tsx +++ b/src/plugins/data/public/ui/query_string_input/no_data_popover.tsx @@ -63,6 +63,7 @@ export function NoDataPopover({ } minWidth={300} anchorPosition="downCenter" + anchorClassName="eui-displayBlock" step={1} stepsTotal={1} isStepOpen={noDataPopoverVisible} diff --git a/src/plugins/data/public/ui/query_string_input/query_bar_top_row.test.tsx b/src/plugins/data/public/ui/query_string_input/query_bar_top_row.test.tsx index 879ff6708068e..960be8ba99f08 100644 --- a/src/plugins/data/public/ui/query_string_input/query_bar_top_row.test.tsx +++ b/src/plugins/data/public/ui/query_string_input/query_bar_top_row.test.tsx @@ -21,7 +21,10 @@ import { mockPersistedLogFactory } from './query_string_input.test.mocks'; import React from 'react'; import { mount } from 'enzyme'; -import { QueryBarTopRow } from './query_bar_top_row'; +import { waitFor } from '@testing-library/dom'; +import { render } from '@testing-library/react'; + +import { QueryBarTopRow } from './'; import { coreMock } from '../../../../../core/public/mocks'; import { dataPluginMock } from '../../mocks'; @@ -120,8 +123,8 @@ describe('QueryBarTopRowTopRow', () => { jest.clearAllMocks(); }); - it('Should render query and time picker', () => { - const component = mount( + it('Should render query and time picker', async () => { + const { getByText, getByTestId } = render( wrapQueryBarTopRowInContext({ query: kqlQuery, screenTitle: 'Another Screen', @@ -131,8 +134,8 @@ describe('QueryBarTopRowTopRow', () => { }) ); - expect(component.find(QUERY_INPUT_SELECTOR).length).toBe(1); - expect(component.find(TIMEPICKER_SELECTOR).length).toBe(1); + await waitFor(() => getByText(kqlQuery.query)); + await waitFor(() => getByTestId('superDatePickerShowDatesButton')); }); it('Should create a unique PersistedLog based on the appName and query language', () => { diff --git a/src/plugins/data/public/ui/query_string_input/query_bar_top_row.tsx b/src/plugins/data/public/ui/query_string_input/query_bar_top_row.tsx index e5d03e2a774f1..e01fbedbe38de 100644 --- a/src/plugins/data/public/ui/query_string_input/query_bar_top_row.tsx +++ b/src/plugins/data/public/ui/query_string_input/query_bar_top_row.tsx @@ -37,12 +37,13 @@ import { FormattedMessage } from '@kbn/i18n/react'; import { Toast } from 'src/core/public'; import { IDataPluginServices, IIndexPattern, TimeRange, TimeHistoryContract, Query } from '../..'; import { useKibana, toMountPoint } from '../../../../kibana_react/public'; -import { QueryStringInput } from './query_string_input'; +import { QueryStringInput } from './'; import { doesKueryExpressionHaveLuceneSyntaxError, UI_SETTINGS } from '../../../common'; import { PersistedLog, getQueryLog } from '../../query'; import { NoDataPopover } from './no_data_popover'; -interface Props { +// @internal +export interface QueryBarTopRowProps { query?: Query; onSubmit: (payload: { dateRange: TimeRange; query?: Query }) => void; onChange: (payload: { dateRange: TimeRange; query?: Query }) => void; @@ -67,7 +68,9 @@ interface Props { indicateNoData?: boolean; } -export function QueryBarTopRow(props: Props) { +// Needed for React.lazy +// eslint-disable-next-line import/no-default-export +export default function QueryBarTopRow(props: QueryBarTopRowProps) { const [isDateRangeInvalid, setIsDateRangeInvalid] = useState(false); const [isQueryInputFocused, setIsQueryInputFocused] = useState(false); diff --git a/src/plugins/data/public/ui/query_string_input/query_string_input.test.tsx b/src/plugins/data/public/ui/query_string_input/query_string_input.test.tsx index bb0a8b848c89e..7d0ad4b3be097 100644 --- a/src/plugins/data/public/ui/query_string_input/query_string_input.test.tsx +++ b/src/plugins/data/public/ui/query_string_input/query_string_input.test.tsx @@ -23,18 +23,24 @@ import { mockPersistedLogFactory, } from './query_string_input.test.mocks'; -import { EuiTextArea } from '@elastic/eui'; import React from 'react'; +import { I18nProvider } from '@kbn/i18n/react'; +import { mount } from 'enzyme'; +import { waitFor } from '@testing-library/dom'; +import { render } from '@testing-library/react'; + +import { EuiTextArea } from '@elastic/eui'; + import { QueryLanguageSwitcher } from './language_switcher'; -import { QueryStringInput, QueryStringInputUI } from './query_string_input'; +import { QueryStringInput } from './'; +import type QueryStringInputUI from './query_string_input'; + import { coreMock } from '../../../../../core/public/mocks'; import { dataPluginMock } from '../../mocks'; -const startMock = coreMock.createStart(); import { stubIndexPatternWithFields } from '../../stubs'; - import { KibanaContextProvider } from 'src/plugins/kibana_react/public'; -import { I18nProvider } from '@kbn/i18n/react'; -import { mount } from 'enzyme'; + +const startMock = coreMock.createStart(); const noop = () => { return; @@ -94,16 +100,17 @@ describe('QueryStringInput', () => { jest.clearAllMocks(); }); - it('Should render the given query', () => { - const component = mount( + it('Should render the given query', async () => { + const { getByText } = render( wrapQueryStringInputInContext({ query: kqlQuery, onSubmit: noop, indexPatterns: [stubIndexPatternWithFields], }) ); - expect(component.find(EuiTextArea).props().value).toBe(kqlQuery.query); - expect(component.find(QueryLanguageSwitcher).prop('language')).toBe(kqlQuery.language); + + await waitFor(() => getByText(kqlQuery.query)); + await waitFor(() => getByText('KQL')); }); it('Should pass the query language to the language switcher', () => { diff --git a/src/plugins/data/public/ui/query_string_input/query_string_input.tsx b/src/plugins/data/public/ui/query_string_input/query_string_input.tsx index 8e1151b387fee..c17872028ea8d 100644 --- a/src/plugins/data/public/ui/query_string_input/query_string_input.tsx +++ b/src/plugins/data/public/ui/query_string_input/query_string_input.tsx @@ -39,15 +39,14 @@ import { Toast } from 'src/core/public'; import { IDataPluginServices, IIndexPattern, Query } from '../..'; import { QuerySuggestion, QuerySuggestionTypes } from '../../autocomplete'; -import { withKibana, KibanaReactContextValue, toMountPoint } from '../../../../kibana_react/public'; +import { KibanaReactContextValue, toMountPoint } from '../../../../kibana_react/public'; import { fetchIndexPatterns } from './fetch_index_patterns'; import { QueryLanguageSwitcher } from './language_switcher'; import { PersistedLog, getQueryLog, matchPairs, toUser, fromUser } from '../../query'; import { SuggestionsListSize } from '../typeahead/suggestions_component'; import { SuggestionsComponent } from '..'; -interface Props { - kibana: KibanaReactContextValue; +export interface QueryStringInputProps { indexPatterns: Array; query: Query; disableAutoFocus?: boolean; @@ -67,6 +66,10 @@ interface Props { isInvalid?: boolean; } +interface Props extends QueryStringInputProps { + kibana: KibanaReactContextValue; +} + interface State { isSuggestionsVisible: boolean; index: number | null; @@ -90,7 +93,9 @@ const KEY_CODES = { END: 35, }; -export class QueryStringInputUI extends Component { +// Needed for React.lazy +// eslint-disable-next-line import/no-default-export +export default class QueryStringInputUI extends Component { public state: State = { isSuggestionsVisible: false, index: null, @@ -442,7 +447,7 @@ export class QueryStringInputUI extends Component { // Send telemetry info every time the user opts in or out of kuery // As a result it is important this function only ever gets called in the // UI component's change handler. - this.services.http.post('/api/kibana/kql_opt_in_telemetry', { + this.services.http.post('/api/kibana/kql_opt_in_stats', { body: JSON.stringify({ opt_in: language === 'kuery' }), }); @@ -543,7 +548,7 @@ export class QueryStringInputUI extends Component { public componentWillUnmount() { if (this.abortController) this.abortController.abort(); - this.updateSuggestions.cancel(); + if (this.updateSuggestions.cancel) this.updateSuggestions.cancel(); this.componentIsUnmounting = true; window.removeEventListener('resize', this.handleAutoHeight); window.removeEventListener('scroll', this.handleListUpdate, { capture: true }); @@ -610,6 +615,7 @@ export class QueryStringInputUI extends Component { })} aria-haspopup="true" aria-expanded={this.state.isSuggestionsVisible} + data-skip-axe="aria-required-children" >
{ ); } } - -export const QueryStringInput = withKibana(QueryStringInputUI); diff --git a/src/plugins/data/public/ui/saved_query_form/index.ts b/src/plugins/data/public/ui/saved_query_form/index.ts index c52b6c92ef6d3..d3326ee0d3118 100644 --- a/src/plugins/data/public/ui/saved_query_form/index.ts +++ b/src/plugins/data/public/ui/saved_query_form/index.ts @@ -17,4 +17,5 @@ * under the License. */ +// @internal export { SavedQueryMeta, SaveQueryForm } from '../saved_query_form/save_query_form'; diff --git a/src/plugins/data/public/ui/search_bar/create_search_bar.tsx b/src/plugins/data/public/ui/search_bar/create_search_bar.tsx index 9f0ba2378592a..48e2e8dab7580 100644 --- a/src/plugins/data/public/ui/search_bar/create_search_bar.tsx +++ b/src/plugins/data/public/ui/search_bar/create_search_bar.tsx @@ -23,7 +23,7 @@ import { CoreStart } from 'src/core/public'; import { IStorageWrapper } from 'src/plugins/kibana_utils/public'; import { KibanaContextProvider } from '../../../../kibana_react/public'; import { QueryStart, SavedQuery } from '../../query'; -import { SearchBarOwnProps, SearchBar } from './search_bar'; +import { SearchBar, SearchBarOwnProps } from './'; import { useFilterManager } from './lib/use_filter_manager'; import { useTimefilter } from './lib/use_timefilter'; import { useSavedQuery } from './lib/use_saved_query'; diff --git a/src/plugins/data/public/ui/search_bar/index.tsx b/src/plugins/data/public/ui/search_bar/index.tsx index fbc9f4a41ebbf..d81ed7333655d 100644 --- a/src/plugins/data/public/ui/search_bar/index.tsx +++ b/src/plugins/data/public/ui/search_bar/index.tsx @@ -17,5 +17,25 @@ * under the License. */ -export { SearchBar, SearchBarProps } from './search_bar'; +import React from 'react'; +import { injectI18n } from '@kbn/i18n/react'; +import { EuiLoadingContent, EuiDelayRender } from '@elastic/eui'; +import { withKibana } from '../../../../kibana_react/public'; +import type { SearchBarProps } from './search_bar'; + +const Fallback = () => ( + + + +); + +const LazySearchBar = React.lazy(() => import('./search_bar')); +const WrappedSearchBar = (props: SearchBarProps) => ( + }> + + +); + +export const SearchBar = injectI18n(withKibana(WrappedSearchBar)); export { StatefulSearchBarProps } from './create_search_bar'; +export type { SearchBarProps, SearchBarOwnProps } from './search_bar'; diff --git a/src/plugins/data/public/ui/search_bar/search_bar.test.tsx b/src/plugins/data/public/ui/search_bar/search_bar.test.tsx index cf438eaa0e972..a89b9bb7f91ef 100644 --- a/src/plugins/data/public/ui/search_bar/search_bar.test.tsx +++ b/src/plugins/data/public/ui/search_bar/search_bar.test.tsx @@ -18,7 +18,10 @@ */ import React from 'react'; -import { SearchBar } from './search_bar'; +import { waitFor } from '@testing-library/dom'; +import { render } from '@testing-library/react'; + +import { SearchBar } from './'; import { KibanaContextProvider } from 'src/plugins/kibana_react/public'; import { I18nProvider } from '@kbn/i18n/react'; @@ -26,7 +29,6 @@ import { I18nProvider } from '@kbn/i18n/react'; import { coreMock } from '../../../../../core/public/mocks'; const startMock = coreMock.createStart(); -import { mount } from 'enzyme'; import { IIndexPattern } from '../..'; const mockTimeHistory = { @@ -41,7 +43,7 @@ jest.mock('..', () => { }; }); -jest.mock('../query_string_input/query_bar_top_row', () => { +jest.mock('../query_string_input', () => { return { QueryBarTopRow: () =>
, }; @@ -115,42 +117,48 @@ function wrapSearchBarInContext(testProps: any) { ); } -describe('SearchBar', () => { +// FLAKY: https://github.com/elastic/kibana/issues/79910 +describe.skip('SearchBar', () => { + const SEARCH_BAR_TEST_ID = 'globalQueryBar'; const SEARCH_BAR_ROOT = '.globalQueryBar'; - const FILTER_BAR = '.filterBar'; + const FILTER_BAR = '.globalFilterBar'; const QUERY_BAR = '.queryBar'; beforeEach(() => { jest.clearAllMocks(); }); - it('Should render query bar when no options provided (in reality - timepicker)', () => { - const component = mount( + it('Should render query bar when no options provided (in reality - timepicker)', async () => { + const { container, getByTestId } = render( wrapSearchBarInContext({ indexPatterns: [mockIndexPattern], }) ); - expect(component.find(SEARCH_BAR_ROOT).length).toBe(1); - expect(component.find(FILTER_BAR).length).toBe(0); - expect(component.find(QUERY_BAR).length).toBe(1); + await waitFor(() => getByTestId(SEARCH_BAR_TEST_ID)); + + expect(container.querySelectorAll(SEARCH_BAR_ROOT).length).toBe(1); + expect(container.querySelectorAll(FILTER_BAR).length).toBe(0); + expect(container.querySelectorAll(QUERY_BAR).length).toBe(1); }); - it('Should render empty when timepicker is off and no options provided', () => { - const component = mount( + it('Should render empty when timepicker is off and no options provided', async () => { + const { container, getByTestId } = render( wrapSearchBarInContext({ indexPatterns: [mockIndexPattern], showDatePicker: false, }) ); - expect(component.find(SEARCH_BAR_ROOT).length).toBe(1); - expect(component.find(FILTER_BAR).length).toBe(0); - expect(component.find(QUERY_BAR).length).toBe(0); + await waitFor(() => getByTestId(SEARCH_BAR_TEST_ID)); + + expect(container.querySelectorAll(SEARCH_BAR_ROOT).length).toBe(1); + expect(container.querySelectorAll(FILTER_BAR).length).toBe(0); + expect(container.querySelectorAll(QUERY_BAR).length).toBe(0); }); - it('Should render filter bar, when required fields are provided', () => { - const component = mount( + it('Should render filter bar, when required fields are provided', async () => { + const { container, getByTestId } = render( wrapSearchBarInContext({ indexPatterns: [mockIndexPattern], showDatePicker: false, @@ -159,13 +167,15 @@ describe('SearchBar', () => { }) ); - expect(component.find(SEARCH_BAR_ROOT).length).toBe(1); - expect(component.find(FILTER_BAR).length).toBe(1); - expect(component.find(QUERY_BAR).length).toBe(0); + await waitFor(() => getByTestId(SEARCH_BAR_TEST_ID)); + + expect(container.querySelectorAll(SEARCH_BAR_ROOT).length).toBe(1); + expect(container.querySelectorAll(FILTER_BAR).length).toBe(1); + expect(container.querySelectorAll(QUERY_BAR).length).toBe(0); }); - it('Should NOT render filter bar, if disabled', () => { - const component = mount( + it('Should NOT render filter bar, if disabled', async () => { + const { container, getByTestId } = render( wrapSearchBarInContext({ indexPatterns: [mockIndexPattern], showFilterBar: false, @@ -175,13 +185,15 @@ describe('SearchBar', () => { }) ); - expect(component.find(SEARCH_BAR_ROOT).length).toBe(1); - expect(component.find(FILTER_BAR).length).toBe(0); - expect(component.find(QUERY_BAR).length).toBe(0); + await waitFor(() => getByTestId(SEARCH_BAR_TEST_ID)); + + expect(container.querySelectorAll(SEARCH_BAR_ROOT).length).toBe(1); + expect(container.querySelectorAll(FILTER_BAR).length).toBe(0); + expect(container.querySelectorAll(QUERY_BAR).length).toBe(0); }); - it('Should render query bar, when required fields are provided', () => { - const component = mount( + it('Should render query bar, when required fields are provided', async () => { + const { container, getByTestId } = render( wrapSearchBarInContext({ indexPatterns: [mockIndexPattern], screenTitle: 'test screen', @@ -190,13 +202,15 @@ describe('SearchBar', () => { }) ); - expect(component.find(SEARCH_BAR_ROOT).length).toBe(1); - expect(component.find(FILTER_BAR).length).toBe(0); - expect(component.find(QUERY_BAR).length).toBe(1); + await waitFor(() => getByTestId(SEARCH_BAR_TEST_ID)); + + expect(container.querySelectorAll(SEARCH_BAR_ROOT).length).toBe(1); + expect(container.querySelectorAll(FILTER_BAR).length).toBe(0); + expect(container.querySelectorAll(QUERY_BAR).length).toBe(1); }); - it('Should NOT render query bar, if disabled', () => { - const component = mount( + it('Should NOT render query bar, if disabled', async () => { + const { container, getByTestId } = render( wrapSearchBarInContext({ indexPatterns: [mockIndexPattern], screenTitle: 'test screen', @@ -206,13 +220,15 @@ describe('SearchBar', () => { }) ); - expect(component.find(SEARCH_BAR_ROOT).length).toBe(1); - expect(component.find(FILTER_BAR).length).toBe(0); - expect(component.find(QUERY_BAR).length).toBe(0); + await waitFor(() => getByTestId(SEARCH_BAR_TEST_ID)); + + expect(container.querySelectorAll(SEARCH_BAR_ROOT).length).toBe(1); + expect(container.querySelectorAll(FILTER_BAR).length).toBe(0); + expect(container.querySelectorAll(QUERY_BAR).length).toBe(0); }); - it('Should render query bar and filter bar', () => { - const component = mount( + it('Should render query bar and filter bar', async () => { + const { container, getByTestId } = render( wrapSearchBarInContext({ indexPatterns: [mockIndexPattern], screenTitle: 'test screen', @@ -223,8 +239,10 @@ describe('SearchBar', () => { }) ); - expect(component.find(SEARCH_BAR_ROOT).length).toBe(1); - expect(component.find(FILTER_BAR).length).toBe(1); - expect(component.find(QUERY_BAR).length).toBe(1); + await waitFor(() => getByTestId(SEARCH_BAR_TEST_ID)); + + expect(container.querySelectorAll(SEARCH_BAR_ROOT).length).toBe(1); + expect(container.querySelectorAll(FILTER_BAR).length).toBe(1); + expect(container.querySelectorAll(QUERY_BAR).length).toBe(1); }); }); diff --git a/src/plugins/data/public/ui/search_bar/search_bar.tsx b/src/plugins/data/public/ui/search_bar/search_bar.tsx index b18b2fa9f0418..95651ac9ed8b3 100644 --- a/src/plugins/data/public/ui/search_bar/search_bar.tsx +++ b/src/plugins/data/public/ui/search_bar/search_bar.tsx @@ -26,11 +26,13 @@ import { get, isEqual } from 'lodash'; import { withKibana, KibanaReactContextValue } from '../../../../kibana_react/public'; -import { QueryBarTopRow } from '../query_string_input/query_bar_top_row'; +import { QueryBarTopRow } from '../query_string_input'; import { SavedQueryAttributes, TimeHistoryContract, SavedQuery } from '../../query'; import { IDataPluginServices } from '../../types'; import { TimeRange, Query, Filter, IIndexPattern } from '../../../common'; -import { SavedQueryMeta, SavedQueryManagementComponent, SaveQueryForm, FilterBar } from '..'; +import { FilterBar } from '../filter_bar/filter_bar'; +import { SavedQueryMeta, SaveQueryForm } from '../saved_query_form'; +import { SavedQueryManagementComponent } from '../saved_query_management'; interface SearchBarInjectedDeps { kibana: KibanaReactContextValue; @@ -437,7 +439,7 @@ class SearchBarUI extends Component { } return ( -
+
{queryBar} {filterBar} @@ -465,4 +467,6 @@ class SearchBarUI extends Component { } } -export const SearchBar = injectI18n(withKibana(SearchBarUI)); +// Needed for React.lazy +// eslint-disable-next-line import/no-default-export +export default injectI18n(withKibana(SearchBarUI)); diff --git a/src/plugins/data/public/ui/shard_failure_modal/index.ts b/src/plugins/data/public/ui/shard_failure_modal/index.ts deleted file mode 100644 index e5af9633e73b7..0000000000000 --- a/src/plugins/data/public/ui/shard_failure_modal/index.ts +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -export { ShardFailureRequest } from './shard_failure_types'; -export { ShardFailureOpenModalButton } from './shard_failure_open_modal_button'; diff --git a/src/plugins/data/public/ui/shard_failure_modal/index.tsx b/src/plugins/data/public/ui/shard_failure_modal/index.tsx new file mode 100644 index 0000000000000..cea882deff365 --- /dev/null +++ b/src/plugins/data/public/ui/shard_failure_modal/index.tsx @@ -0,0 +1,39 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React from 'react'; +import { EuiLoadingContent, EuiDelayRender } from '@elastic/eui'; +import type { ShardFailureOpenModalButtonProps } from './shard_failure_open_modal_button'; + +const Fallback = () => ( + + + +); + +const LazyShardFailureOpenModalButton = React.lazy( + () => import('./shard_failure_open_modal_button') +); +export const ShardFailureOpenModalButton = (props: ShardFailureOpenModalButtonProps) => ( + }> + + +); + +export type { ShardFailureRequest } from './shard_failure_types'; diff --git a/src/plugins/data/public/ui/shard_failure_modal/shard_failure_open_modal_button.test.tsx b/src/plugins/data/public/ui/shard_failure_modal/shard_failure_open_modal_button.test.tsx index aee8d1f4eac4d..7a4ca80e6192f 100644 --- a/src/plugins/data/public/ui/shard_failure_modal/shard_failure_open_modal_button.test.tsx +++ b/src/plugins/data/public/ui/shard_failure_modal/shard_failure_open_modal_button.test.tsx @@ -19,7 +19,7 @@ import { openModal } from './shard_failure_open_modal_button.test.mocks'; import React from 'react'; import { mountWithIntl } from 'test_utils/enzyme_helpers'; -import { ShardFailureOpenModalButton } from './shard_failure_open_modal_button'; +import ShardFailureOpenModalButton from './shard_failure_open_modal_button'; import { shardFailureRequest } from './__mocks__/shard_failure_request'; import { shardFailureResponse } from './__mocks__/shard_failure_response'; import { findTestSubject } from '@elastic/eui/lib/test'; diff --git a/src/plugins/data/public/ui/shard_failure_modal/shard_failure_open_modal_button.tsx b/src/plugins/data/public/ui/shard_failure_modal/shard_failure_open_modal_button.tsx index 9d89dc4cb1a29..b6bbba31dc5f0 100644 --- a/src/plugins/data/public/ui/shard_failure_modal/shard_failure_open_modal_button.tsx +++ b/src/plugins/data/public/ui/shard_failure_modal/shard_failure_open_modal_button.tsx @@ -26,13 +26,20 @@ import { toMountPoint } from '../../../../kibana_react/public'; import { ShardFailureModal } from './shard_failure_modal'; import { ShardFailureRequest } from './shard_failure_types'; -interface Props { +// @internal +export interface ShardFailureOpenModalButtonProps { request: ShardFailureRequest; response: SearchResponse; title: string; } -export function ShardFailureOpenModalButton({ request, response, title }: Props) { +// Needed for React.lazy +// eslint-disable-next-line import/no-default-export +export default function ShardFailureOpenModalButton({ + request, + response, + title, +}: ShardFailureOpenModalButtonProps) { function onClick() { const modal = getOverlays().openModal( toMountPoint( diff --git a/src/plugins/data/public/ui/typeahead/__snapshots__/suggestion_component.test.tsx.snap b/src/plugins/data/public/ui/typeahead/__snapshots__/suggestion_component.test.tsx.snap index 38b570c86c6c5..19ce92178d5e4 100644 --- a/src/plugins/data/public/ui/typeahead/__snapshots__/suggestion_component.test.tsx.snap +++ b/src/plugins/data/public/ui/typeahead/__snapshots__/suggestion_component.test.tsx.snap @@ -22,6 +22,7 @@ exports[`SuggestionComponent Should display the suggestion and use the provided
as promised, not helpful
@@ -56,6 +57,7 @@ exports[`SuggestionComponent Should make the element active if the selected prop
as promised, not helpful
diff --git a/src/plugins/data/public/ui/typeahead/index.ts b/src/plugins/data/public/ui/typeahead/index.ts deleted file mode 100644 index 38b51622b85f7..0000000000000 --- a/src/plugins/data/public/ui/typeahead/index.ts +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -export { SuggestionsComponent } from './suggestions_component'; diff --git a/src/plugins/data/public/ui/typeahead/index.tsx b/src/plugins/data/public/ui/typeahead/index.tsx new file mode 100644 index 0000000000000..aa3c2d71300df --- /dev/null +++ b/src/plugins/data/public/ui/typeahead/index.tsx @@ -0,0 +1,35 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React from 'react'; +import { EuiLoadingContent, EuiDelayRender } from '@elastic/eui'; +import type { SuggestionsComponentProps } from './suggestions_component'; + +const Fallback = () => ( + + + +); + +const LazySuggestionsComponent = React.lazy(() => import('./suggestions_component')); +export const SuggestionsComponent = (props: SuggestionsComponentProps) => ( + }> + + +); diff --git a/src/plugins/data/public/ui/typeahead/suggestion_component.tsx b/src/plugins/data/public/ui/typeahead/suggestion_component.tsx index 724287b874bf7..20cb60ddab9e1 100644 --- a/src/plugins/data/public/ui/typeahead/suggestion_component.tsx +++ b/src/plugins/data/public/ui/typeahead/suggestion_component.tsx @@ -72,7 +72,9 @@ export function SuggestionComponent(props: Props) {
-
{props.suggestion.text}
+
+ {props.suggestion.text} +
{props.shouldDisplayDescription && (
{props.suggestion.description}
)} diff --git a/src/plugins/data/public/ui/typeahead/suggestions_component.test.tsx b/src/plugins/data/public/ui/typeahead/suggestions_component.test.tsx index 583940015c152..d813a5281c448 100644 --- a/src/plugins/data/public/ui/typeahead/suggestions_component.test.tsx +++ b/src/plugins/data/public/ui/typeahead/suggestions_component.test.tsx @@ -21,7 +21,7 @@ import { mount, shallow } from 'enzyme'; import React from 'react'; import { QuerySuggestion, QuerySuggestionTypes } from '../../autocomplete'; import { SuggestionComponent } from './suggestion_component'; -import { SuggestionsComponent } from './suggestions_component'; +import SuggestionsComponent from './suggestions_component'; const noop = () => { return; diff --git a/src/plugins/data/public/ui/typeahead/suggestions_component.tsx b/src/plugins/data/public/ui/typeahead/suggestions_component.tsx index 50ed9e9542d36..7ec8d0d9b720e 100644 --- a/src/plugins/data/public/ui/typeahead/suggestions_component.tsx +++ b/src/plugins/data/public/ui/typeahead/suggestions_component.tsx @@ -29,7 +29,8 @@ import { SUGGESTIONS_LIST_REQUIRED_WIDTH, } from './constants'; -interface Props { +// @internal +export interface SuggestionsComponentProps { index: number | null; onClick: (suggestion: QuerySuggestion) => void; onMouseEnter: (index: number) => void; @@ -42,7 +43,9 @@ interface Props { export type SuggestionsListSize = 's' | 'l'; -export class SuggestionsComponent extends Component { +// Needed for React.lazy +// eslint-disable-next-line import/no-default-export +export default class SuggestionsComponent extends Component { private childNodes: HTMLDivElement[] = []; private parentNode: HTMLDivElement | null = null; @@ -107,7 +110,7 @@ export class SuggestionsComponent extends Component { ); } - public componentDidUpdate(prevProps: Props) { + public componentDidUpdate(prevProps: SuggestionsComponentProps) { if (prevProps.index !== this.props.index) { this.scrollIntoView(); } diff --git a/src/plugins/data/server/index.ts b/src/plugins/data/server/index.ts index 03baff4910309..11dcbb01bf4a6 100644 --- a/src/plugins/data/server/index.ts +++ b/src/plugins/data/server/index.ts @@ -133,16 +133,17 @@ export { IndexPatternsFetcher, FieldDescriptor as IndexPatternFieldDescriptor, shouldReadFieldFromDocValues, // used only in logstash_fields fixture + FieldDescriptor, } from './index_patterns'; export { - IIndexPattern, IFieldType, IFieldSubType, ES_FIELD_TYPES, KBN_FIELD_TYPES, IndexPatternAttributes, UI_SETTINGS, + IndexPattern, } from '../common'; /** @@ -213,11 +214,13 @@ export { ISearchSetup, ISearchStart, toSnakeCase, + getAsyncOptions, getDefaultSearchParams, getShardTimeout, getTotalLoaded, shimHitsTotal, usageProvider, + shimAbortSignal, SearchUsage, } from './search'; @@ -286,6 +289,9 @@ export { export const config: PluginConfigDescriptor = { exposeToBrowser: { autocomplete: true, + search: true, }, schema: configSchema, }; + +export type { IndexPatternsService } from './index_patterns'; diff --git a/src/plugins/data/server/index_patterns/fetcher/index_patterns_fetcher.ts b/src/plugins/data/server/index_patterns/fetcher/index_patterns_fetcher.ts index ff9d67152e268..57c636a9e3c69 100644 --- a/src/plugins/data/server/index_patterns/fetcher/index_patterns_fetcher.ts +++ b/src/plugins/data/server/index_patterns/fetcher/index_patterns_fetcher.ts @@ -55,9 +55,10 @@ export class IndexPatternsFetcher { async getFieldsForWildcard(options: { pattern: string | string[]; metaFields?: string[]; + fieldCapsOptions?: { allowNoIndices: boolean }; }): Promise { - const { pattern, metaFields } = options; - return await getFieldCapabilities(this._callDataCluster, pattern, metaFields); + const { pattern, metaFields, fieldCapsOptions } = options; + return await getFieldCapabilities(this._callDataCluster, pattern, metaFields, fieldCapsOptions); } /** diff --git a/src/plugins/data/server/index_patterns/fetcher/lib/es_api.ts b/src/plugins/data/server/index_patterns/fetcher/lib/es_api.ts index 0738a16034d46..27ce14f9a3597 100644 --- a/src/plugins/data/server/index_patterns/fetcher/lib/es_api.ts +++ b/src/plugins/data/server/index_patterns/fetcher/lib/es_api.ts @@ -69,15 +69,20 @@ export async function callIndexAliasApi( * * @param {Function} callCluster bound function for accessing an es client * @param {Array|String} indices + * @param {Object} fieldCapsOptions * @return {Promise} */ -export async function callFieldCapsApi(callCluster: LegacyAPICaller, indices: string[] | string) { +export async function callFieldCapsApi( + callCluster: LegacyAPICaller, + indices: string[] | string, + fieldCapsOptions: { allowNoIndices: boolean } = { allowNoIndices: false } +) { try { return (await callCluster('fieldCaps', { index: indices, fields: '*', ignoreUnavailable: true, - allowNoIndices: false, + ...fieldCapsOptions, })) as FieldCapsResponse; } catch (error) { throw convertEsError(indices, error); diff --git a/src/plugins/data/server/index_patterns/fetcher/lib/field_capabilities/field_capabilities.test.js b/src/plugins/data/server/index_patterns/fetcher/lib/field_capabilities/field_capabilities.test.js index a0af7582ac6f3..0e5757b7b782b 100644 --- a/src/plugins/data/server/index_patterns/fetcher/lib/field_capabilities/field_capabilities.test.js +++ b/src/plugins/data/server/index_patterns/fetcher/lib/field_capabilities/field_capabilities.test.js @@ -61,7 +61,7 @@ describe('index_patterns/field_capabilities/field_capabilities', () => { await getFieldCapabilities(footballs[0], footballs[1]); sinon.assert.calledOnce(callFieldCapsApi); - calledWithExactly(callFieldCapsApi, [footballs[0], footballs[1]]); + calledWithExactly(callFieldCapsApi, [footballs[0], footballs[1], undefined]); }); }); diff --git a/src/plugins/data/server/index_patterns/fetcher/lib/field_capabilities/field_capabilities.ts b/src/plugins/data/server/index_patterns/fetcher/lib/field_capabilities/field_capabilities.ts index 6b26c82dc95e7..62e77e0adad66 100644 --- a/src/plugins/data/server/index_patterns/fetcher/lib/field_capabilities/field_capabilities.ts +++ b/src/plugins/data/server/index_patterns/fetcher/lib/field_capabilities/field_capabilities.ts @@ -32,14 +32,20 @@ import { FieldDescriptor } from '../../index_patterns_fetcher'; * @param {Function} callCluster bound function for accessing an es client * @param {Array} [indices=[]] the list of indexes to check * @param {Array} [metaFields=[]] the list of internal fields to include + * @param {Object} fieldCapsOptions * @return {Promise>} */ export async function getFieldCapabilities( callCluster: LegacyAPICaller, indices: string | string[] = [], - metaFields: string[] = [] + metaFields: string[] = [], + fieldCapsOptions?: { allowNoIndices: boolean } ) { - const esFieldCaps: FieldCapsResponse = await callFieldCapsApi(callCluster, indices); + const esFieldCaps: FieldCapsResponse = await callFieldCapsApi( + callCluster, + indices, + fieldCapsOptions + ); const fieldsFromFieldCapsByName = keyBy(readFieldCapsResponse(esFieldCaps), 'name'); const allFieldsUnsorted = Object.keys(fieldsFromFieldCapsByName) diff --git a/src/plugins/data/server/index_patterns/index_patterns_service.ts b/src/plugins/data/server/index_patterns/index_patterns_service.ts index 44699993dd135..d665e3715fa72 100644 --- a/src/plugins/data/server/index_patterns/index_patterns_service.ts +++ b/src/plugins/data/server/index_patterns/index_patterns_service.ts @@ -17,7 +17,7 @@ * under the License. */ -import { CoreSetup, CoreStart, Plugin, KibanaRequest, Logger } from 'kibana/server'; +import { CoreSetup, CoreStart, Plugin, Logger, SavedObjectsClientContract } from 'kibana/server'; import { registerRoutes } from './routes'; import { indexPatternSavedObjectType } from '../saved_objects'; import { capabilitiesProvider } from './capabilities_provider'; @@ -29,7 +29,7 @@ import { SavedObjectsClientServerToCommon } from './saved_objects_client_wrapper export interface IndexPatternsServiceStart { indexPatternsServiceFactory: ( - kibanaRequest: KibanaRequest + savedObjectsClient: SavedObjectsClientContract ) => Promise; } @@ -47,11 +47,10 @@ export class IndexPatternsService implements Plugin { - const savedObjectsClient = savedObjects.getScopedClient(kibanaRequest); + indexPatternsServiceFactory: async (savedObjectsClient: SavedObjectsClientContract) => { const uiSettingsClient = uiSettings.asScopedToClient(savedObjectsClient); const formats = await fieldFormats.fieldFormatServiceFactory(uiSettingsClient); diff --git a/src/plugins/data/server/index_patterns/utils.ts b/src/plugins/data/server/index_patterns/utils.ts index e841097fe49c2..1e7a85599612c 100644 --- a/src/plugins/data/server/index_patterns/utils.ts +++ b/src/plugins/data/server/index_patterns/utils.ts @@ -18,11 +18,11 @@ */ import { SavedObjectsClientContract } from 'kibana/server'; -import { IIndexPattern, IFieldType } from '../../common'; +import { IFieldType, IndexPatternAttributes, SavedObject } from '../../common'; export const getFieldByName = ( fieldName: string, - indexPattern: IIndexPattern + indexPattern: SavedObject ): IFieldType | undefined => { const fields: IFieldType[] = indexPattern && JSON.parse(indexPattern.attributes.fields); const field = fields && fields.find((f) => f.name === fieldName); @@ -33,8 +33,8 @@ export const getFieldByName = ( export const findIndexPatternById = async ( savedObjectsClient: SavedObjectsClientContract, index: string -): Promise => { - const savedObjectsResponse = await savedObjectsClient.find({ +): Promise | undefined> => { + const savedObjectsResponse = await savedObjectsClient.find({ type: 'index-pattern', fields: ['fields'], search: `"${index}"`, @@ -42,6 +42,6 @@ export const findIndexPatternById = async ( }); if (savedObjectsResponse.total > 0) { - return (savedObjectsResponse.saved_objects[0] as unknown) as IIndexPattern; + return savedObjectsResponse.saved_objects[0]; } }; diff --git a/src/plugins/data/server/kql_telemetry/route.ts b/src/plugins/data/server/kql_telemetry/route.ts index dd7ff333e6257..efcb3d038bcc6 100644 --- a/src/plugins/data/server/kql_telemetry/route.ts +++ b/src/plugins/data/server/kql_telemetry/route.ts @@ -27,7 +27,7 @@ export function registerKqlTelemetryRoute( ) { router.post( { - path: '/api/kibana/kql_opt_in_telemetry', + path: '/api/kibana/kql_opt_in_stats', validate: { body: schema.object({ opt_in: schema.boolean(), diff --git a/src/plugins/data/server/plugin.ts b/src/plugins/data/server/plugin.ts index 588885391262e..88f24b7ca5a70 100644 --- a/src/plugins/data/server/plugin.ts +++ b/src/plugins/data/server/plugin.ts @@ -111,13 +111,15 @@ export class DataServerPlugin public start(core: CoreStart) { const fieldFormats = this.fieldFormats.start(); + const indexPatterns = this.indexPatterns.start(core, { + fieldFormats, + logger: this.logger.get('indexPatterns'), + }); + return { - search: this.searchService.start(core, { fieldFormats }), fieldFormats, - indexPatterns: this.indexPatterns.start(core, { - fieldFormats, - logger: this.logger.get('indexPatterns'), - }), + indexPatterns, + search: this.searchService.start(core, { fieldFormats, indexPatterns }), }; } diff --git a/src/plugins/data/server/search/es_search/es_search_strategy.ts b/src/plugins/data/server/search/es_search/es_search_strategy.ts index e2ed500689cfa..6e185d30ad56a 100644 --- a/src/plugins/data/server/search/es_search/es_search_strategy.ts +++ b/src/plugins/data/server/search/es_search/es_search_strategy.ts @@ -23,7 +23,13 @@ import { Observable } from 'rxjs'; import { ApiResponse } from '@elastic/elasticsearch'; import { SearchUsage } from '../collectors/usage'; import { toSnakeCase } from './to_snake_case'; -import { ISearchStrategy, getDefaultSearchParams, getTotalLoaded, getShardTimeout } from '..'; +import { + ISearchStrategy, + getDefaultSearchParams, + getTotalLoaded, + getShardTimeout, + shimAbortSignal, +} from '..'; export const esSearchStrategyProvider = ( config$: Observable, @@ -52,10 +58,10 @@ export const esSearchStrategyProvider = ( }); try { - // Temporary workaround until https://github.com/elastic/elasticsearch-js/issues/1297 - const promise = context.core.elasticsearch.client.asCurrentUser.search(params); - if (options?.abortSignal) - options.abortSignal.addEventListener('abort', () => promise.abort()); + const promise = shimAbortSignal( + context.core.elasticsearch.client.asCurrentUser.search(params), + options?.abortSignal + ); const { body: rawResponse } = (await promise) as ApiResponse>; if (usage) usage.trackSuccess(rawResponse.took); diff --git a/src/plugins/data/server/search/es_search/get_default_search_params.ts b/src/plugins/data/server/search/es_search/get_default_search_params.ts index 13607fce51670..b51293b88fcec 100644 --- a/src/plugins/data/server/search/es_search/get_default_search_params.ts +++ b/src/plugins/data/server/search/es_search/get_default_search_params.ts @@ -42,3 +42,11 @@ export async function getDefaultSearchParams(uiSettingsClient: IUiSettingsClient trackTotalHits: true, }; } + +/** + @internal + */ +export const getAsyncOptions = () => ({ + waitForCompletionTimeout: '100ms', // Wait up to 100ms for the response to return + keepAlive: '1m', // Extend the TTL for this search request by one minute +}); diff --git a/src/plugins/data/server/search/es_search/index.ts b/src/plugins/data/server/search/es_search/index.ts index 1bd17fc986168..63ab7a025ee51 100644 --- a/src/plugins/data/server/search/es_search/index.ts +++ b/src/plugins/data/server/search/es_search/index.ts @@ -21,5 +21,6 @@ export { esSearchStrategyProvider } from './es_search_strategy'; export * from './get_default_search_params'; export { getTotalLoaded } from './get_total_loaded'; export * from './to_snake_case'; +export { shimAbortSignal } from './shim_abort_signal'; export { ES_SEARCH_STRATEGY, IEsSearchRequest, IEsSearchResponse } from '../../../common'; diff --git a/src/plugins/data/server/search/es_search/shim_abort_signal.test.ts b/src/plugins/data/server/search/es_search/shim_abort_signal.test.ts new file mode 100644 index 0000000000000..794b6535cc184 --- /dev/null +++ b/src/plugins/data/server/search/es_search/shim_abort_signal.test.ts @@ -0,0 +1,55 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { elasticsearchServiceMock } from '../../../../../core/server/mocks'; +import { shimAbortSignal } from '.'; + +describe('shimAbortSignal', () => { + it('aborts the promise if the signal is aborted', () => { + const promise = elasticsearchServiceMock.createSuccessTransportRequestPromise({ + success: true, + }); + const controller = new AbortController(); + shimAbortSignal(promise, controller.signal); + controller.abort(); + + expect(promise.abort).toHaveBeenCalled(); + }); + + it('returns the original promise', async () => { + const promise = elasticsearchServiceMock.createSuccessTransportRequestPromise({ + success: true, + }); + const controller = new AbortController(); + const response = await shimAbortSignal(promise, controller.signal); + + expect(response).toEqual(expect.objectContaining({ body: { success: true } })); + }); + + it('allows the promise to be aborted manually', () => { + const promise = elasticsearchServiceMock.createSuccessTransportRequestPromise({ + success: true, + }); + const controller = new AbortController(); + const enhancedPromise = shimAbortSignal(promise, controller.signal); + + enhancedPromise.abort(); + expect(promise.abort).toHaveBeenCalled(); + }); +}); diff --git a/src/plugins/data/server/search/es_search/shim_abort_signal.ts b/src/plugins/data/server/search/es_search/shim_abort_signal.ts new file mode 100644 index 0000000000000..14a4a6919c5af --- /dev/null +++ b/src/plugins/data/server/search/es_search/shim_abort_signal.ts @@ -0,0 +1,41 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { TransportRequestPromise } from '@elastic/elasticsearch/lib/Transport'; + +/** + * + * @internal + * NOTE: Temporary workaround until https://github.com/elastic/elasticsearch-js/issues/1297 + * is resolved + * + * @param promise a TransportRequestPromise + * @param signal optional AbortSignal + * + * @returns a TransportRequestPromise that will be aborted if the signal is aborted + */ +export const shimAbortSignal = >( + promise: T, + signal: AbortSignal | undefined +): T => { + if (signal) { + signal.addEventListener('abort', () => promise.abort()); + } + return promise; +}; diff --git a/src/plugins/data/server/search/mocks.ts b/src/plugins/data/server/search/mocks.ts index 0c74ecb4b2c9d..0d4ba0cba24a3 100644 --- a/src/plugins/data/server/search/mocks.ts +++ b/src/plugins/data/server/search/mocks.ts @@ -19,6 +19,7 @@ import { ISearchSetup, ISearchStart } from './types'; import { searchAggsSetupMock, searchAggsStartMock } from './aggs/mocks'; +import { searchSourceMock } from './search_source/mocks'; export function createSearchSetupMock(): jest.Mocked { return { @@ -33,5 +34,6 @@ export function createSearchStartMock(): jest.Mocked { aggs: searchAggsStartMock(), getSearchStrategy: jest.fn(), search: jest.fn(), + searchSource: searchSourceMock.createStartContract(), }; } diff --git a/src/plugins/data/server/search/routes/call_msearch.test.ts b/src/plugins/data/server/search/routes/call_msearch.test.ts new file mode 100644 index 0000000000000..3d409e22aaa88 --- /dev/null +++ b/src/plugins/data/server/search/routes/call_msearch.test.ts @@ -0,0 +1,101 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { Observable } from 'rxjs'; +import { IUiSettingsClient, IScopedClusterClient, SharedGlobalConfig } from 'src/core/server'; + +import { + coreMock, + pluginInitializerContextConfigMock, +} from '../../../../../../src/core/server/mocks'; +import { convertRequestBody, getCallMsearch } from './call_msearch'; + +describe('callMsearch', () => { + let esClient: DeeplyMockedKeys; + let globalConfig$: Observable; + let uiSettings: IUiSettingsClient; + let callMsearch: ReturnType; + + beforeEach(() => { + const coreContext = coreMock.createRequestHandlerContext(); + esClient = coreContext.elasticsearch.client; + globalConfig$ = pluginInitializerContextConfigMock({}).legacy.globalConfig$; + uiSettings = coreContext.uiSettings.client; + + callMsearch = getCallMsearch({ esClient, globalConfig$, uiSettings }); + }); + + it('handler calls msearch with the given request', async () => { + const mockBody = { + searches: [{ header: { index: 'foo' }, body: { query: { match_all: {} } } }], + }; + + await callMsearch({ + body: mockBody, + signal: new AbortController().signal, + }); + + expect(esClient.asCurrentUser.msearch).toHaveBeenCalledTimes(1); + expect(esClient.asCurrentUser.msearch.mock.calls[0]).toMatchInlineSnapshot(` + Array [ + Object { + "body": "{\\"ignore_unavailable\\":true,\\"index\\":\\"foo\\"} + {\\"query\\":{\\"match_all\\":{}}} + ", + }, + Object { + "querystring": Object { + "ignore_throttled": true, + "ignore_unavailable": true, + "max_concurrent_shard_requests": undefined, + }, + }, + ] + `); + }); + + describe('convertRequestBody', () => { + it('combines header & body into proper msearch request', () => { + const request = { + searches: [{ header: { index: 'foo', preference: 0 }, body: { test: true } }], + }; + expect(convertRequestBody(request, { timeout: '30000ms' })).toMatchInlineSnapshot(` + "{\\"ignore_unavailable\\":true,\\"index\\":\\"foo\\",\\"preference\\":0} + {\\"timeout\\":\\"30000ms\\",\\"test\\":true} + " + `); + }); + + it('handles multiple searches', () => { + const request = { + searches: [ + { header: { index: 'foo', preference: 0 }, body: { test: true } }, + { header: { index: 'bar', preference: 1 }, body: { hello: 'world' } }, + ], + }; + expect(convertRequestBody(request, { timeout: '30000ms' })).toMatchInlineSnapshot(` + "{\\"ignore_unavailable\\":true,\\"index\\":\\"foo\\",\\"preference\\":0} + {\\"timeout\\":\\"30000ms\\",\\"test\\":true} + {\\"ignore_unavailable\\":true,\\"index\\":\\"bar\\",\\"preference\\":1} + {\\"timeout\\":\\"30000ms\\",\\"hello\\":\\"world\\"} + " + `); + }); + }); +}); diff --git a/src/plugins/data/server/search/routes/call_msearch.ts b/src/plugins/data/server/search/routes/call_msearch.ts new file mode 100644 index 0000000000000..8103b680c6bbb --- /dev/null +++ b/src/plugins/data/server/search/routes/call_msearch.ts @@ -0,0 +1,99 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { Observable } from 'rxjs'; +import { first } from 'rxjs/operators'; +import { ApiResponse } from '@elastic/elasticsearch'; +import { SearchResponse } from 'elasticsearch'; +import { IUiSettingsClient, IScopedClusterClient, SharedGlobalConfig } from 'src/core/server'; + +import { MsearchRequestBody, MsearchResponse } from '../../../common/search/search_source'; +import { shimHitsTotal } from './shim_hits_total'; +import { getShardTimeout, getDefaultSearchParams, toSnakeCase, shimAbortSignal } from '..'; + +/** @internal */ +export function convertRequestBody( + requestBody: MsearchRequestBody, + { timeout }: { timeout?: string } +): string { + return requestBody.searches.reduce((req, curr) => { + const header = JSON.stringify({ + ignore_unavailable: true, + ...curr.header, + }); + const body = JSON.stringify({ + timeout, + ...curr.body, + }); + return `${req}${header}\n${body}\n`; + }, ''); +} + +interface CallMsearchDependencies { + esClient: IScopedClusterClient; + globalConfig$: Observable; + uiSettings: IUiSettingsClient; +} + +/** + * Helper for the `/internal/_msearch` route, exported separately here + * so that it can be reused elsewhere in the data plugin on the server, + * e.g. SearchSource + * + * @internal + */ +export function getCallMsearch(dependencies: CallMsearchDependencies) { + return async (params: { + body: MsearchRequestBody; + signal?: AbortSignal; + }): Promise => { + const { esClient, globalConfig$, uiSettings } = dependencies; + + // get shardTimeout + const config = await globalConfig$.pipe(first()).toPromise(); + const timeout = getShardTimeout(config); + + // trackTotalHits is not supported by msearch + const { trackTotalHits, ...defaultParams } = await getDefaultSearchParams(uiSettings); + + const body = convertRequestBody(params.body, timeout); + + const promise = shimAbortSignal( + esClient.asCurrentUser.msearch( + { + body, + }, + { + querystring: toSnakeCase(defaultParams), + } + ), + params.signal + ); + const response = (await promise) as ApiResponse<{ responses: Array> }>; + + return { + body: { + ...response, + body: { + responses: response.body.responses?.map((r: SearchResponse) => shimHitsTotal(r)), + }, + }, + }; + }; +} diff --git a/src/plugins/data/server/search/routes/index.ts b/src/plugins/data/server/search/routes/index.ts index a290f08f9b843..f858653f26439 100644 --- a/src/plugins/data/server/search/routes/index.ts +++ b/src/plugins/data/server/search/routes/index.ts @@ -17,6 +17,7 @@ * under the License. */ +export * from './call_msearch'; export * from './msearch'; export * from './search'; export * from './shim_hits_total'; diff --git a/src/plugins/data/server/search/routes/msearch.test.ts b/src/plugins/data/server/search/routes/msearch.test.ts index 3a7d67c31b8be..2f414fe0b4920 100644 --- a/src/plugins/data/server/search/routes/msearch.test.ts +++ b/src/plugins/data/server/search/routes/msearch.test.ts @@ -30,7 +30,8 @@ import { httpServerMock, pluginInitializerContextConfigMock, } from '../../../../../../src/core/server/mocks'; -import { registerMsearchRoute, convertRequestBody } from './msearch'; +import { convertRequestBody } from './call_msearch'; +import { registerMsearchRoute } from './msearch'; import { DataPluginStart } from '../../plugin'; import { dataPluginMock } from '../../mocks'; @@ -49,7 +50,7 @@ describe('msearch route', () => { it('handler calls /_msearch with the given request', async () => { const response = { id: 'yay', body: { responses: [{ hits: { total: 5 } }] } }; - const mockClient = { transport: { request: jest.fn().mockResolvedValue(response) } }; + const mockClient = { msearch: jest.fn().mockResolvedValue(response) }; const mockContext = { core: { elasticsearch: { client: { asCurrentUser: mockClient } }, @@ -70,11 +71,16 @@ describe('msearch route', () => { const handler = mockRouter.post.mock.calls[0][1]; await handler((mockContext as unknown) as RequestHandlerContext, mockRequest, mockResponse); - expect(mockClient.transport.request.mock.calls[0][0].method).toBe('GET'); - expect(mockClient.transport.request.mock.calls[0][0].path).toBe('/_msearch'); - expect(mockClient.transport.request.mock.calls[0][0].body).toEqual( + expect(mockClient.msearch.mock.calls[0][0].body).toEqual( convertRequestBody(mockBody as any, {}) ); + expect(mockClient.msearch.mock.calls[0][1].querystring).toMatchInlineSnapshot(` + Object { + "ignore_throttled": true, + "ignore_unavailable": true, + "max_concurrent_shard_requests": undefined, + } + `); expect(mockResponse.ok).toBeCalled(); expect(mockResponse.ok.mock.calls[0][0]).toEqual({ body: response, @@ -89,7 +95,7 @@ describe('msearch route', () => { }, }; const mockClient = { - transport: { request: jest.fn().mockReturnValue(Promise.reject(response)) }, + msearch: jest.fn().mockReturnValue(Promise.reject(response)), }; const mockContext = { core: { @@ -111,40 +117,11 @@ describe('msearch route', () => { const handler = mockRouter.post.mock.calls[0][1]; await handler((mockContext as unknown) as RequestHandlerContext, mockRequest, mockResponse); - expect(mockClient.transport.request).toBeCalled(); + expect(mockClient.msearch).toBeCalled(); expect(mockResponse.customError).toBeCalled(); const error: any = mockResponse.customError.mock.calls[0][0]; expect(error.body.message).toBe('oh no'); expect(error.body.attributes.error).toBe('oops'); }); - - describe('convertRequestBody', () => { - it('combines header & body into proper msearch request', () => { - const request = { - searches: [{ header: { index: 'foo', preference: 0 }, body: { test: true } }], - }; - expect(convertRequestBody(request, { timeout: '30000ms' })).toMatchInlineSnapshot(` - "{\\"ignore_unavailable\\":true,\\"index\\":\\"foo\\",\\"preference\\":0} - {\\"timeout\\":\\"30000ms\\",\\"test\\":true} - " - `); - }); - - it('handles multiple searches', () => { - const request = { - searches: [ - { header: { index: 'foo', preference: 0 }, body: { test: true } }, - { header: { index: 'bar', preference: 1 }, body: { hello: 'world' } }, - ], - }; - expect(convertRequestBody(request, { timeout: '30000ms' })).toMatchInlineSnapshot(` - "{\\"ignore_unavailable\\":true,\\"index\\":\\"foo\\",\\"preference\\":0} - {\\"timeout\\":\\"30000ms\\",\\"test\\":true} - {\\"ignore_unavailable\\":true,\\"index\\":\\"bar\\",\\"preference\\":1} - {\\"timeout\\":\\"30000ms\\",\\"hello\\":\\"world\\"} - " - `); - }); - }); }); diff --git a/src/plugins/data/server/search/routes/msearch.ts b/src/plugins/data/server/search/routes/msearch.ts index e1ddb06e4fb6f..7b44aa18bf8fc 100644 --- a/src/plugins/data/server/search/routes/msearch.ts +++ b/src/plugins/data/server/search/routes/msearch.ts @@ -17,46 +17,12 @@ * under the License. */ -import { first } from 'rxjs/operators'; import { schema } from '@kbn/config-schema'; -import { SearchResponse } from 'elasticsearch'; import { IRouter } from 'src/core/server'; import { SearchRouteDependencies } from '../search_service'; -import { shimHitsTotal } from './shim_hits_total'; -import { getShardTimeout, getDefaultSearchParams, toSnakeCase } from '..'; -interface MsearchHeaders { - index: string; - preference?: number | string; -} - -interface MsearchRequest { - header: MsearchHeaders; - body: any; -} - -interface RequestBody { - searches: MsearchRequest[]; -} - -/** @internal */ -export function convertRequestBody( - requestBody: RequestBody, - { timeout }: { timeout?: string } -): string { - return requestBody.searches.reduce((req, curr) => { - const header = JSON.stringify({ - ignore_unavailable: true, - ...curr.header, - }); - const body = JSON.stringify({ - timeout, - ...curr.body, - }); - return `${req}${header}\n${body}\n`; - }, ''); -} +import { getCallMsearch } from './call_msearch'; /** * The msearch route takes in an array of searches, each consisting of header @@ -93,35 +59,15 @@ export function registerMsearchRoute(router: IRouter, deps: SearchRouteDependenc }, }, async (context, request, res) => { - const client = context.core.elasticsearch.client.asCurrentUser; - - // get shardTimeout - const config = await deps.globalConfig$.pipe(first()).toPromise(); - const timeout = getShardTimeout(config); - - const body = convertRequestBody(request.body, timeout); - - // trackTotalHits is not supported by msearch - const { trackTotalHits, ...defaultParams } = await getDefaultSearchParams( - context.core.uiSettings.client - ); + const callMsearch = getCallMsearch({ + esClient: context.core.elasticsearch.client, + globalConfig$: deps.globalConfig$, + uiSettings: context.core.uiSettings.client, + }); try { - const response = await client.transport.request({ - method: 'GET', - path: '/_msearch', - body, - querystring: toSnakeCase(defaultParams), - }); - - return res.ok({ - body: { - ...response, - body: { - responses: response.body.responses?.map((r: SearchResponse) => shimHitsTotal(r)), - }, - }, - }); + const response = await callMsearch({ body: request.body }); + return res.ok(response); } catch (err) { return res.customError({ statusCode: err.statusCode || 500, diff --git a/src/plugins/data/server/search/routes/search.ts b/src/plugins/data/server/search/routes/search.ts index b5d5ec283767d..492ad4395b32a 100644 --- a/src/plugins/data/server/search/routes/search.ts +++ b/src/plugins/data/server/search/routes/search.ts @@ -22,7 +22,6 @@ import { IRouter } from 'src/core/server'; import { getRequestAbortedSignal } from '../../lib'; import { SearchRouteDependencies } from '../search_service'; import { shimHitsTotal } from './shim_hits_total'; -import { isEsResponse } from '../../../common'; export function registerSearchRoute( router: IRouter, @@ -62,11 +61,9 @@ export function registerSearchRoute( return res.ok({ body: { ...response, - ...(isEsResponse(response) - ? { - rawResponse: shimHitsTotal(response.rawResponse), - } - : {}), + ...{ + rawResponse: shimHitsTotal(response.rawResponse), + }, }, }); } catch (err) { diff --git a/src/plugins/data/server/search/search_service.test.ts b/src/plugins/data/server/search/search_service.test.ts index 7057c9c7ca15c..a001d56b36514 100644 --- a/src/plugins/data/server/search/search_service.test.ts +++ b/src/plugins/data/server/search/search_service.test.ts @@ -22,6 +22,7 @@ import { coreMock } from '../../../../core/server/mocks'; import { DataPluginStart } from '../plugin'; import { createFieldFormatsStartMock } from '../field_formats/mocks'; +import { createIndexPatternsStartMock } from '../index_patterns/mocks'; import { SearchService, SearchServiceSetupDependencies } from './search_service'; @@ -54,6 +55,7 @@ describe('Search service', () => { it('exposes proper contract', async () => { const start = plugin.start(mockCoreStart, { fieldFormats: createFieldFormatsStartMock(), + indexPatterns: createIndexPatternsStartMock(), }); expect(start).toHaveProperty('aggs'); expect(start).toHaveProperty('getSearchStrategy'); diff --git a/src/plugins/data/server/search/search_service.ts b/src/plugins/data/server/search/search_service.ts index e19d3dd8a5451..6e66f8027207b 100644 --- a/src/plugins/data/server/search/search_service.ts +++ b/src/plugins/data/server/search/search_service.ts @@ -17,10 +17,12 @@ * under the License. */ -import { Observable } from 'rxjs'; +import { BehaviorSubject, Observable } from 'rxjs'; +import { pick } from 'lodash'; import { CoreSetup, CoreStart, + KibanaRequest, Logger, Plugin, PluginInitializerContext, @@ -28,24 +30,38 @@ import { SharedGlobalConfig, StartServicesAccessor, } from 'src/core/server'; +import { first } from 'rxjs/operators'; import { ISearchSetup, ISearchStart, ISearchStrategy, SearchEnhancements } from './types'; import { AggsService, AggsSetupDependencies } from './aggs'; import { FieldFormatsStart } from '../field_formats'; -import { registerMsearchRoute, registerSearchRoute } from './routes'; +import { IndexPatternsServiceStart } from '../index_patterns'; +import { getCallMsearch, registerMsearchRoute, registerSearchRoute } from './routes'; import { ES_SEARCH_STRATEGY, esSearchStrategyProvider } from './es_search'; import { DataPluginStart } from '../plugin'; import { UsageCollectionSetup } from '../../../usage_collection/server'; import { registerUsageCollector } from './collectors/register'; import { usageProvider } from './collectors/usage'; import { searchTelemetry } from '../saved_objects'; -import { IEsSearchRequest, IEsSearchResponse, ISearchOptions } from '../../common'; +import { + IKibanaSearchRequest, + IKibanaSearchResponse, + IEsSearchRequest, + IEsSearchResponse, + ISearchOptions, + SearchSourceDependencies, + SearchSourceService, + searchSourceRequiredUiSettings, +} from '../../common/search'; +import { + getShardDelayBucketAgg, + SHARD_DELAY_AGG_NAME, +} from '../../common/search/aggs/buckets/shard_delay'; +import { aggShardDelay } from '../../common/search/aggs/buckets/shard_delay_fn'; +import { ConfigSchema } from '../../config'; -type StrategyMap< - SearchStrategyRequest extends IEsSearchRequest = IEsSearchRequest, - SearchStrategyResponse extends IEsSearchResponse = IEsSearchResponse -> = Record>; +type StrategyMap = Record>; /** @internal */ export interface SearchServiceSetupDependencies { @@ -56,6 +72,7 @@ export interface SearchServiceSetupDependencies { /** @internal */ export interface SearchServiceStartDependencies { fieldFormats: FieldFormatsStart; + indexPatterns: IndexPatternsServiceStart; } /** @internal */ @@ -66,11 +83,12 @@ export interface SearchRouteDependencies { export class SearchService implements Plugin { private readonly aggsService = new AggsService(); + private readonly searchSourceService = new SearchSourceService(); private defaultSearchStrategyName: string = ES_SEARCH_STRATEGY; - private searchStrategies: StrategyMap = {}; + private searchStrategies: StrategyMap = {}; constructor( - private initializerContext: PluginInitializerContext, + private initializerContext: PluginInitializerContext, private readonly logger: Logger ) {} @@ -102,44 +120,98 @@ export class SearchService implements Plugin { registerUsageCollector(usageCollection, this.initializerContext); } + const aggs = this.aggsService.setup({ registerFunction }); + + this.initializerContext.config + .create() + .pipe(first()) + .toPromise() + .then((value) => { + if (value.search.aggs.shardDelay.enabled) { + aggs.types.registerBucket(SHARD_DELAY_AGG_NAME, getShardDelayBucketAgg); + registerFunction(aggShardDelay); + } + }); + return { __enhance: (enhancements: SearchEnhancements) => { if (this.searchStrategies.hasOwnProperty(enhancements.defaultStrategy)) { this.defaultSearchStrategyName = enhancements.defaultStrategy; } }, - aggs: this.aggsService.setup({ registerFunction }), + aggs, registerSearchStrategy: this.registerSearchStrategy, usage, }; } - - private search( - context: RequestHandlerContext, - searchRequest: IEsSearchRequest, - options: ISearchOptions - ) { - return this.getSearchStrategy(options.strategy || this.defaultSearchStrategyName).search( - context, - searchRequest, - options - ); - } - public start( - { uiSettings }: CoreStart, - { fieldFormats }: SearchServiceStartDependencies + { elasticsearch, savedObjects, uiSettings }: CoreStart, + { fieldFormats, indexPatterns }: SearchServiceStartDependencies ): ISearchStart { return { aggs: this.aggsService.start({ fieldFormats, uiSettings }), getSearchStrategy: this.getSearchStrategy, search: ( context: RequestHandlerContext, - searchRequest: IEsSearchRequest, + searchRequest: IKibanaSearchRequest, options: Record ) => { return this.search(context, searchRequest, options); }, + searchSource: { + asScoped: async (request: KibanaRequest) => { + const esClient = elasticsearch.client.asScoped(request); + const savedObjectsClient = savedObjects.getScopedClient(request); + const scopedIndexPatterns = await indexPatterns.indexPatternsServiceFactory( + savedObjectsClient + ); + const uiSettingsClient = uiSettings.asScopedToClient(savedObjectsClient); + + // cache ui settings, only including items which are explicitly needed by SearchSource + const uiSettingsCache = pick( + await uiSettingsClient.getAll(), + searchSourceRequiredUiSettings + ); + + const searchSourceDependencies: SearchSourceDependencies = { + getConfig: (key: string): T => uiSettingsCache[key], + search: (searchRequest, options) => { + /** + * Unless we want all SearchSource users to provide both a KibanaRequest + * (needed for index patterns) AND the RequestHandlerContext (needed for + * low-level search), we need to fake the context as it can be derived + * from the request object anyway. This will pose problems for folks who + * are registering custom search strategies as they are only getting a + * subset of the entire context. Ideally low-level search should be + * refactored to only require the needed dependencies: esClient & uiSettings. + */ + const fakeRequestHandlerContext = { + core: { + elasticsearch: { + client: esClient, + }, + uiSettings: { + client: uiSettingsClient, + }, + }, + } as RequestHandlerContext; + return this.search(fakeRequestHandlerContext, searchRequest, options); + }, + // onResponse isn't used on the server, so we just return the original value + onResponse: (req, res) => res, + legacy: { + callMsearch: getCallMsearch({ + esClient, + globalConfig$: this.initializerContext.config.legacy.globalConfig$, + uiSettings: uiSettingsClient, + }), + loadingCount$: new BehaviorSubject(0), + }, + }; + + return this.searchSourceService.start(scopedIndexPatterns, searchSourceDependencies); + }, + }, }; } @@ -148,8 +220,8 @@ export class SearchService implements Plugin { } private registerSearchStrategy = < - SearchStrategyRequest extends IEsSearchRequest = IEsSearchRequest, - SearchStrategyResponse extends IEsSearchResponse = IEsSearchResponse + SearchStrategyRequest extends IKibanaSearchRequest = IEsSearchRequest, + SearchStrategyResponse extends IKibanaSearchResponse = IEsSearchResponse >( name: string, strategy: ISearchStrategy @@ -158,7 +230,25 @@ export class SearchService implements Plugin { this.searchStrategies[name] = strategy; }; - private getSearchStrategy = (name: string): ISearchStrategy => { + private search = < + SearchStrategyRequest extends IKibanaSearchRequest = IEsSearchRequest, + SearchStrategyResponse extends IKibanaSearchResponse = IEsSearchResponse + >( + context: RequestHandlerContext, + searchRequest: SearchStrategyRequest, + options: ISearchOptions + ): Promise => { + return this.getSearchStrategy( + options.strategy || this.defaultSearchStrategyName + ).search(context, searchRequest, options); + }; + + private getSearchStrategy = < + SearchStrategyRequest extends IKibanaSearchRequest = IEsSearchRequest, + SearchStrategyResponse extends IKibanaSearchResponse = IEsSearchResponse + >( + name: string + ): ISearchStrategy => { this.logger.debug(`Get strategy ${name}`); const strategy = this.searchStrategies[name]; if (!strategy) { diff --git a/src/plugins/data/server/search/search_source/mocks.ts b/src/plugins/data/server/search/search_source/mocks.ts new file mode 100644 index 0000000000000..7e9cc8f2ff42c --- /dev/null +++ b/src/plugins/data/server/search/search_source/mocks.ts @@ -0,0 +1,35 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { KibanaRequest } from 'src/core/server'; + +import { searchSourceCommonMock } from '../../../common/search/search_source/mocks'; +import { ISearchStart } from '../types'; + +function createStartContract(): MockedKeys { + return { + asScoped: async (request: jest.Mocked) => { + return searchSourceCommonMock; + }, + }; +} + +export const searchSourceMock = { + createStartContract, +}; diff --git a/src/plugins/data/server/search/types.ts b/src/plugins/data/server/search/types.ts index aefdac2ab639f..0de4ef529e896 100644 --- a/src/plugins/data/server/search/types.ts +++ b/src/plugins/data/server/search/types.ts @@ -17,8 +17,13 @@ * under the License. */ -import { RequestHandlerContext } from '../../../../core/server'; -import { ISearchOptions } from '../../common/search'; +import { KibanaRequest, RequestHandlerContext } from 'src/core/server'; +import { + ISearchOptions, + ISearchStartSearchSource, + IKibanaSearchRequest, + IKibanaSearchResponse, +} from '../../common/search'; import { AggsSetup, AggsStart } from './aggs'; import { SearchUsage } from './collectors'; import { IEsSearchRequest, IEsSearchResponse } from './es_search'; @@ -34,8 +39,8 @@ export interface ISearchSetup { * strategies. */ registerSearchStrategy: < - SearchStrategyRequest extends IEsSearchRequest = IEsSearchRequest, - SearchStrategyResponse extends IEsSearchResponse = IEsSearchResponse + SearchStrategyRequest extends IKibanaSearchRequest = IEsSearchRequest, + SearchStrategyResponse extends IKibanaSearchResponse = IEsSearchResponse >( name: string, strategy: ISearchStrategy @@ -53,8 +58,8 @@ export interface ISearchSetup { } export interface ISearchStart< - SearchStrategyRequest extends IEsSearchRequest = IEsSearchRequest, - SearchStrategyResponse extends IEsSearchResponse = IEsSearchResponse + SearchStrategyRequest extends IKibanaSearchRequest = IEsSearchRequest, + SearchStrategyResponse extends IKibanaSearchResponse = IEsSearchResponse > { aggs: AggsStart; /** @@ -66,9 +71,12 @@ export interface ISearchStart< ) => ISearchStrategy; search: ( context: RequestHandlerContext, - request: IEsSearchRequest, + request: SearchStrategyRequest, options: ISearchOptions - ) => Promise; + ) => Promise; + searchSource: { + asScoped: (request: KibanaRequest) => Promise; + }; } /** @@ -76,8 +84,8 @@ export interface ISearchStart< * that resolves to a response. */ export interface ISearchStrategy< - SearchStrategyRequest extends IEsSearchRequest = IEsSearchRequest, - SearchStrategyResponse extends IEsSearchResponse = IEsSearchResponse + SearchStrategyRequest extends IKibanaSearchRequest = IEsSearchRequest, + SearchStrategyResponse extends IKibanaSearchResponse = IEsSearchResponse > { search: ( context: RequestHandlerContext, diff --git a/src/plugins/data/server/server.api.md b/src/plugins/data/server/server.api.md index c48aa8397dc83..07afad1c96a06 100644 --- a/src/plugins/data/server/server.api.md +++ b/src/plugins/data/server/server.api.md @@ -5,170 +5,53 @@ ```ts import { $Values } from '@kbn/utility-types'; -import { ApiResponse } from '@elastic/elasticsearch/lib/Transport'; +import { ApiResponse } from '@elastic/elasticsearch'; import { Assign } from '@kbn/utility-types'; -import Boom from 'boom'; -import { BulkIndexDocumentsParams } from 'elasticsearch'; -import { CatAliasesParams } from 'elasticsearch'; -import { CatAllocationParams } from 'elasticsearch'; -import { CatCommonParams } from 'elasticsearch'; -import { CatFielddataParams } from 'elasticsearch'; -import { CatHealthParams } from 'elasticsearch'; -import { CatHelpParams } from 'elasticsearch'; -import { CatIndicesParams } from 'elasticsearch'; -import { CatRecoveryParams } from 'elasticsearch'; -import { CatSegmentsParams } from 'elasticsearch'; -import { CatShardsParams } from 'elasticsearch'; -import { CatSnapshotsParams } from 'elasticsearch'; -import { CatTasksParams } from 'elasticsearch'; -import { CatThreadPoolParams } from 'elasticsearch'; -import { ClearScrollParams } from 'elasticsearch'; -import { Client } from 'elasticsearch'; -import { ClusterAllocationExplainParams } from 'elasticsearch'; -import { ClusterGetSettingsParams } from 'elasticsearch'; -import { ClusterHealthParams } from 'elasticsearch'; -import { ClusterPendingTasksParams } from 'elasticsearch'; -import { ClusterPutSettingsParams } from 'elasticsearch'; -import { ClusterRerouteParams } from 'elasticsearch'; -import { ClusterStateParams } from 'elasticsearch'; -import { ClusterStatsParams } from 'elasticsearch'; +import { BehaviorSubject } from 'rxjs'; import { ConfigDeprecationProvider } from '@kbn/config'; import { CoreSetup } from 'src/core/server'; import { CoreSetup as CoreSetup_2 } from 'kibana/server'; import { CoreStart } from 'src/core/server'; -import { CountParams } from 'elasticsearch'; -import { CreateDocumentParams } from 'elasticsearch'; -import { DeleteDocumentByQueryParams } from 'elasticsearch'; -import { DeleteDocumentParams } from 'elasticsearch'; -import { DeleteScriptParams } from 'elasticsearch'; -import { DeleteTemplateParams } from 'elasticsearch'; +import { CoreStart as CoreStart_2 } from 'kibana/server'; import { Duration } from 'moment'; +import { ElasticsearchClient } from 'kibana/server'; import { Ensure } from '@kbn/utility-types'; import { EnvironmentMode } from '@kbn/config'; import { ErrorToastOptions } from 'src/core/public/notifications'; -import { ExistsParams } from 'elasticsearch'; -import { ExplainParams } from 'elasticsearch'; import { ExpressionAstFunction } from 'src/plugins/expressions/common'; import { ExpressionsServerSetup } from 'src/plugins/expressions/server'; -import { FieldStatsParams } from 'elasticsearch'; -import { GenericParams } from 'elasticsearch'; -import { GetParams } from 'elasticsearch'; -import { GetResponse } from 'elasticsearch'; -import { GetScriptParams } from 'elasticsearch'; -import { GetSourceParams } from 'elasticsearch'; -import { GetTemplateParams } from 'elasticsearch'; -import { IncomingHttpHeaders } from 'http'; -import { IndexDocumentParams } from 'elasticsearch'; -import { IndicesAnalyzeParams } from 'elasticsearch'; -import { IndicesClearCacheParams } from 'elasticsearch'; -import { IndicesCloseParams } from 'elasticsearch'; -import { IndicesCreateParams } from 'elasticsearch'; -import { IndicesDeleteAliasParams } from 'elasticsearch'; -import { IndicesDeleteParams } from 'elasticsearch'; -import { IndicesDeleteTemplateParams } from 'elasticsearch'; -import { IndicesExistsAliasParams } from 'elasticsearch'; -import { IndicesExistsParams } from 'elasticsearch'; -import { IndicesExistsTemplateParams } from 'elasticsearch'; -import { IndicesExistsTypeParams } from 'elasticsearch'; -import { IndicesFlushParams } from 'elasticsearch'; -import { IndicesFlushSyncedParams } from 'elasticsearch'; -import { IndicesForcemergeParams } from 'elasticsearch'; -import { IndicesGetAliasParams } from 'elasticsearch'; -import { IndicesGetFieldMappingParams } from 'elasticsearch'; -import { IndicesGetMappingParams } from 'elasticsearch'; -import { IndicesGetParams } from 'elasticsearch'; -import { IndicesGetSettingsParams } from 'elasticsearch'; -import { IndicesGetTemplateParams } from 'elasticsearch'; -import { IndicesGetUpgradeParams } from 'elasticsearch'; -import { IndicesOpenParams } from 'elasticsearch'; -import { IndicesPutAliasParams } from 'elasticsearch'; -import { IndicesPutMappingParams } from 'elasticsearch'; -import { IndicesPutSettingsParams } from 'elasticsearch'; -import { IndicesPutTemplateParams } from 'elasticsearch'; -import { IndicesRecoveryParams } from 'elasticsearch'; -import { IndicesRefreshParams } from 'elasticsearch'; -import { IndicesRolloverParams } from 'elasticsearch'; -import { IndicesSegmentsParams } from 'elasticsearch'; -import { IndicesShardStoresParams } from 'elasticsearch'; -import { IndicesShrinkParams } from 'elasticsearch'; -import { IndicesStatsParams } from 'elasticsearch'; -import { IndicesUpdateAliasesParams } from 'elasticsearch'; -import { IndicesUpgradeParams } from 'elasticsearch'; -import { IndicesValidateQueryParams } from 'elasticsearch'; -import { InfoParams } from 'elasticsearch'; -import { IngestDeletePipelineParams } from 'elasticsearch'; -import { IngestGetPipelineParams } from 'elasticsearch'; -import { IngestPutPipelineParams } from 'elasticsearch'; -import { IngestSimulateParams } from 'elasticsearch'; import { ISearchOptions as ISearchOptions_2 } from 'src/plugins/data/public'; import { ISearchSource } from 'src/plugins/data/public'; -import { KibanaClient } from '@elastic/elasticsearch/api/kibana'; -import { KibanaConfigType as KibanaConfigType_2 } from 'src/core/server/kibana_config'; -import { KibanaRequest } from 'kibana/server'; -import { LegacyAPICaller as LegacyAPICaller_2 } from 'kibana/server'; -import { Logger } from '@kbn/logging'; -import { Logger as Logger_2 } from 'kibana/server'; +import { KibanaRequest } from 'src/core/server'; +import { LegacyAPICaller } from 'kibana/server'; +import { Logger } from 'kibana/server'; import { LoggerFactory } from '@kbn/logging'; -import { LogMeta } from '@kbn/logging'; -import { MGetParams } from 'elasticsearch'; -import { MGetResponse } from 'elasticsearch'; import { Moment } from 'moment'; import moment from 'moment'; -import { MSearchParams } from 'elasticsearch'; -import { MSearchResponse } from 'elasticsearch'; -import { MSearchTemplateParams } from 'elasticsearch'; -import { MTermVectorsParams } from 'elasticsearch'; -import { NodesHotThreadsParams } from 'elasticsearch'; -import { NodesInfoParams } from 'elasticsearch'; -import { NodesStatsParams } from 'elasticsearch'; +import { NameList } from 'elasticsearch'; import { Observable } from 'rxjs'; import { PackageInfo } from '@kbn/config'; import { PathConfigType } from '@kbn/utils'; -import { PingParams } from 'elasticsearch'; import { Plugin as Plugin_2 } from 'src/core/server'; +import { Plugin as Plugin_3 } from 'kibana/server'; import { PluginInitializerContext as PluginInitializerContext_2 } from 'src/core/server'; -import { PutScriptParams } from 'elasticsearch'; -import { PutTemplateParams } from 'elasticsearch'; import { RecursiveReadonly } from '@kbn/utility-types'; -import { ReindexParams } from 'elasticsearch'; -import { ReindexRethrottleParams } from 'elasticsearch'; -import { RenderSearchTemplateParams } from 'elasticsearch'; import { RequestAdapter } from 'src/plugins/inspector/common'; +import { RequestHandlerContext } from 'src/core/server'; import { RequestStatistics } from 'src/plugins/inspector/common'; import { SavedObject } from 'src/core/server'; -import { SavedObjectsClientContract as SavedObjectsClientContract_2 } from 'src/core/server'; -import { ScrollParams } from 'elasticsearch'; +import { SavedObjectsClientContract } from 'src/core/server'; +import { SavedObjectsClientContract as SavedObjectsClientContract_2 } from 'kibana/server'; import { Search } from '@elastic/elasticsearch/api/requestParams'; -import { SearchParams } from 'elasticsearch'; import { SearchResponse } from 'elasticsearch'; -import { SearchShardsParams } from 'elasticsearch'; -import { SearchTemplateParams } from 'elasticsearch'; import { SerializedFieldFormat as SerializedFieldFormat_2 } from 'src/plugins/expressions/common'; import { ShardsResponse } from 'elasticsearch'; -import { SnapshotCreateParams } from 'elasticsearch'; -import { SnapshotCreateRepositoryParams } from 'elasticsearch'; -import { SnapshotDeleteParams } from 'elasticsearch'; -import { SnapshotDeleteRepositoryParams } from 'elasticsearch'; -import { SnapshotGetParams } from 'elasticsearch'; -import { SnapshotGetRepositoryParams } from 'elasticsearch'; -import { SnapshotRestoreParams } from 'elasticsearch'; -import { SnapshotStatusParams } from 'elasticsearch'; -import { SnapshotVerifyRepositoryParams } from 'elasticsearch'; -import { SuggestParams } from 'elasticsearch'; -import { TasksCancelParams } from 'elasticsearch'; -import { TasksGetParams } from 'elasticsearch'; -import { TasksListParams } from 'elasticsearch'; -import { TermvectorsParams } from 'elasticsearch'; import { ToastInputFields } from 'src/core/public/notifications'; -import { TransportRequestOptions } from '@elastic/elasticsearch/lib/Transport'; -import { TransportRequestParams } from '@elastic/elasticsearch/lib/Transport'; import { TransportRequestPromise } from '@elastic/elasticsearch/lib/Transport'; import { Type } from '@kbn/config-schema'; import { TypeOf } from '@kbn/config-schema'; import { Unit } from '@elastic/datemath'; import { UnwrapPromiseOrReturn } from '@kbn/utility-types'; -import { UpdateDocumentByQueryParams } from 'elasticsearch'; -import { UpdateDocumentParams } from 'elasticsearch'; // Warning: (ae-forgotten-export) The symbol "AggConfigSerialized" needs to be exported by the entry point index.d.ts // Warning: (ae-missing-release-tag) "AggConfigOptions" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) @@ -396,6 +279,32 @@ export interface EsQueryConfig { queryStringOptions: Record; } +// Warning: (ae-missing-release-tag) "FieldDescriptor" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +interface FieldDescriptor { + // (undocumented) + aggregatable: boolean; + // (undocumented) + esTypes: string[]; + // (undocumented) + name: string; + // (undocumented) + readFromDocValues: boolean; + // (undocumented) + searchable: boolean; + // Warning: (ae-forgotten-export) The symbol "FieldSubType" needs to be exported by the entry point index.d.ts + // + // (undocumented) + subType?: FieldSubType; + // (undocumented) + type: string; +} + +export { FieldDescriptor } + +export { FieldDescriptor as IndexPatternFieldDescriptor } + // Warning: (ae-missing-release-tag) "FieldFormatConfig" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) @@ -446,6 +355,12 @@ export type Filter = { query?: any; }; +// @internal (undocumented) +export const getAsyncOptions: () => { + waitForCompletionTimeout: string; + keepAlive: string; +}; + // Warning: (ae-forgotten-export) The symbol "IUiSettingsClient" needs to be exported by the entry point index.d.ts // Warning: (ae-missing-release-tag) "getDefaultSearchParams" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // @@ -467,6 +382,7 @@ export function getShardTimeout(config: SharedGlobalConfig): { timeout?: undefined; }; +// Warning: (ae-forgotten-export) The symbol "IIndexPattern" needs to be exported by the entry point index.d.ts // Warning: (ae-missing-release-tag) "getTime" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) @@ -498,28 +414,20 @@ export type IAggConfigs = AggConfigs; export type IAggType = AggType; // Warning: (ae-forgotten-export) The symbol "IKibanaSearchRequest" needs to be exported by the entry point index.d.ts +// Warning: (ae-forgotten-export) The symbol "ISearchRequestParams" needs to be exported by the entry point index.d.ts // Warning: (ae-missing-release-tag) "IEsSearchRequest" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) -export interface IEsSearchRequest extends IKibanaSearchRequest { +export interface IEsSearchRequest extends IKibanaSearchRequest { // (undocumented) indexType?: string; - // Warning: (ae-forgotten-export) The symbol "ISearchRequestParams" needs to be exported by the entry point index.d.ts - // - // (undocumented) - params?: ISearchRequestParams; } // Warning: (ae-forgotten-export) The symbol "IKibanaSearchResponse" needs to be exported by the entry point index.d.ts // Warning: (ae-missing-release-tag) "IEsSearchResponse" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) -export interface IEsSearchResponse extends IKibanaSearchResponse { - isPartial?: boolean; - isRunning?: boolean; - // (undocumented) - rawResponse: SearchResponse; -} +export type IEsSearchResponse = IKibanaSearchResponse>; // Warning: (ae-missing-release-tag) "IFieldFormatsRegistry" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // @@ -590,40 +498,125 @@ export interface IFieldType { visualizable?: boolean; } -// Warning: (ae-missing-release-tag) "IIndexPattern" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// Warning: (ae-forgotten-export) The symbol "MetricAggType" needs to be exported by the entry point index.d.ts +// Warning: (ae-missing-release-tag) "IMetricAggType" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type IMetricAggType = MetricAggType; + +// Warning: (ae-missing-release-tag) "IndexPattern" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) -export interface IIndexPattern { +export class IndexPattern implements IIndexPattern { + // Warning: (ae-forgotten-export) The symbol "IndexPatternDeps" needs to be exported by the entry point index.d.ts + constructor({ spec, fieldFormats, shortDotsEnable, metaFields, }: IndexPatternDeps); + addScriptedField(name: string, script: string, fieldType?: string): Promise; // (undocumented) - [key: string]: any; + fieldFormatMap: Record; + // Warning: (ae-forgotten-export) The symbol "IIndexPatternFieldList" needs to be exported by the entry point index.d.ts + // + // (undocumented) + fields: IIndexPatternFieldList & { + toSpec: () => IndexPatternFieldMap; + }; // (undocumented) - fieldFormatMap?: Record; + flattenHit: (hit: Record, deep?: boolean) => Record; // (undocumented) - fields: IFieldType[]; + formatField: FormatFieldFn; // (undocumented) - getTimeField?(): IFieldType | undefined; + formatHit: { + (hit: Record, type?: string): any; + formatField: FormatFieldFn; + }; + // (undocumented) + getAggregationRestrictions(): Record> | undefined; + getAsSavedObjectBody(): { + title: string; + timeFieldName: string | undefined; + intervalName: string | undefined; + sourceFilters: string | undefined; + fields: string | undefined; + fieldFormatMap: string | undefined; + type: string | undefined; + typeMeta: string | undefined; + }; + // (undocumented) + getComputedFields(): { + storedFields: string[]; + scriptFields: any; + docvalueFields: { + field: any; + format: string; + }[]; + }; + // (undocumented) + getFieldByName(name: string): IndexPatternField | undefined; + getFormatterForField(field: IndexPatternField | IndexPatternField['spec'] | IFieldType): FieldFormat; + // Warning: (ae-forgotten-export) The symbol "IndexPatternField" needs to be exported by the entry point index.d.ts + // + // (undocumented) + getNonScriptedFields(): IndexPatternField[]; + getOriginalSavedObjectBody: () => { + title?: string | undefined; + timeFieldName?: string | undefined; + intervalName?: string | undefined; + fields?: string | undefined; + sourceFilters?: string | undefined; + fieldFormatMap?: string | undefined; + typeMeta?: string | undefined; + type?: string | undefined; + }; + // (undocumented) + getScriptedFields(): IndexPatternField[]; + getSourceFiltering(): { + excludes: any[]; + }; + // (undocumented) + getTimeField(): IndexPatternField | undefined; // (undocumented) id?: string; // (undocumented) - timeFieldName?: string; + intervalName: string | undefined; + // (undocumented) + isTimeBased(): boolean; + // (undocumented) + isTimeNanosBased(): boolean; + // (undocumented) + metaFields: string[]; + removeScriptedField(fieldName: string): void; + resetOriginalSavedObjectBody: () => void; + // Warning: (ae-forgotten-export) The symbol "SourceFilter" needs to be exported by the entry point index.d.ts + // + // (undocumented) + sourceFilters?: SourceFilter[]; + // (undocumented) + timeFieldName: string | undefined; // (undocumented) title: string; + // Warning: (ae-forgotten-export) The symbol "IndexPatternSpec" needs to be exported by the entry point index.d.ts + // + // (undocumented) + toSpec(): IndexPatternSpec; + // (undocumented) + type: string | undefined; + // Warning: (ae-forgotten-export) The symbol "TypeMeta" needs to be exported by the entry point index.d.ts + // + // (undocumented) + typeMeta?: TypeMeta; // (undocumented) - type?: string; + version: string | undefined; } -// Warning: (ae-forgotten-export) The symbol "MetricAggType" needs to be exported by the entry point index.d.ts -// Warning: (ae-missing-release-tag) "IMetricAggType" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) -export type IMetricAggType = MetricAggType; - // Warning: (ae-missing-release-tag) "IndexPatternAttributes" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // -// @public @deprecated +// @public (undocumented) export interface IndexPatternAttributes { // (undocumented) fieldFormatMap?: string; @@ -643,28 +636,6 @@ export interface IndexPatternAttributes { typeMeta: string; } -// Warning: (ae-missing-release-tag) "FieldDescriptor" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) -export interface IndexPatternFieldDescriptor { - // (undocumented) - aggregatable: boolean; - // (undocumented) - esTypes: string[]; - // (undocumented) - name: string; - // (undocumented) - readFromDocValues: boolean; - // (undocumented) - searchable: boolean; - // Warning: (ae-forgotten-export) The symbol "FieldSubType" needs to be exported by the entry point index.d.ts - // - // (undocumented) - subType?: FieldSubType; - // (undocumented) - type: string; -} - // Warning: (ae-missing-release-tag) "indexPatterns" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) @@ -677,17 +648,35 @@ export const indexPatterns: { // // @public (undocumented) export class IndexPatternsFetcher { - constructor(callDataCluster: LegacyAPICaller_2); + constructor(callDataCluster: LegacyAPICaller); getFieldsForTimePattern(options: { pattern: string; metaFields: string[]; lookBack: number; interval: string; - }): Promise; + }): Promise; getFieldsForWildcard(options: { pattern: string | string[]; metaFields?: string[]; - }): Promise; + fieldCapsOptions?: { + allowNoIndices: boolean; + }; + }): Promise; +} + +// Warning: (ae-forgotten-export) The symbol "IndexPatternsServiceStart" needs to be exported by the entry point index.d.ts +// Warning: (ae-missing-release-tag) "IndexPatternsService" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export class IndexPatternsService implements Plugin_3 { + // (undocumented) + setup(core: CoreSetup_2): void; + // Warning: (ae-forgotten-export) The symbol "IndexPatternsServiceStartDeps" needs to be exported by the entry point index.d.ts + // + // (undocumented) + start(core: CoreStart_2, { fieldFormats, logger }: IndexPatternsServiceStartDeps): { + indexPatternsServiceFactory: (savedObjectsClient: SavedObjectsClientContract_2) => Promise; + }; } // Warning: (ae-missing-release-tag) "ISearchOptions" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) @@ -710,29 +699,31 @@ export interface ISearchSetup { // // (undocumented) aggs: AggsSetup; - registerSearchStrategy: (name: string, strategy: ISearchStrategy) => void; + registerSearchStrategy: (name: string, strategy: ISearchStrategy) => void; usage?: SearchUsage; } // Warning: (ae-missing-release-tag) "ISearchStart" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) -export interface ISearchStart { +export interface ISearchStart { // Warning: (ae-forgotten-export) The symbol "AggsStart" needs to be exported by the entry point index.d.ts // // (undocumented) aggs: AggsStart; getSearchStrategy: (name: string) => ISearchStrategy; - // Warning: (ae-forgotten-export) The symbol "RequestHandlerContext" needs to be exported by the entry point index.d.ts - // // (undocumented) - search: (context: RequestHandlerContext, request: IEsSearchRequest, options: ISearchOptions) => Promise; + search: (context: RequestHandlerContext, request: SearchStrategyRequest, options: ISearchOptions) => Promise; + // (undocumented) + searchSource: { + asScoped: (request: KibanaRequest) => Promise; + }; } // Warning: (ae-missing-release-tag) "ISearchStrategy" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public -export interface ISearchStrategy { +export interface ISearchStrategy { // (undocumented) cancel?: (context: RequestHandlerContext, id: string) => Promise; // (undocumented) @@ -884,13 +875,13 @@ export class Plugin implements Plugin_2>; fieldFormats: { fieldFormatServiceFactory: (uiSettings: import("../../../core/server").IUiSettingsClient) => Promise; }; indexPatterns: { - indexPatternsServiceFactory: (kibanaRequest: import("../../../core/server").KibanaRequest) => Promise; + indexPatternsServiceFactory: (savedObjectsClient: Pick) => Promise; }; + search: ISearchStart>; }; // (undocumented) stop(): void; @@ -923,8 +914,6 @@ export interface PluginStart { // // (undocumented) fieldFormats: FieldFormatsStart; - // Warning: (ae-forgotten-export) The symbol "IndexPatternsServiceStart" needs to be exported by the entry point index.d.ts - // // (undocumented) indexPatterns: IndexPatternsServiceStart; // (undocumented) @@ -998,6 +987,9 @@ export interface SearchUsage { trackSuccess(duration: number): Promise; } +// @internal +export const shimAbortSignal: >(promise: T, signal: AbortSignal | undefined) => T; + // @internal export function shimHitsTotal(response: SearchResponse): { hits: { @@ -1110,7 +1102,8 @@ export function usageProvider(core: CoreSetup_2): SearchUsage; // // src/plugins/data/common/es_query/filters/meta_filter.ts:53:3 - (ae-forgotten-export) The symbol "FilterState" needs to be exported by the entry point index.d.ts // src/plugins/data/common/es_query/filters/meta_filter.ts:54:3 - (ae-forgotten-export) The symbol "FilterMeta" needs to be exported by the entry point index.d.ts -// src/plugins/data/common/index_patterns/fields/types.ts:41:25 - (ae-forgotten-export) The symbol "IndexPattern" needs to be exported by the entry point index.d.ts +// src/plugins/data/common/index_patterns/index_patterns/index_pattern.ts:64:45 - (ae-forgotten-export) The symbol "IndexPatternFieldMap" needs to be exported by the entry point index.d.ts +// src/plugins/data/common/index_patterns/index_patterns/index_pattern.ts:70:5 - (ae-forgotten-export) The symbol "FormatFieldFn" needs to be exported by the entry point index.d.ts // src/plugins/data/server/index.ts:40:23 - (ae-forgotten-export) The symbol "buildCustomFilter" needs to be exported by the entry point index.d.ts // src/plugins/data/server/index.ts:40:23 - (ae-forgotten-export) The symbol "buildFilter" needs to be exported by the entry point index.d.ts // src/plugins/data/server/index.ts:71:21 - (ae-forgotten-export) The symbol "getEsQueryConfig" needs to be exported by the entry point index.d.ts @@ -1132,20 +1125,22 @@ export function usageProvider(core: CoreSetup_2): SearchUsage; // src/plugins/data/server/index.ts:101:26 - (ae-forgotten-export) The symbol "TruncateFormat" needs to be exported by the entry point index.d.ts // src/plugins/data/server/index.ts:127:27 - (ae-forgotten-export) The symbol "isFilterable" needs to be exported by the entry point index.d.ts // src/plugins/data/server/index.ts:127:27 - (ae-forgotten-export) The symbol "isNestedField" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:225:20 - (ae-forgotten-export) The symbol "getRequestInspectorStats" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:225:20 - (ae-forgotten-export) The symbol "getResponseInspectorStats" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:225:20 - (ae-forgotten-export) The symbol "tabifyAggResponse" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:225:20 - (ae-forgotten-export) The symbol "tabifyGetColumns" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:227:1 - (ae-forgotten-export) The symbol "CidrMask" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:228:1 - (ae-forgotten-export) The symbol "dateHistogramInterval" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:237:1 - (ae-forgotten-export) The symbol "InvalidEsCalendarIntervalError" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:238:1 - (ae-forgotten-export) The symbol "InvalidEsIntervalFormatError" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:239:1 - (ae-forgotten-export) The symbol "Ipv4Address" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:243:1 - (ae-forgotten-export) The symbol "isValidEsInterval" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:244:1 - (ae-forgotten-export) The symbol "isValidInterval" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:248:1 - (ae-forgotten-export) The symbol "propFilter" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:251:1 - (ae-forgotten-export) The symbol "toAbsoluteDates" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:228:20 - (ae-forgotten-export) The symbol "getRequestInspectorStats" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:228:20 - (ae-forgotten-export) The symbol "getResponseInspectorStats" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:228:20 - (ae-forgotten-export) The symbol "tabifyAggResponse" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:228:20 - (ae-forgotten-export) The symbol "tabifyGetColumns" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:230:1 - (ae-forgotten-export) The symbol "CidrMask" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:231:1 - (ae-forgotten-export) The symbol "dateHistogramInterval" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:240:1 - (ae-forgotten-export) The symbol "InvalidEsCalendarIntervalError" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:241:1 - (ae-forgotten-export) The symbol "InvalidEsIntervalFormatError" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:242:1 - (ae-forgotten-export) The symbol "Ipv4Address" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:246:1 - (ae-forgotten-export) The symbol "isValidEsInterval" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:247:1 - (ae-forgotten-export) The symbol "isValidInterval" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:251:1 - (ae-forgotten-export) The symbol "propFilter" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:254:1 - (ae-forgotten-export) The symbol "toAbsoluteDates" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index_patterns/index_patterns_service.ts:50:14 - (ae-forgotten-export) The symbol "IndexPatternsService" needs to be exported by the entry point index.d.ts // src/plugins/data/server/plugin.ts:88:66 - (ae-forgotten-export) The symbol "DataEnhancements" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/search/types.ts:78:5 - (ae-forgotten-export) The symbol "ISearchStartSearchSource" needs to be exported by the entry point index.d.ts // (No @packageDocumentation comment for this package) diff --git a/src/plugins/discover/common/index.ts b/src/plugins/discover/common/index.ts index 72030d91220b5..4334af63539e3 100644 --- a/src/plugins/discover/common/index.ts +++ b/src/plugins/discover/common/index.ts @@ -27,3 +27,4 @@ export const FIELDS_LIMIT_SETTING = 'fields:popularLimit'; export const CONTEXT_DEFAULT_SIZE_SETTING = 'context:defaultSize'; export const CONTEXT_STEP_SETTING = 'context:step'; export const CONTEXT_TIE_BREAKER_FIELDS_SETTING = 'context:tieBreakerFields'; +export const MODIFY_COLUMNS_ON_SWITCH = 'discover:modifyColumnsOnSwitch'; diff --git a/src/plugins/discover/public/application/angular/context.js b/src/plugins/discover/public/application/angular/context.js index 6223090aa9f97..bb9d71c8671a2 100644 --- a/src/plugins/discover/public/application/angular/context.js +++ b/src/plugins/discover/public/application/angular/context.js @@ -45,26 +45,18 @@ const k7Breadcrumbs = ($route) => { }; getAngularModule().config(($routeProvider) => { - $routeProvider - // deprecated route, kept for compatibility - // should be removed in the future - .when('/context/:indexPatternId/:type/:id*', { - redirectTo: '/context/:indexPatternId/:id', - }) - .when('/context/:indexPatternId/:id*', { - controller: ContextAppRouteController, - k7Breadcrumbs, - controllerAs: 'contextAppRoute', - resolve: { - indexPattern: ($route, Promise) => { - const indexPattern = getServices().indexPatterns.get( - $route.current.params.indexPatternId - ); - return Promise.props({ ip: indexPattern }); - }, + $routeProvider.when('/context/:indexPatternId/:id*', { + controller: ContextAppRouteController, + k7Breadcrumbs, + controllerAs: 'contextAppRoute', + resolve: { + indexPattern: ($route, Promise) => { + const indexPattern = getServices().indexPatterns.get($route.current.params.indexPatternId); + return Promise.props({ ip: indexPattern }); }, - template: contextAppRouteTemplate, - }); + }, + template: contextAppRouteTemplate, + }); }); function ContextAppRouteController($routeParams, $scope, $route) { diff --git a/src/plugins/discover/public/application/angular/context/api/_stubs.js b/src/plugins/discover/public/application/angular/context/api/_stubs.js index 35ddf396c2dba..d82189db60935 100644 --- a/src/plugins/discover/public/application/angular/context/api/_stubs.js +++ b/src/plugins/discover/public/application/angular/context/api/_stubs.js @@ -74,7 +74,7 @@ export function createContextSearchSourceStub(hits, timeField = '@timestamp') { searchSourceStub.fetch = sinon.spy(() => { const timeField = searchSourceStub._stubTimeField; const lastQuery = searchSourceStub.setField.withArgs('query').lastCall.args[1]; - const timeRange = lastQuery.query.constant_score.filter.range[timeField]; + const timeRange = lastQuery.query.bool.must.constant_score.filter.range[timeField]; const lastSort = searchSourceStub.setField.withArgs('sort').lastCall.args[1]; const sortDirection = lastSort[0][timeField]; const sortFunction = diff --git a/src/plugins/discover/public/application/angular/context/api/context.predecessors.test.js b/src/plugins/discover/public/application/angular/context/api/context.predecessors.test.js index 4987c77f4bf25..4c0515906a494 100644 --- a/src/plugins/discover/public/application/angular/context/api/context.predecessors.test.js +++ b/src/plugins/discover/public/application/angular/context/api/context.predecessors.test.js @@ -124,7 +124,9 @@ describe('context app', function () { ).then((hits) => { const intervals = mockSearchSource.setField.args .filter(([property]) => property === 'query') - .map(([, { query }]) => get(query, ['constant_score', 'filter', 'range', '@timestamp'])); + .map(([, { query }]) => + get(query, ['bool', 'must', 'constant_score', 'filter', 'range', '@timestamp']) + ); expect( intervals.every(({ gte, lte }) => (gte && lte ? moment(gte).isBefore(lte) : true)) @@ -160,7 +162,9 @@ describe('context app', function () { ).then((hits) => { const intervals = mockSearchSource.setField.args .filter(([property]) => property === 'query') - .map(([, { query }]) => get(query, ['constant_score', 'filter', 'range', '@timestamp'])); + .map(([, { query }]) => + get(query, ['bool', 'must', 'constant_score', 'filter', 'range', '@timestamp']) + ); // should have started at the given time expect(intervals[0].gte).toEqual(moment(MS_PER_DAY * 1000).toISOString()); diff --git a/src/plugins/discover/public/application/angular/context/api/context.successors.test.js b/src/plugins/discover/public/application/angular/context/api/context.successors.test.js index ebf6e78585962..285d39cd4d8a4 100644 --- a/src/plugins/discover/public/application/angular/context/api/context.successors.test.js +++ b/src/plugins/discover/public/application/angular/context/api/context.successors.test.js @@ -125,7 +125,9 @@ describe('context app', function () { ).then((hits) => { const intervals = mockSearchSource.setField.args .filter(([property]) => property === 'query') - .map(([, { query }]) => get(query, ['constant_score', 'filter', 'range', '@timestamp'])); + .map(([, { query }]) => + get(query, ['bool', 'must', 'constant_score', 'filter', 'range', '@timestamp']) + ); expect( intervals.every(({ gte, lte }) => (gte && lte ? moment(gte).isBefore(lte) : true)) @@ -163,7 +165,9 @@ describe('context app', function () { ).then((hits) => { const intervals = mockSearchSource.setField.args .filter(([property]) => property === 'query') - .map(([, { query }]) => get(query, ['constant_score', 'filter', 'range', '@timestamp'])); + .map(([, { query }]) => + get(query, ['bool', 'must', 'constant_score', 'filter', 'range', '@timestamp']) + ); // should have started at the given time expect(intervals[0].lte).toEqual(moment(MS_PER_DAY * 3000).toISOString()); diff --git a/src/plugins/discover/public/application/angular/context/api/context.ts b/src/plugins/discover/public/application/angular/context/api/context.ts index e244176914a9b..ba8cffd1d7558 100644 --- a/src/plugins/discover/public/application/angular/context/api/context.ts +++ b/src/plugins/discover/public/application/angular/context/api/context.ts @@ -31,6 +31,7 @@ export interface EsHitRecord { fields: Record; sort: number[]; _source: Record; + _id: string; } export type EsHitRecordList = EsHitRecord[]; @@ -100,7 +101,8 @@ function fetchContextProvider(indexPatterns: IndexPatternsContract) { interval, searchAfter, remainingSize, - nanos + nanos, + anchor._id ); documents = diff --git a/src/plugins/discover/public/application/angular/context/api/utils/fetch_hits_in_interval.ts b/src/plugins/discover/public/application/angular/context/api/utils/fetch_hits_in_interval.ts index 9a199ea4a62fc..5ac4164191633 100644 --- a/src/plugins/discover/public/application/angular/context/api/utils/fetch_hits_in_interval.ts +++ b/src/plugins/discover/public/application/angular/context/api/utils/fetch_hits_in_interval.ts @@ -43,7 +43,8 @@ export async function fetchHitsInInterval( interval: IntervalValue[], searchAfter: EsQuerySearchAfter, maxCount: number, - nanosValue: string + nanosValue: string, + anchorId: string ): Promise { const range: RangeQuery = { format: 'strict_date_optional_time', @@ -61,10 +62,19 @@ export async function fetchHitsInInterval( .setField('size', maxCount) .setField('query', { query: { - constant_score: { - filter: { - range: { - [timeField]: range, + bool: { + must: { + constant_score: { + filter: { + range: { + [timeField]: range, + }, + }, + }, + }, + must_not: { + ids: { + values: [anchorId], }, }, }, diff --git a/src/plugins/discover/public/application/angular/context/query_parameters/actions.js b/src/plugins/discover/public/application/angular/context/query_parameters/actions.js index fcd4b8ac02cfb..cdf9283737226 100644 --- a/src/plugins/discover/public/application/angular/context/query_parameters/actions.js +++ b/src/plugins/discover/public/application/angular/context/query_parameters/actions.js @@ -19,6 +19,7 @@ import _ from 'lodash'; import { esFilters } from '../../../../../../data/public'; +import { popularizeField } from '../../../helpers/popularize_field'; import { MAX_CONTEXT_SIZE, MIN_CONTEXT_SIZE, QUERY_PARAMETER_KEYS } from './constants'; @@ -56,7 +57,7 @@ export function getQueryParameterActions(filterManager, indexPatterns) { filterManager.addFilters(newFilters); if (indexPatterns) { const indexPattern = await indexPatterns.get(indexPatternId); - indexPattern.popularizeField(field.name, 1); + await popularizeField(indexPattern, field.name, indexPatterns); } }; diff --git a/src/plugins/discover/public/application/angular/context_app.js b/src/plugins/discover/public/application/angular/context_app.js index f698ed84a8948..145d3afe23224 100644 --- a/src/plugins/discover/public/application/angular/context_app.js +++ b/src/plugins/discover/public/application/angular/context_app.js @@ -56,8 +56,8 @@ getAngularModule().directive('contextApp', function ContextApp() { }); function ContextAppController($scope, Private) { - const { filterManager, indexpatterns, uiSettings } = getServices(); - const queryParameterActions = getQueryParameterActions(filterManager, indexpatterns); + const { filterManager, indexPatterns, uiSettings } = getServices(); + const queryParameterActions = getQueryParameterActions(filterManager, indexPatterns); const queryActions = Private(QueryActionsProvider); this.state = createInitialState( parseInt(uiSettings.get(CONTEXT_STEP_SETTING), 10), diff --git a/src/plugins/discover/public/application/angular/discover.js b/src/plugins/discover/public/application/angular/discover.js index 7871cc4b16464..078a047324113 100644 --- a/src/plugins/discover/public/application/angular/discover.js +++ b/src/plugins/discover/public/application/angular/discover.js @@ -27,6 +27,12 @@ import { i18n } from '@kbn/i18n'; import { getState, splitState } from './discover_state'; import { RequestAdapter } from '../../../../inspector/public'; +import { + esFilters, + indexPatterns as indexPatternsUtils, + connectToQueryState, + syncQueryStateWithUrl, +} from '../../../../data/public'; import { SavedObjectSaveModal, showSaveModal } from '../../../../saved_objects/public'; import { getSortArray, getSortForSearchSource } from './doc_table'; import { createFixedScroll } from './directives/fixed_scroll'; @@ -34,7 +40,6 @@ import * as columnActions from './doc_table/actions/columns'; import indexTemplateLegacy from './discover_legacy.html'; import { showOpenSearchPanel } from '../components/top_nav/show_open_search_panel'; import { addHelpMenuToAppChrome } from '../components/help_menu/help_menu_util'; -import { getPainlessError } from './get_painless_error'; import { discoverResponseHandler } from './response_handler'; import { getRequestInspectorStats, @@ -65,12 +70,8 @@ const { import { getRootBreadcrumbs, getSavedSearchBreadcrumbs } from '../helpers/breadcrumbs'; import { validateTimeRange } from '../helpers/validate_time_range'; -import { - esFilters, - indexPatterns as indexPatternsUtils, - connectToQueryState, - syncQueryStateWithUrl, -} from '../../../../data/public'; +import { popularizeField } from '../helpers/popularize_field'; +import { getSwitchIndexPatternAppState } from '../helpers/get_switch_index_pattern_app_state'; import { getIndexPatternId } from '../helpers/get_index_pattern_id'; import { addFatalError } from '../../../../kibana_legacy/public'; import { @@ -79,6 +80,7 @@ import { SORT_DEFAULT_ORDER_SETTING, SEARCH_ON_PAGE_LOAD_SETTING, DOC_HIDE_TIME_COLUMN_SETTING, + MODIFY_COLUMNS_ON_SWITCH, } from '../../../common'; const fetchStatuses = { @@ -252,6 +254,11 @@ function discoverController($element, $route, $scope, $timeout, $window, Promise if (!_.isEqual(newStatePartial, oldStatePartial)) { $scope.$evalAsync(async () => { + if (oldStatePartial.index !== newStatePartial.index) { + //in case of index switch the route has currently to be reloaded, legacy + return; + } + $scope.state = { ...newState }; // detect changes that should trigger fetching of new data @@ -276,8 +283,18 @@ function discoverController($element, $route, $scope, $timeout, $window, Promise }); $scope.setIndexPattern = async (id) => { - await replaceUrlAppState({ index: id }); - $route.reload(); + const nextIndexPattern = await indexPatterns.get(id); + if (nextIndexPattern) { + const nextAppState = getSwitchIndexPatternAppState( + $scope.indexPattern, + nextIndexPattern, + $scope.state.columns, + $scope.state.sort, + config.get(MODIFY_COLUMNS_ON_SWITCH) + ); + await replaceUrlAppState(nextAppState); + $route.reload(); + } }; // update data source when filters update @@ -786,18 +803,10 @@ function discoverController($element, $route, $scope, $timeout, $window, Promise // If the request was aborted then no need to surface this error in the UI if (error instanceof Error && error.name === 'AbortError') return; - const fetchError = getPainlessError(error); + $scope.fetchStatus = fetchStatuses.NO_RESULTS; + $scope.rows = []; - if (fetchError) { - $scope.fetchError = fetchError; - } else { - toastNotifications.addError(error, { - title: i18n.translate('discover.errorLoadingData', { - defaultMessage: 'Error loading data', - }), - toastMessage: error.shortMessage || error.body?.message, - }); - } + data.search.showError(error); }); }; @@ -960,7 +969,9 @@ function discoverController($element, $route, $scope, $timeout, $window, Promise // TODO: On array fields, negating does not negate the combination, rather all terms $scope.filterQuery = function (field, values, operation) { - $scope.indexPattern.popularizeField(field, 1); + const { indexPattern } = $scope; + + popularizeField(indexPattern, field.name, indexPatterns); const newFilters = esFilters.generateFilters( filterManager, field, @@ -973,7 +984,8 @@ function discoverController($element, $route, $scope, $timeout, $window, Promise $scope.addColumn = function addColumn(columnName) { if (uiCapabilities.discover.save) { - $scope.indexPattern.popularizeField(columnName, 1); + const { indexPattern } = $scope; + popularizeField(indexPattern, columnName, indexPatterns); } const columns = columnActions.addColumn($scope.state.columns, columnName); setAppState({ columns }); @@ -981,7 +993,8 @@ function discoverController($element, $route, $scope, $timeout, $window, Promise $scope.removeColumn = function removeColumn(columnName) { if (uiCapabilities.discover.save) { - $scope.indexPattern.popularizeField(columnName, 1); + const { indexPattern } = $scope; + popularizeField(indexPattern, columnName, indexPatterns); } const columns = columnActions.removeColumn($scope.state.columns, columnName); // The state's sort property is an array of [sortByColumn,sortDirection] diff --git a/src/plugins/discover/public/application/angular/doc_table/components/table_row.ts b/src/plugins/discover/public/application/angular/doc_table/components/table_row.ts index e7fafde2e68d0..17f3199b75b15 100644 --- a/src/plugins/discover/public/application/angular/doc_table/components/table_row.ts +++ b/src/plugins/discover/public/application/angular/doc_table/components/table_row.ts @@ -18,6 +18,7 @@ */ import { find, template } from 'lodash'; +import { stringify } from 'query-string'; import $ from 'jquery'; import rison from 'rison-node'; import '../../doc_viewer'; @@ -25,7 +26,7 @@ import '../../doc_viewer'; import openRowHtml from './table_row/open.html'; import detailsHtml from './table_row/details.html'; -import { dispatchRenderComplete } from '../../../../../../kibana_utils/public'; +import { dispatchRenderComplete, url } from '../../../../../../kibana_utils/public'; import { DOC_HIDE_TIME_COLUMN_SETTING } from '../../../../../common'; import cellTemplateHtml from '../components/table_row/cell.html'; import truncateByHeightTemplateHtml from '../components/table_row/truncate_by_height.html'; @@ -49,7 +50,7 @@ interface LazyScope extends ng.IScope { [key: string]: any; } -export function createTableRowDirective($compile: ng.ICompileService, $httpParamSerializer: any) { +export function createTableRowDirective($compile: ng.ICompileService) { const cellTemplate = template(noWhiteSpace(cellTemplateHtml)); const truncateByHeightTemplate = template(noWhiteSpace(truncateByHeightTemplateHtml)); @@ -108,32 +109,31 @@ export function createTableRowDirective($compile: ng.ICompileService, $httpParam }); $scope.inlineFilter = function inlineFilter($event: any, type: string) { - const column = $($event.target).data().column; + const column = $($event.currentTarget).data().column; const field = $scope.indexPattern.fields.getByName(column); $scope.filter(field, $scope.flattenedRow[column], type); }; $scope.getContextAppHref = () => { - const path = `#/context/${encodeURIComponent($scope.indexPattern.id)}/${encodeURIComponent( - $scope.row._id - )}`; const globalFilters: any = getServices().filterManager.getGlobalFilters(); const appFilters: any = getServices().filterManager.getAppFilters(); - const hash = $httpParamSerializer({ - _g: encodeURI( - rison.encode({ + + const hash = stringify( + url.encodeQuery({ + _g: rison.encode({ filters: globalFilters || [], - }) - ), - _a: encodeURI( - rison.encode({ + }), + _a: rison.encode({ columns: $scope.columns, filters: (appFilters || []).map(esFilters.disableFilter), - }) - ), - }); + }), + }), + { encode: false, sort: false } + ); - return `${path}?${hash}`; + return `#/context/${encodeURIComponent($scope.indexPattern.id)}/${encodeURIComponent( + $scope.row._id + )}?${hash}`; }; // create a tr element that lists the value for each *column* diff --git a/src/plugins/discover/public/application/angular/doc_table/components/table_row/cell.html b/src/plugins/discover/public/application/angular/doc_table/components/table_row/cell.html index e8c4fceeca7ff..0d17c2ca94cac 100644 --- a/src/plugins/discover/public/application/angular/doc_table/components/table_row/cell.html +++ b/src/plugins/discover/public/application/angular/doc_table/components/table_row/cell.html @@ -14,24 +14,24 @@ <% if (filterable) { %> + > + > <% } %> diff --git a/src/plugins/discover/public/application/angular/get_painless_error.ts b/src/plugins/discover/public/application/angular/get_painless_error.ts deleted file mode 100644 index e1e98d9df27b1..0000000000000 --- a/src/plugins/discover/public/application/angular/get_painless_error.ts +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { i18n } from '@kbn/i18n'; -import { get } from 'lodash'; - -export function getPainlessError(error: Error) { - const rootCause: Array<{ lang: string; script: string }> | undefined = get( - error, - 'body.attributes.error.root_cause' - ); - const message: string = get(error, 'body.message'); - - if (!rootCause) { - return; - } - - const [{ lang, script }] = rootCause; - - if (lang !== 'painless') { - return; - } - - return { - lang, - script, - message: i18n.translate('discover.painlessError.painlessScriptedFieldErrorMessage', { - defaultMessage: "Error with Painless scripted field '{script}'.", - values: { script }, - }), - error: message, - }; -} diff --git a/src/plugins/discover/public/application/components/discover_legacy.tsx b/src/plugins/discover/public/application/components/discover_legacy.tsx index 1a98843649259..de1faaf9fc19d 100644 --- a/src/plugins/discover/public/application/components/discover_legacy.tsx +++ b/src/plugins/discover/public/application/components/discover_legacy.tsx @@ -25,13 +25,12 @@ import { IUiSettingsClient, MountPoint } from 'kibana/public'; import { HitsCounter } from './hits_counter'; import { TimechartHeader } from './timechart_header'; import { DiscoverSidebar } from './sidebar'; -import { getServices, IIndexPattern } from '../../kibana_services'; +import { getServices, IndexPattern } from '../../kibana_services'; // @ts-ignore import { DiscoverNoResults } from '../angular/directives/no_results'; import { DiscoverUninitialized } from '../angular/directives/uninitialized'; import { DiscoverHistogram } from '../angular/directives/histogram'; import { LoadingSpinner } from './loading_spinner/loading_spinner'; -import { DiscoverFetchError, FetchError } from './fetch_error/fetch_error'; import { DocTableLegacy } from '../angular/doc_table/create_doc_table_react'; import { SkipBottomButton } from './skip_bottom_button'; import { @@ -54,11 +53,10 @@ export interface DiscoverLegacyProps { addColumn: (column: string) => void; fetch: () => void; fetchCounter: number; - fetchError: FetchError; fieldCounts: Record; histogramData: Chart; hits: number; - indexPattern: IIndexPattern; + indexPattern: IndexPattern; minimumVisibleRows: number; onAddFilter: (field: IndexPatternField | string, value: string, type: '+' | '-') => void; onChangeInterval: (interval: string) => void; @@ -95,7 +93,6 @@ export function DiscoverLegacy({ addColumn, fetch, fetchCounter, - fetchError, fieldCounts, histogramData, hits, @@ -216,8 +213,7 @@ export function DiscoverLegacy({ {resultState === 'uninitialized' && } {/* @TODO: Solved in the Angular way to satisfy functional test - should be improved*/} - {fetchError && } -
+
diff --git a/src/plugins/discover/public/application/components/fetch_error/fetch_error.scss b/src/plugins/discover/public/application/components/fetch_error/fetch_error.scss deleted file mode 100644 index a587b2897e3a0..0000000000000 --- a/src/plugins/discover/public/application/components/fetch_error/fetch_error.scss +++ /dev/null @@ -1,3 +0,0 @@ -.discoverFetchError { - max-width: 1000px; -} diff --git a/src/plugins/discover/public/application/components/fetch_error/fetch_error.tsx b/src/plugins/discover/public/application/components/fetch_error/fetch_error.tsx deleted file mode 100644 index dc8f1238eac6f..0000000000000 --- a/src/plugins/discover/public/application/components/fetch_error/fetch_error.tsx +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -import './fetch_error.scss'; -import React, { Fragment } from 'react'; -import { FormattedMessage, I18nProvider } from '@kbn/i18n/react'; -import { EuiFlexGroup, EuiFlexItem, EuiCallOut, EuiCodeBlock, EuiSpacer } from '@elastic/eui'; -import { getServices } from '../../../kibana_services'; - -export interface FetchError { - lang: string; - script: string; - message: string; - error: string; -} - -interface Props { - fetchError: FetchError; -} - -export const DiscoverFetchError = ({ fetchError }: Props) => { - if (!fetchError) { - return null; - } - - let body; - - if (fetchError.lang === 'painless') { - const { chrome } = getServices(); - const mangagementUrlObj = chrome.navLinks.get('kibana:stack_management'); - const managementUrl = mangagementUrlObj ? mangagementUrlObj.url : ''; - const url = `${managementUrl}/kibana/indexPatterns`; - - body = ( -

- - ), - managementLink: ( - - - - ), - }} - /> -

- ); - } - - return ( - - - - - - - - {body} - - {fetchError.error} - - - - - - - - ); -}; diff --git a/src/plugins/discover/public/application/components/fetch_error/index.ts b/src/plugins/discover/public/application/components/fetch_error/index.ts deleted file mode 100644 index 0206bc48257ac..0000000000000 --- a/src/plugins/discover/public/application/components/fetch_error/index.ts +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import './fetch_error'; diff --git a/src/plugins/discover/public/application/components/sidebar/discover_field.test.tsx b/src/plugins/discover/public/application/components/sidebar/discover_field.test.tsx index b03b37da40908..8ab296bf1af4f 100644 --- a/src/plugins/discover/public/application/components/sidebar/discover_field.test.tsx +++ b/src/plugins/discover/public/application/components/sidebar/discover_field.test.tsx @@ -20,13 +20,12 @@ import React from 'react'; import { findTestSubject } from '@elastic/eui/lib/test'; // @ts-ignore -import StubIndexPattern from 'test_utils/stub_index_pattern'; -// @ts-ignore import stubbedLogstashFields from 'fixtures/logstash_fields'; import { mountWithIntl } from 'test_utils/enzyme_helpers'; import { DiscoverField } from './discover_field'; import { coreMock } from '../../../../../../core/public/mocks'; import { IndexPatternField } from '../../../../../data/public'; +import { getStubIndexPattern } from '../../../../../data/public/test_utils'; jest.mock('../../../kibana_services', () => ({ getServices: () => ({ @@ -52,32 +51,44 @@ jest.mock('../../../kibana_services', () => ({ }), })); -function getComponent(selected = false, showDetails = false, useShortDots = false) { - const indexPattern = new StubIndexPattern( +function getComponent({ + selected = false, + showDetails = false, + useShortDots = false, + field, +}: { + selected?: boolean; + showDetails?: boolean; + useShortDots?: boolean; + field?: IndexPatternField; +}) { + const indexPattern = getStubIndexPattern( 'logstash-*', (cfg: any) => cfg, 'time', stubbedLogstashFields(), - coreMock.createStart() + coreMock.createSetup() ); - const field = new IndexPatternField( - { - name: 'bytes', - type: 'number', - esTypes: ['long'], - count: 10, - scripted: false, - searchable: true, - aggregatable: true, - readFromDocValues: true, - }, - 'bytes' - ); + const finalField = + field ?? + new IndexPatternField( + { + name: 'bytes', + type: 'number', + esTypes: ['long'], + count: 10, + scripted: false, + searchable: true, + aggregatable: true, + readFromDocValues: true, + }, + 'bytes' + ); const props = { indexPattern, - field, + field: finalField, getDetails: jest.fn(() => ({ buckets: [], error: '', exists: 1, total: true, columns: [] })), onAddFilter: jest.fn(), onAddField: jest.fn(), @@ -92,18 +103,37 @@ function getComponent(selected = false, showDetails = false, useShortDots = fals describe('discover sidebar field', function () { it('should allow selecting fields', function () { - const { comp, props } = getComponent(); + const { comp, props } = getComponent({}); findTestSubject(comp, 'fieldToggle-bytes').simulate('click'); expect(props.onAddField).toHaveBeenCalledWith('bytes'); }); it('should allow deselecting fields', function () { - const { comp, props } = getComponent(true); + const { comp, props } = getComponent({ selected: true }); findTestSubject(comp, 'fieldToggle-bytes').simulate('click'); expect(props.onRemoveField).toHaveBeenCalledWith('bytes'); }); it('should trigger getDetails', function () { - const { comp, props } = getComponent(true); + const { comp, props } = getComponent({ selected: true }); findTestSubject(comp, 'field-bytes-showDetails').simulate('click'); expect(props.getDetails).toHaveBeenCalledWith(props.field); }); + it('should not allow clicking on _source', function () { + const field = new IndexPatternField( + { + name: '_source', + type: '_source', + esTypes: ['_source'], + searchable: true, + aggregatable: true, + readFromDocValues: true, + }, + '_source' + ); + const { comp, props } = getComponent({ + selected: true, + field, + }); + findTestSubject(comp, 'field-_source-showDetails').simulate('click'); + expect(props.getDetails).not.toHaveBeenCalled(); + }); }); diff --git a/src/plugins/discover/public/application/components/sidebar/discover_field.tsx b/src/plugins/discover/public/application/components/sidebar/discover_field.tsx index bb330cba68e2e..8ff603884239e 100644 --- a/src/plugins/discover/public/application/components/sidebar/discover_field.tsx +++ b/src/plugins/discover/public/application/components/sidebar/discover_field.tsx @@ -172,6 +172,19 @@ export function DiscoverField({ ); } + if (field.type === '_source') { + return ( + + ); + } + return ( { togglePopover(); }} - buttonProps={{ 'data-test-subj': `field-${field.name}-showDetails` }} + dataTestSubj={`field-${field.name}-showDetails`} fieldIcon={dscFieldIcon} fieldAction={actionButton} fieldName={fieldName} diff --git a/src/plugins/discover/public/application/components/sidebar/discover_sidebar.test.tsx b/src/plugins/discover/public/application/components/sidebar/discover_sidebar.test.tsx index 9572f35641d69..6177b60a0a7ad 100644 --- a/src/plugins/discover/public/application/components/sidebar/discover_sidebar.test.tsx +++ b/src/plugins/discover/public/application/components/sidebar/discover_sidebar.test.tsx @@ -21,8 +21,6 @@ import _ from 'lodash'; import { ReactWrapper } from 'enzyme'; import { findTestSubject } from '@elastic/eui/lib/test'; // @ts-ignore -import StubIndexPattern from 'test_utils/stub_index_pattern'; -// @ts-ignore import realHits from 'fixtures/real_hits.js'; // @ts-ignore import stubbedLogstashFields from 'fixtures/logstash_fields'; @@ -31,6 +29,7 @@ import React from 'react'; import { DiscoverSidebar, DiscoverSidebarProps } from './discover_sidebar'; import { coreMock } from '../../../../../../core/public/mocks'; import { IndexPatternAttributes } from '../../../../../data/common'; +import { getStubIndexPattern } from '../../../../../data/public/test_utils'; import { SavedObject } from '../../../../../../core/types'; jest.mock('../../../kibana_services', () => ({ @@ -65,14 +64,15 @@ jest.mock('./lib/get_index_pattern_field_list', () => ({ })); function getCompProps() { - const indexPattern = new StubIndexPattern( + const indexPattern = getStubIndexPattern( 'logstash-*', (cfg: any) => cfg, 'time', stubbedLogstashFields(), - coreMock.createStart() + coreMock.createSetup() ); + // @ts-expect-error _.each() is passing additional args to flattenHit const hits = _.each(_.cloneDeep(realHits), indexPattern.flattenHit) as Array< Record >; diff --git a/src/plugins/discover/public/application/components/sidebar/lib/field_calculator.test.ts b/src/plugins/discover/public/application/components/sidebar/lib/field_calculator.test.ts index 8746883a5d968..94c76f2d5f012 100644 --- a/src/plugins/discover/public/application/components/sidebar/lib/field_calculator.test.ts +++ b/src/plugins/discover/public/application/components/sidebar/lib/field_calculator.test.ts @@ -21,11 +21,10 @@ import _ from 'lodash'; // @ts-ignore import realHits from 'fixtures/real_hits.js'; // @ts-ignore -import StubIndexPattern from 'test_utils/stub_index_pattern'; -// @ts-ignore import stubbedLogstashFields from 'fixtures/logstash_fields'; import { coreMock } from '../../../../../../../core/public/mocks'; import { IndexPattern } from '../../../../../../data/public'; +import { getStubIndexPattern } from '../../../../../../data/public/test_utils'; // @ts-ignore import { fieldCalculator } from './field_calculator'; @@ -33,12 +32,12 @@ let indexPattern: IndexPattern; describe('fieldCalculator', function () { beforeEach(function () { - indexPattern = new StubIndexPattern( + indexPattern = getStubIndexPattern( 'logstash-*', (cfg: any) => cfg, 'time', stubbedLogstashFields(), - coreMock.createStart() + coreMock.createSetup() ); }); it('should have a _countMissing that counts nulls & undefineds in an array', function () { @@ -142,7 +141,7 @@ describe('fieldCalculator', function () { let hits: any; beforeEach(function () { - hits = _.each(_.cloneDeep(realHits), indexPattern.flattenHit); + hits = _.each(_.cloneDeep(realHits), (hit) => indexPattern.flattenHit(hit)); }); it('Should return an array of values for _source fields', function () { diff --git a/src/plugins/discover/public/application/components/table/table.test.tsx b/src/plugins/discover/public/application/components/table/table.test.tsx index 07e9e0a129a26..2874e2483275b 100644 --- a/src/plugins/discover/public/application/components/table/table.test.tsx +++ b/src/plugins/discover/public/application/components/table/table.test.tsx @@ -22,7 +22,7 @@ import { findTestSubject } from '@elastic/eui/lib/test'; import { DocViewTable } from './table'; import { indexPatterns, IndexPattern } from '../../../../../data/public'; -const indexPattern = { +const indexPattern = ({ fields: { getAll: () => [ { @@ -60,7 +60,7 @@ const indexPattern = { metaFields: ['_index', '_score'], flattenHit: undefined, formatHit: jest.fn((hit) => hit._source), -} as IndexPattern; +} as unknown) as IndexPattern; indexPattern.fields.getByName = (name: string) => { return indexPattern.fields.getAll().find((field) => field.name === name); diff --git a/src/plugins/discover/public/application/embeddable/search_embeddable.ts b/src/plugins/discover/public/application/embeddable/search_embeddable.ts index 1de62fe5a0348..af88cacfcf992 100644 --- a/src/plugins/discover/public/application/embeddable/search_embeddable.ts +++ b/src/plugins/discover/public/application/embeddable/search_embeddable.ts @@ -221,7 +221,6 @@ export class SearchEmbeddable if (!searchScope.columns) { return; } - indexPattern.popularizeField(columnName, 1); const columns = columnActions.addColumn(searchScope.columns, columnName); this.updateInput({ columns }); }; diff --git a/src/plugins/discover/public/application/helpers/get_switch_index_pattern_app_state.test.ts b/src/plugins/discover/public/application/helpers/get_switch_index_pattern_app_state.test.ts new file mode 100644 index 0000000000000..d35346ed24737 --- /dev/null +++ b/src/plugins/discover/public/application/helpers/get_switch_index_pattern_app_state.test.ts @@ -0,0 +1,90 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { getSwitchIndexPatternAppState } from './get_switch_index_pattern_app_state'; +import { IIndexPatternFieldList, IndexPattern } from '../../../../data/common/index_patterns'; + +const currentIndexPattern: IndexPattern = { + id: 'prev', + getFieldByName(name) { + return this.fields.getByName(name); + }, + fields: { + getByName: (name: string) => { + const fields = [ + { name: 'category', sortable: true }, + { name: 'name', sortable: true }, + ] as IIndexPatternFieldList; + return fields.find((field) => field.name === name); + }, + }, +} as IndexPattern; + +const nextIndexPattern = { + id: 'next', + getFieldByName(name) { + return this.fields.getByName(name); + }, + fields: { + getByName: (name: string) => { + const fields = [{ name: 'category', sortable: true }] as IIndexPatternFieldList; + return fields.find((field) => field.name === name); + }, + }, +} as IndexPattern; + +describe('Discover getSwitchIndexPatternAppState', () => { + test('removing fields that are not part of the next index pattern, keeping unknown fields ', async () => { + const result = getSwitchIndexPatternAppState( + currentIndexPattern, + nextIndexPattern, + ['category', 'name', 'unknown'], + [['category', 'desc']] + ); + expect(result.columns).toEqual(['category', 'unknown']); + expect(result.sort).toEqual([['category', 'desc']]); + }); + test('removing sorted by fields that are not part of the next index pattern', async () => { + const result = getSwitchIndexPatternAppState( + currentIndexPattern, + nextIndexPattern, + ['name'], + [ + ['category', 'desc'], + ['name', 'asc'], + ] + ); + expect(result.columns).toEqual(['_source']); + expect(result.sort).toEqual([['category', 'desc']]); + }); + test('removing sorted by fields that without modifying columns', async () => { + const result = getSwitchIndexPatternAppState( + currentIndexPattern, + nextIndexPattern, + ['name'], + [ + ['category', 'desc'], + ['name', 'asc'], + ], + false + ); + expect(result.columns).toEqual(['name']); + expect(result.sort).toEqual([['category', 'desc']]); + }); +}); diff --git a/src/plugins/discover/public/application/helpers/get_switch_index_pattern_app_state.ts b/src/plugins/discover/public/application/helpers/get_switch_index_pattern_app_state.ts new file mode 100644 index 0000000000000..458b9b7e066fd --- /dev/null +++ b/src/plugins/discover/public/application/helpers/get_switch_index_pattern_app_state.ts @@ -0,0 +1,46 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +import { getSortArray } from '../angular/doc_table'; +import { SortPairArr } from '../angular/doc_table/lib/get_sort'; +import { IndexPattern } from '../../kibana_services'; + +/** + * Helper function to remove or adapt the currently selected columns/sort to be valid with the next + * index pattern, returns a new state object + */ +export function getSwitchIndexPatternAppState( + currentIndexPattern: IndexPattern, + nextIndexPattern: IndexPattern, + currentColumns: string[], + currentSort: SortPairArr[], + modifyColumns: boolean = true +) { + const nextColumns = modifyColumns + ? currentColumns.filter( + (column) => + nextIndexPattern.fields.getByName(column) || !currentIndexPattern.fields.getByName(column) + ) + : currentColumns; + const nextSort = getSortArray(currentSort, nextIndexPattern); + return { + index: nextIndexPattern.id, + columns: nextColumns.length ? nextColumns : ['_source'], + sort: nextSort, + }; +} diff --git a/src/plugins/discover/public/application/helpers/popularize_field.test.ts b/src/plugins/discover/public/application/helpers/popularize_field.test.ts new file mode 100644 index 0000000000000..f1ff67c23b92b --- /dev/null +++ b/src/plugins/discover/public/application/helpers/popularize_field.test.ts @@ -0,0 +1,82 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { IndexPattern, IndexPatternsService } from '../../../../data/public'; +import { popularizeField } from './popularize_field'; + +describe('Popularize field', () => { + test('returns undefined if index pattern lacks id', async () => { + const indexPattern = ({} as unknown) as IndexPattern; + const fieldName = '@timestamp'; + const indexPatternsService = ({} as unknown) as IndexPatternsService; + const result = await popularizeField(indexPattern, fieldName, indexPatternsService); + expect(result).toBeUndefined(); + }); + + test('returns undefined if field not found', async () => { + const indexPattern = ({ + fields: { + getByName: () => {}, + }, + } as unknown) as IndexPattern; + const fieldName = '@timestamp'; + const indexPatternsService = ({} as unknown) as IndexPatternsService; + const result = await popularizeField(indexPattern, fieldName, indexPatternsService); + expect(result).toBeUndefined(); + }); + + test('returns undefined if successful', async () => { + const field = { + count: 0, + }; + const indexPattern = ({ + id: 'id', + fields: { + getByName: () => field, + }, + } as unknown) as IndexPattern; + const fieldName = '@timestamp'; + const indexPatternsService = ({ + updateSavedObject: async () => {}, + } as unknown) as IndexPatternsService; + const result = await popularizeField(indexPattern, fieldName, indexPatternsService); + expect(result).toBeUndefined(); + expect(field.count).toEqual(1); + }); + + test('hides errors', async () => { + const field = { + count: 0, + }; + const indexPattern = ({ + id: 'id', + fields: { + getByName: () => field, + }, + } as unknown) as IndexPattern; + const fieldName = '@timestamp'; + const indexPatternsService = ({ + updateSavedObject: async () => { + throw new Error('unknown error'); + }, + } as unknown) as IndexPatternsService; + const result = await popularizeField(indexPattern, fieldName, indexPatternsService); + expect(result).toBeUndefined(); + }); +}); diff --git a/src/plugins/discover/public/application/helpers/popularize_field.ts b/src/plugins/discover/public/application/helpers/popularize_field.ts new file mode 100644 index 0000000000000..0aea86e47c954 --- /dev/null +++ b/src/plugins/discover/public/application/helpers/popularize_field.ts @@ -0,0 +1,41 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { IndexPattern, IndexPatternsService } from '../../../../data/public'; + +async function popularizeField( + indexPattern: IndexPattern, + fieldName: string, + indexPatternsService: IndexPatternsService +) { + if (!indexPattern.id) return; + const field = indexPattern.fields.getByName(fieldName); + if (!field) { + return; + } + + field.count++; + // Catch 409 errors caused by user adding columns in a higher frequency that the changes can be persisted to Elasticsearch + try { + await indexPatternsService.updateSavedObject(indexPattern, 0, true); + // eslint-disable-next-line no-empty + } catch {} +} + +export { popularizeField }; diff --git a/src/plugins/discover/public/plugin.ts b/src/plugins/discover/public/plugin.ts index 440bd3fdf86d3..b1bbc89b62d9d 100644 --- a/src/plugins/discover/public/plugin.ts +++ b/src/plugins/discover/public/plugin.ts @@ -277,6 +277,14 @@ export class DiscoverPlugin return `#${path}`; }); plugins.urlForwarding.forwardApp('context', 'discover', (path) => { + const urlParts = path.split('/'); + // take care of urls containing legacy url, those split in the following way + // ["", "context", indexPatternId, _type, id + params] + if (urlParts[4]) { + // remove _type part + const newPath = [...urlParts.slice(0, 3), ...urlParts.slice(4)].join('/'); + return `#${newPath}`; + } return `#${path}`; }); plugins.urlForwarding.forwardApp('discover', 'discover', (path) => { diff --git a/src/plugins/discover/public/register_feature.ts b/src/plugins/discover/public/register_feature.ts index 5443bb261ab10..9a66936233692 100644 --- a/src/plugins/discover/public/register_feature.ts +++ b/src/plugins/discover/public/register_feature.ts @@ -25,6 +25,9 @@ export function registerFeature(home: HomePublicPluginSetup) { title: i18n.translate('discover.discoverTitle', { defaultMessage: 'Discover', }), + subtitle: i18n.translate('discover.discoverSubtitle', { + defaultMessage: 'Search and find insights.', + }), description: i18n.translate('discover.discoverDescription', { defaultMessage: 'Interactively explore your data by querying and filtering raw documents.', }), @@ -32,5 +35,7 @@ export function registerFeature(home: HomePublicPluginSetup) { path: '/app/discover#/', showOnHomePage: false, category: FeatureCatalogueCategory.DATA, + solutionId: 'kibana', + order: 200, }); } diff --git a/src/plugins/discover/server/saved_objects/search.ts b/src/plugins/discover/server/saved_objects/search.ts index c13550e543ab6..a6e42f956a025 100644 --- a/src/plugins/discover/server/saved_objects/search.ts +++ b/src/plugins/discover/server/saved_objects/search.ts @@ -48,7 +48,7 @@ export const searchSavedObjectType: SavedObjectsType = { hits: { type: 'integer', index: false, doc_values: false }, kibanaSavedObjectMeta: { properties: { - searchSourceJSON: { type: 'text', index: false, doc_values: false }, + searchSourceJSON: { type: 'text', index: false }, }, }, sort: { type: 'keyword', index: false, doc_values: false }, diff --git a/src/plugins/discover/server/saved_objects/search_migrations.test.ts b/src/plugins/discover/server/saved_objects/search_migrations.test.ts index babd25c03dbb2..3324a2d93f5ad 100644 --- a/src/plugins/discover/server/saved_objects/search_migrations.test.ts +++ b/src/plugins/discover/server/saved_objects/search_migrations.test.ts @@ -22,36 +22,61 @@ import { searchMigrations } from './search_migrations'; const savedObjectMigrationContext = (null as unknown) as SavedObjectMigrationContext; +const testMigrateMatchAllQuery = (migrationFn: Function) => { + it('should migrate obsolete match_all query', () => { + const migratedDoc = migrationFn( + { + type: 'search', + attributes: { + kibanaSavedObjectMeta: { + searchSourceJSON: JSON.stringify({ + query: { + match_all: {}, + }, + }), + }, + }, + }, + savedObjectMigrationContext + ); + const migratedSearchSource = JSON.parse( + migratedDoc.attributes.kibanaSavedObjectMeta.searchSourceJSON + ); + + expect(migratedSearchSource).toEqual({ + query: { + query: '', + language: 'kuery', + }, + }); + }); + + it('should return original doc if searchSourceJSON cannot be parsed', () => { + const migratedDoc = migrationFn( + { + type: 'search', + attributes: { + kibanaSavedObjectMeta: 'kibanaSavedObjectMeta', + }, + }, + savedObjectMigrationContext + ); + + expect(migratedDoc).toEqual({ + type: 'search', + attributes: { + kibanaSavedObjectMeta: 'kibanaSavedObjectMeta', + }, + }); + }); +}; + describe('migration search', () => { describe('6.7.2', () => { const migrationFn = searchMigrations['6.7.2']; - it('should migrate obsolete match_all query', () => { - const migratedDoc = migrationFn( - { - type: 'search', - attributes: { - kibanaSavedObjectMeta: { - searchSourceJSON: JSON.stringify({ - query: { - match_all: {}, - }, - }), - }, - }, - }, - savedObjectMigrationContext - ); - const migratedSearchSource = JSON.parse( - migratedDoc.attributes.kibanaSavedObjectMeta.searchSourceJSON - ); - - expect(migratedSearchSource).toEqual({ - query: { - query: '', - language: 'kuery', - }, - }); + describe('migrateMatchAllQuery', () => { + testMigrateMatchAllQuery(migrationFn); }); }); @@ -328,4 +353,12 @@ Object { expect(migratedDoc).toEqual(doc); }); }); + + describe('7.9.3', () => { + const migrationFn = searchMigrations['7.9.3']; + + describe('migrateMatchAllQuery', () => { + testMigrateMatchAllQuery(migrationFn); + }); + }); }); diff --git a/src/plugins/discover/server/saved_objects/search_migrations.ts b/src/plugins/discover/server/saved_objects/search_migrations.ts index 0302159c43c56..fdb086bd17a2d 100644 --- a/src/plugins/discover/server/saved_objects/search_migrations.ts +++ b/src/plugins/discover/server/saved_objects/search_migrations.ts @@ -21,6 +21,12 @@ import { flow, get } from 'lodash'; import { SavedObjectMigrationFn } from 'kibana/server'; import { DEFAULT_QUERY_LANGUAGE } from '../../../data/common'; +/** + * This migration script is related to: + * @link https://github.com/elastic/kibana/pull/62194 + * @link https://github.com/elastic/kibana/pull/14644 + * This is only a problem when you import an object from 5.x into 6.x but to be sure that all saved objects migrated we should execute it twice in 6.7.2 and 7.9.3 + */ const migrateMatchAllQuery: SavedObjectMigrationFn = (doc) => { const searchSourceJSON = get(doc, 'attributes.kibanaSavedObjectMeta.searchSourceJSON'); @@ -31,6 +37,7 @@ const migrateMatchAllQuery: SavedObjectMigrationFn = (doc) => { searchSource = JSON.parse(searchSourceJSON); } catch (e) { // Let it go, the data is invalid and we'll leave it as is + return doc; } if (searchSource.query?.match_all) { @@ -125,4 +132,5 @@ export const searchMigrations = { '6.7.2': flow(migrateMatchAllQuery), '7.0.0': flow(setNewReferences), '7.4.0': flow(migrateSearchSortToNestedArray), + '7.9.3': flow(migrateMatchAllQuery), }; diff --git a/src/plugins/discover/server/ui_settings.ts b/src/plugins/discover/server/ui_settings.ts index 3eca11cc584a9..5447b982eef14 100644 --- a/src/plugins/discover/server/ui_settings.ts +++ b/src/plugins/discover/server/ui_settings.ts @@ -32,6 +32,7 @@ import { CONTEXT_DEFAULT_SIZE_SETTING, CONTEXT_STEP_SETTING, CONTEXT_TIE_BREAKER_FIELDS_SETTING, + MODIFY_COLUMNS_ON_SWITCH, } from '../common'; export const uiSettings: Record = { @@ -163,4 +164,15 @@ export const uiSettings: Record = { category: ['discover'], schema: schema.arrayOf(schema.string()), }, + [MODIFY_COLUMNS_ON_SWITCH]: { + name: i18n.translate('discover.advancedSettings.discover.modifyColumnsOnSwitchTitle', { + defaultMessage: 'Modify columns when changing index patterns', + }), + value: true, + description: i18n.translate('discover.advancedSettings.discover.modifyColumnsOnSwitchText', { + defaultMessage: 'Remove columns that not available in the new index pattern.', + }), + category: ['discover'], + schema: schema.boolean(), + }, }; diff --git a/src/plugins/embeddable/.storybook/main.js b/src/plugins/embeddable/.storybook/main.js new file mode 100644 index 0000000000000..1818aa44a9399 --- /dev/null +++ b/src/plugins/embeddable/.storybook/main.js @@ -0,0 +1,7 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +module.exports = require('@kbn/storybook').defaultConfig; diff --git a/src/plugins/embeddable/README.asciidoc b/src/plugins/embeddable/README.asciidoc new file mode 100644 index 0000000000000..10ec2b840ffa7 --- /dev/null +++ b/src/plugins/embeddable/README.asciidoc @@ -0,0 +1,44 @@ +[[embeddable-plugin]] +== Embeddables plugin + +Embeddables are re-usable widgets that can be rendered in any environment or plugin. Developers can embed them directly in their plugin. End users can dynamically add them to any embeddable _containers_. + +=== Embeddable containers + +Containers are a special type of embeddable that can contain nested embeddables. Embeddables can be dynamically added to embeddable _containers_. Currently only dashboard uses this interface. + +=== Examples + +Many example embeddables are implemented and registered https://github.com/elastic/kibana/tree/master/examples/embeddable_examples[here]. They can be played around with and explored https://github.com/elastic/kibana/tree/master/examples/embeddable_explorer[in the Embeddable Explorer example plugin]. Just run kibana with + +[source,sh] +-- +yarn start --run-examples +-- + +and navigate to the Embeddable explorer app. + +There is also an example of rendering dashboard container outside of dashboard app https://github.com/elastic/kibana/tree/master/examples/dashboard_embeddable_examples[here]. + +=== Docs + +(./docs/README.md)[Embeddable docs, guides & caveats] + +=== API docs + +==== Server API +https://github.com/elastic/kibana/blob/master/docs/development/plugins/embeddable/server/kibana-plugin-plugins-embeddable-server.embeddablesetup.md[Server Setup contract] +https://github.com/elastic/kibana/blob/master/docs/development/plugins/embeddable/server/kibana-plugin-plugins-embeddable-server.embeddablestart.md[Server Start contract] + +===== Browser API +https://github.com/elastic/kibana/blob/master/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablesetup.md[Browser Setup contract] +https://github.com/elastic/kibana/blob/master/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablestart.md[Browser Start contract] + +=== Testing + +Run unit tests + +[source,sh] +-- +node scripts/jest embeddable +-- diff --git a/src/plugins/embeddable/README.md b/src/plugins/embeddable/README.md deleted file mode 100644 index 55abe8606159c..0000000000000 --- a/src/plugins/embeddable/README.md +++ /dev/null @@ -1,31 +0,0 @@ -# Embeddables - -Embeddables are re-usable widgets that can be rendered in any environment or plugin. Developers can embed them directly in their plugin. End users can dynamically add them to any embeddable _containers_. - -## Embeddable containers - -Containers are a special type of embeddable that can contain nested embeddables. Embeddables can be dynamically added to embeddable _containers_. Currently only dashboard uses this interface. - -## Examples - -Many example embeddables are implemented and registered [here](https://github.com/elastic/kibana/tree/master/examples/embeddable_examples). They can be played around with and explored [in the Embeddable Explorer example plugin](https://github.com/elastic/kibana/tree/master/examples/embeddable_explorer). Just run kibana with - -``` -yarn start --run-examples -``` - -and navigate to the Embeddable explorer app. - -There is also an example of rendering dashboard container outside of dashboard app [here](https://github.com/elastic/kibana/tree/master/examples/dashboard_embeddable_examples). - -## Docs - -[Embeddable docs, guides & caveats](./docs/README.md) - -## Testing - -Run unit tests - -```shell -node scripts/jest embeddable -``` diff --git a/src/plugins/embeddable/public/bootstrap.ts b/src/plugins/embeddable/public/bootstrap.ts index 33cf210763b10..5c95214ef591b 100644 --- a/src/plugins/embeddable/public/bootstrap.ts +++ b/src/plugins/embeddable/public/bootstrap.ts @@ -19,7 +19,6 @@ import { UiActionsSetup } from '../../ui_actions/public'; import { contextMenuTrigger, - createFilterAction, panelBadgeTrigger, EmbeddableContext, CONTEXT_MENU_TRIGGER, @@ -29,8 +28,6 @@ import { ACTION_INSPECT_PANEL, REMOVE_PANEL_ACTION, ACTION_EDIT_PANEL, - FilterActionContext, - ACTION_APPLY_FILTER, panelNotificationTrigger, PANEL_NOTIFICATION_TRIGGER, } from './lib'; @@ -48,7 +45,6 @@ declare module '../../ui_actions/public' { [ACTION_INSPECT_PANEL]: EmbeddableContext; [REMOVE_PANEL_ACTION]: EmbeddableContext; [ACTION_EDIT_PANEL]: EmbeddableContext; - [ACTION_APPLY_FILTER]: FilterActionContext; } } @@ -60,8 +56,4 @@ export const bootstrap = (uiActions: UiActionsSetup) => { uiActions.registerTrigger(contextMenuTrigger); uiActions.registerTrigger(panelBadgeTrigger); uiActions.registerTrigger(panelNotificationTrigger); - - const actionApplyFilter = createFilterAction(); - - uiActions.registerAction(actionApplyFilter); }; diff --git a/src/plugins/embeddable/public/components/panel_options_menu/__examples__/panel_options_menu.examples.tsx b/src/plugins/embeddable/public/components/panel_options_menu/__examples__/panel_options_menu.stories.tsx similarity index 100% rename from src/plugins/embeddable/public/components/panel_options_menu/__examples__/panel_options_menu.examples.tsx rename to src/plugins/embeddable/public/components/panel_options_menu/__examples__/panel_options_menu.stories.tsx diff --git a/src/plugins/embeddable/public/index.ts b/src/plugins/embeddable/public/index.ts index c5d8853ada5e8..789353ca4abd7 100644 --- a/src/plugins/embeddable/public/index.ts +++ b/src/plugins/embeddable/public/index.ts @@ -24,7 +24,6 @@ import { EmbeddablePublicPlugin } from './plugin'; export { ACTION_ADD_PANEL, - ACTION_APPLY_FILTER, ACTION_EDIT_PANEL, Adapters, AddPanelAction, @@ -78,6 +77,8 @@ export { EmbeddableRendererProps, } from './lib'; +export { AttributeService, ATTRIBUTE_SERVICE_KEY } from './lib/attribute_service'; + export { EnhancementRegistryDefinition } from './types'; export function plugin(initializerContext: PluginInitializerContext) { diff --git a/src/plugins/embeddable/public/lib/actions/apply_filter_action.test.ts b/src/plugins/embeddable/public/lib/actions/apply_filter_action.test.ts deleted file mode 100644 index 88c1a5917e609..0000000000000 --- a/src/plugins/embeddable/public/lib/actions/apply_filter_action.test.ts +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { createFilterAction } from './apply_filter_action'; -import { expectErrorAsync } from '../../tests/helpers'; -import { defaultTrigger } from '../../../../ui_actions/public/triggers'; - -test('has ACTION_APPLY_FILTER type and id', () => { - const action = createFilterAction(); - expect(action.id).toBe('ACTION_APPLY_FILTER'); - expect(action.type).toBe('ACTION_APPLY_FILTER'); -}); - -test('has expected display name', () => { - const action = createFilterAction(); - expect(action.getDisplayName({} as any)).toMatchInlineSnapshot(`"Apply filter to current view"`); -}); - -describe('getIconType()', () => { - test('returns "filter" icon', async () => { - const action = createFilterAction(); - const result = action.getIconType({} as any); - expect(result).toBe('filter'); - }); -}); - -describe('isCompatible()', () => { - test('when embeddable filters and filters exist, returns true', async () => { - const action = createFilterAction(); - const result = await action.isCompatible({ - embeddable: { - getRoot: () => ({ - getInput: () => ({ - filters: [], - }), - }), - } as any, - filters: [], - trigger: defaultTrigger, - }); - expect(result).toBe(true); - }); - - test('when embeddable filters not set, returns false', async () => { - const action = createFilterAction(); - const result = await action.isCompatible({ - embeddable: { - getRoot: () => ({ - getInput: () => ({ - // filters: [], - }), - }), - } as any, - filters: [], - trigger: defaultTrigger, - }); - expect(result).toBe(false); - }); - - test('when triggerContext or filters are not set, returns false', async () => { - const action = createFilterAction(); - - const result1 = await action.isCompatible({ - embeddable: { - getRoot: () => ({ - getInput: () => ({ - filters: [], - }), - }), - } as any, - } as any); - expect(result1).toBe(false); - }); -}); - -const getEmbeddable = () => { - const root = { - getInput: jest.fn(() => ({ - filters: [], - })), - updateInput: jest.fn(), - }; - const embeddable = { - getRoot: () => root, - } as any; - return [embeddable, root]; -}; - -describe('execute()', () => { - describe('when no filters are given', () => { - test('throws an error', async () => { - const action = createFilterAction(); - const error = await expectErrorAsync(() => - action.execute({ - embeddable: getEmbeddable(), - } as any) - ); - expect(error).toBeInstanceOf(Error); - expect(error.message).toBe('Applying a filter requires a filter and embeddable as context'); - }); - - test('updates filter input on success', async () => { - const action = createFilterAction(); - const [embeddable, root] = getEmbeddable(); - - await action.execute({ - embeddable, - filters: ['FILTER' as any], - trigger: defaultTrigger, - }); - - expect(root.updateInput).toHaveBeenCalledTimes(1); - expect(root.updateInput.mock.calls[0][0]).toMatchObject({ - filters: ['FILTER'], - }); - }); - }); -}); diff --git a/src/plugins/embeddable/public/lib/actions/apply_filter_action.ts b/src/plugins/embeddable/public/lib/actions/apply_filter_action.ts deleted file mode 100644 index 3460203aac29c..0000000000000 --- a/src/plugins/embeddable/public/lib/actions/apply_filter_action.ts +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { i18n } from '@kbn/i18n'; -import { ActionByType, createAction, IncompatibleActionError } from '../ui_actions'; -import { IEmbeddable, EmbeddableInput } from '../embeddables'; -import { Filter } from '../../../../../plugins/data/public'; - -export const ACTION_APPLY_FILTER = 'ACTION_APPLY_FILTER'; - -type RootEmbeddable = IEmbeddable; -export interface FilterActionContext { - embeddable: IEmbeddable; - filters: Filter[]; -} - -async function isCompatible(context: FilterActionContext) { - if (context.embeddable === undefined) { - return false; - } - const root = context.embeddable.getRoot() as RootEmbeddable; - return Boolean(root.getInput().filters !== undefined && context.filters !== undefined); -} - -export function createFilterAction(): ActionByType { - return createAction({ - type: ACTION_APPLY_FILTER, - id: ACTION_APPLY_FILTER, - order: 100, - getIconType: () => 'filter', - getDisplayName: () => { - return i18n.translate('embeddableApi.actions.applyFilterActionTitle', { - defaultMessage: 'Apply filter to current view', - }); - }, - isCompatible, - execute: async ({ embeddable, filters }) => { - if (!filters || !embeddable) { - throw new Error('Applying a filter requires a filter and embeddable as context'); - } - - if (!(await isCompatible({ embeddable, filters }))) { - throw new IncompatibleActionError(); - } - - const root = embeddable.getRoot() as RootEmbeddable; - - root.updateInput({ - filters, - }); - }, - }); -} diff --git a/src/plugins/embeddable/public/lib/actions/edit_panel_action.test.tsx b/src/plugins/embeddable/public/lib/actions/edit_panel_action.test.tsx index 8c3d7ab9c30d0..ba24913c6d1c0 100644 --- a/src/plugins/embeddable/public/lib/actions/edit_panel_action.test.tsx +++ b/src/plugins/embeddable/public/lib/actions/edit_panel_action.test.tsx @@ -18,7 +18,7 @@ */ import { EditPanelAction } from './edit_panel_action'; -import { Embeddable, EmbeddableInput } from '../embeddables'; +import { Embeddable, EmbeddableInput, SavedObjectEmbeddableInput } from '../embeddables'; import { ViewMode } from '../types'; import { ContactCardEmbeddable } from '../test_samples'; import { embeddablePluginMock } from '../../mocks'; @@ -53,20 +53,50 @@ test('is compatible when edit url is available, in edit mode and editable', asyn ).toBe(true); }); -test('redirects to app using state transfer', async () => { +test('redirects to app using state transfer with by value mode', async () => { applicationMock.currentAppId$ = of('superCoolCurrentApp'); const action = new EditPanelAction(getFactory, applicationMock, stateTransferMock); - const input = { id: '123', viewMode: ViewMode.EDIT }; - const embeddable = new EditableEmbeddable(input, true); + const embeddable = new EditableEmbeddable( + ({ + id: '123', + viewMode: ViewMode.EDIT, + coolInput1: 1, + coolInput2: 2, + } as unknown) as EmbeddableInput, + true + ); + embeddable.getOutput = jest.fn(() => ({ editApp: 'ultraVisualize', editPath: '/123' })); + await action.execute({ embeddable }); + expect(stateTransferMock.navigateToEditor).toHaveBeenCalledWith('ultraVisualize', { + path: '/123', + state: { + originatingApp: 'superCoolCurrentApp', + embeddableId: '123', + valueInput: { + id: '123', + viewMode: ViewMode.EDIT, + coolInput1: 1, + coolInput2: 2, + }, + }, + }); +}); + +test('redirects to app using state transfer without by value mode', async () => { + applicationMock.currentAppId$ = of('superCoolCurrentApp'); + const action = new EditPanelAction(getFactory, applicationMock, stateTransferMock); + const embeddable = new EditableEmbeddable( + { id: '123', viewMode: ViewMode.EDIT, savedObjectId: '1234' } as SavedObjectEmbeddableInput, + true + ); embeddable.getOutput = jest.fn(() => ({ editApp: 'ultraVisualize', editPath: '/123' })); await action.execute({ embeddable }); expect(stateTransferMock.navigateToEditor).toHaveBeenCalledWith('ultraVisualize', { path: '/123', state: { originatingApp: 'superCoolCurrentApp', - byValueMode: true, embeddableId: '123', - valueInput: input, + valueInput: undefined, }, }); }); diff --git a/src/plugins/embeddable/public/lib/actions/edit_panel_action.ts b/src/plugins/embeddable/public/lib/actions/edit_panel_action.ts index 8d12ddd0299e7..cbc28713197ba 100644 --- a/src/plugins/embeddable/public/lib/actions/edit_panel_action.ts +++ b/src/plugins/embeddable/public/lib/actions/edit_panel_action.ts @@ -29,6 +29,8 @@ import { EmbeddableEditorState, EmbeddableStateTransfer, SavedObjectEmbeddableInput, + EmbeddableInput, + Container, } from '../..'; export const ACTION_EDIT_PANEL = 'editPanel'; @@ -118,8 +120,7 @@ export class EditPanelAction implements Action { const byValueMode = !(embeddable.getInput() as SavedObjectEmbeddableInput).savedObjectId; const state: EmbeddableEditorState = { originatingApp: this.currentAppId, - byValueMode, - valueInput: byValueMode ? embeddable.getInput() : undefined, + valueInput: byValueMode ? this.getExplicitInput({ embeddable }) : undefined, embeddableId: embeddable.id, }; return { app, path, state }; @@ -132,4 +133,11 @@ export class EditPanelAction implements Action { const editUrl = embeddable ? embeddable.getOutput().editUrl : undefined; return editUrl ? editUrl : ''; } + + private getExplicitInput({ embeddable }: ActionContext): EmbeddableInput { + return ( + (embeddable.getRoot() as Container)?.getInput()?.panels?.[embeddable.id]?.explicitInput ?? + embeddable.getInput() + ); + } } diff --git a/src/plugins/embeddable/public/lib/actions/index.ts b/src/plugins/embeddable/public/lib/actions/index.ts index ea32c6aa2d455..8be2c3f5df450 100644 --- a/src/plugins/embeddable/public/lib/actions/index.ts +++ b/src/plugins/embeddable/public/lib/actions/index.ts @@ -17,5 +17,4 @@ * under the License. */ -export * from './apply_filter_action'; export * from './edit_panel_action'; diff --git a/src/plugins/embeddable/public/lib/attribute_service/attribute_service.mock.tsx b/src/plugins/embeddable/public/lib/attribute_service/attribute_service.mock.tsx new file mode 100644 index 0000000000000..9b08d52ed517c --- /dev/null +++ b/src/plugins/embeddable/public/lib/attribute_service/attribute_service.mock.tsx @@ -0,0 +1,46 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { EmbeddableInput, SavedObjectEmbeddableInput } from '../index'; +import { coreMock } from '../../../../../core/public/mocks'; +import { AttributeServiceOptions } from './attribute_service'; +import { CoreStart } from 'src/core/public'; +import { AttributeService, ATTRIBUTE_SERVICE_KEY } from './index'; + +export const mockAttributeService = < + A extends { title: string }, + V extends EmbeddableInput & { [ATTRIBUTE_SERVICE_KEY]: A } = EmbeddableInput & { + [ATTRIBUTE_SERVICE_KEY]: A; + }, + R extends SavedObjectEmbeddableInput = SavedObjectEmbeddableInput +>( + type: string, + options: AttributeServiceOptions, + customCore?: jest.Mocked +): AttributeService => { + const core = customCore ? customCore : coreMock.createStart(); + return new AttributeService( + type, + jest.fn(), + core.i18n.Context, + core.notifications.toasts, + options, + jest.fn().mockReturnValue(() => ({ getDisplayName: () => type })) + ); +}; diff --git a/src/plugins/embeddable/public/lib/attribute_service/attribute_service.test.ts b/src/plugins/embeddable/public/lib/attribute_service/attribute_service.test.ts new file mode 100644 index 0000000000000..868501adb9687 --- /dev/null +++ b/src/plugins/embeddable/public/lib/attribute_service/attribute_service.test.ts @@ -0,0 +1,202 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { ATTRIBUTE_SERVICE_KEY } from './attribute_service'; +import { mockAttributeService } from './attribute_service.mock'; +import { coreMock } from '../../../../../core/public/mocks'; +import { OnSaveProps } from 'src/plugins/saved_objects/public/save_modal'; + +interface TestAttributes { + title: string; + testAttr1?: string; + testAttr2?: { array: unknown[]; testAttr3: string }; +} + +interface TestByValueInput { + id: string; + [ATTRIBUTE_SERVICE_KEY]: TestAttributes; +} + +describe('attributeService', () => { + const defaultTestType = 'defaultTestType'; + let attributes: TestAttributes; + let byValueInput: TestByValueInput; + let byReferenceInput: { id: string; savedObjectId: string }; + const defaultSaveMethod = ( + type: string, + testAttributes: TestAttributes, + savedObjectId?: string + ): Promise<{ id: string }> => { + return new Promise(() => { + return { id: '123' }; + }); + }; + const defaultUnwrapMethod = (savedObjectId: string): Promise => { + return new Promise(() => { + return { ...attributes }; + }); + }; + const defaultCheckForDuplicateTitle = (props: OnSaveProps): Promise => { + return new Promise(() => { + return true; + }); + }; + const options = { + saveMethod: defaultSaveMethod, + unwrapMethod: defaultUnwrapMethod, + checkForDuplicateTitle: defaultCheckForDuplicateTitle, + }; + + beforeEach(() => { + attributes = { + title: 'ultra title', + testAttr1: 'neat first attribute', + testAttr2: { array: [1, 2, 3], testAttr3: 'super attribute' }, + }; + byValueInput = { + id: '456', + attributes, + }; + byReferenceInput = { + id: '456', + savedObjectId: '123', + }; + }); + + describe('determining input type', () => { + const defaultAttributeService = mockAttributeService(defaultTestType, options); + const customAttributeService = mockAttributeService( + defaultTestType, + options + ); + + it('can determine input type given default types', () => { + expect( + defaultAttributeService.inputIsRefType({ id: '456', savedObjectId: '123' }) + ).toBeTruthy(); + expect( + defaultAttributeService.inputIsRefType({ + id: '456', + attributes: { title: 'wow I am by value' }, + }) + ).toBeFalsy(); + }); + it('can determine input type given custom types', () => { + expect( + customAttributeService.inputIsRefType({ id: '456', savedObjectId: '123' }) + ).toBeTruthy(); + expect( + customAttributeService.inputIsRefType({ + id: '456', + [ATTRIBUTE_SERVICE_KEY]: { title: 'wow I am by value' }, + }) + ).toBeFalsy(); + }); + }); + + describe('unwrapping attributes', () => { + it('does not throw error when given reference type input with no unwrap method', async () => { + const attributeService = mockAttributeService(defaultTestType, { + saveMethod: defaultSaveMethod, + checkForDuplicateTitle: jest.fn(), + }); + expect(await attributeService.unwrapAttributes(byReferenceInput)).toEqual(byReferenceInput); + }); + + it('returns attributes when when given value type input', async () => { + const attributeService = mockAttributeService(defaultTestType, options); + expect(await attributeService.unwrapAttributes(byValueInput)).toEqual(attributes); + }); + + it('runs attributes through a custom unwrap method', async () => { + const attributeService = mockAttributeService(defaultTestType, { + saveMethod: defaultSaveMethod, + unwrapMethod: (savedObjectId) => { + return new Promise((resolve) => { + return resolve({ + ...attributes, + testAttr2: { array: [1, 2, 3, 4, 5], testAttr3: 'kibanana' }, + }); + }); + }, + checkForDuplicateTitle: jest.fn(), + }); + expect(await attributeService.unwrapAttributes(byReferenceInput)).toEqual({ + ...attributes, + testAttr2: { array: [1, 2, 3, 4, 5], testAttr3: 'kibanana' }, + }); + }); + }); + + describe('wrapping attributes', () => { + it('returns given attributes when use ref type is false', async () => { + const attributeService = mockAttributeService(defaultTestType, options); + expect(await attributeService.wrapAttributes(attributes, false)).toEqual({ attributes }); + }); + + it('calls saveMethod with appropriate parameters', async () => { + const core = coreMock.createStart(); + const saveMethod = jest.fn(); + saveMethod.mockReturnValueOnce({}); + const attributeService = mockAttributeService( + defaultTestType, + { + saveMethod, + unwrapMethod: defaultUnwrapMethod, + checkForDuplicateTitle: defaultCheckForDuplicateTitle, + }, + core + ); + expect(await attributeService.wrapAttributes(attributes, true, byReferenceInput)).toEqual( + byReferenceInput + ); + expect(saveMethod).toHaveBeenCalledWith(defaultTestType, attributes, '123'); + }); + + it('uses custom save method when given an id', async () => { + const saveMethod = jest.fn().mockReturnValue({ id: '123' }); + const attributeService = mockAttributeService(defaultTestType, { + saveMethod, + unwrapMethod: defaultUnwrapMethod, + checkForDuplicateTitle: defaultCheckForDuplicateTitle, + }); + expect(await attributeService.wrapAttributes(attributes, true, byReferenceInput)).toEqual( + byReferenceInput + ); + expect(saveMethod).toHaveBeenCalledWith( + defaultTestType, + attributes, + byReferenceInput.savedObjectId + ); + }); + + it('uses custom save method given no id', async () => { + const saveMethod = jest.fn().mockReturnValue({ id: '678' }); + const attributeService = mockAttributeService(defaultTestType, { + saveMethod, + unwrapMethod: defaultUnwrapMethod, + checkForDuplicateTitle: defaultCheckForDuplicateTitle, + }); + expect(await attributeService.wrapAttributes(attributes, true)).toEqual({ + savedObjectId: '678', + }); + expect(saveMethod).toHaveBeenCalledWith(defaultTestType, attributes, undefined); + }); + }); +}); diff --git a/src/plugins/embeddable/public/lib/attribute_service/attribute_service.tsx b/src/plugins/embeddable/public/lib/attribute_service/attribute_service.tsx new file mode 100644 index 0000000000000..c4628ab7fbdba --- /dev/null +++ b/src/plugins/embeddable/public/lib/attribute_service/attribute_service.tsx @@ -0,0 +1,192 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React from 'react'; +import { i18n } from '@kbn/i18n'; +import { get } from 'lodash'; +import { I18nStart, NotificationsStart } from 'src/core/public'; +import { SavedObjectSaveModal, OnSaveProps, SaveResult } from '../../../../saved_objects/public'; +import { + EmbeddableInput, + SavedObjectEmbeddableInput, + isSavedObjectEmbeddableInput, + IEmbeddable, + Container, + EmbeddableFactoryNotFoundError, + EmbeddableFactory, +} from '../index'; + +/** + * The attribute service is a shared, generic service that embeddables can use to provide the functionality + * required to fulfill the requirements of the ReferenceOrValueEmbeddable interface. The attribute_service + * can also be used as a higher level wrapper to transform an embeddable input shape that references a saved object + * into an embeddable input shape that contains that saved object's attributes by value. + */ +export const ATTRIBUTE_SERVICE_KEY = 'attributes'; + +export interface AttributeServiceOptions { + saveMethod: ( + type: string, + attributes: A, + savedObjectId?: string + ) => Promise<{ id?: string } | { error: Error }>; + checkForDuplicateTitle: (props: OnSaveProps) => Promise; + unwrapMethod?: (savedObjectId: string) => Promise; +} + +export class AttributeService< + SavedObjectAttributes extends { title: string }, + ValType extends EmbeddableInput & { + [ATTRIBUTE_SERVICE_KEY]: SavedObjectAttributes; + } = EmbeddableInput & { [ATTRIBUTE_SERVICE_KEY]: SavedObjectAttributes }, + RefType extends SavedObjectEmbeddableInput = SavedObjectEmbeddableInput +> { + constructor( + private type: string, + private showSaveModal: ( + saveModal: React.ReactElement, + I18nContext: I18nStart['Context'] + ) => void, + private i18nContext: I18nStart['Context'], + private toasts: NotificationsStart['toasts'], + private options: AttributeServiceOptions, + getEmbeddableFactory?: (embeddableFactoryId: string) => EmbeddableFactory + ) { + if (getEmbeddableFactory) { + const factory = getEmbeddableFactory(this.type); + if (!factory) { + throw new EmbeddableFactoryNotFoundError(this.type); + } + } + } + + private async defaultUnwrapMethod(input: RefType): Promise { + return new Promise((resolve) => { + // @ts-ignore + return resolve({ ...input }); + }); + } + + public async unwrapAttributes(input: RefType | ValType): Promise { + if (this.inputIsRefType(input)) { + return this.options.unwrapMethod + ? await this.options.unwrapMethod(input.savedObjectId) + : await this.defaultUnwrapMethod(input); + } + return input[ATTRIBUTE_SERVICE_KEY]; + } + + public async wrapAttributes( + newAttributes: SavedObjectAttributes, + useRefType: boolean, + input?: ValType | RefType + ): Promise> { + const originalInput = input ? input : {}; + const savedObjectId = + input && this.inputIsRefType(input) + ? (input as SavedObjectEmbeddableInput).savedObjectId + : undefined; + if (!useRefType) { + return { [ATTRIBUTE_SERVICE_KEY]: newAttributes } as ValType; + } + try { + const savedItem = await this.options.saveMethod(this.type, newAttributes, savedObjectId); + if ('id' in savedItem) { + return { ...originalInput, savedObjectId: savedItem.id } as RefType; + } + return { ...originalInput } as RefType; + } catch (error) { + this.toasts.addDanger({ + title: i18n.translate('embeddableApi.attributeService.saveToLibraryError', { + defaultMessage: `Panel was not saved to the library. Error: {errorMessage}`, + values: { + errorMessage: error.message, + }, + }), + 'data-test-subj': 'saveDashboardFailure', + }); + return Promise.reject({ error }); + } + } + + inputIsRefType = (input: ValType | RefType): input is RefType => { + return isSavedObjectEmbeddableInput(input); + }; + + public getExplicitInputFromEmbeddable(embeddable: IEmbeddable): ValType | RefType { + return ((embeddable.getRoot() as Container).getInput()?.panels?.[embeddable.id] + ?.explicitInput ?? embeddable.getInput()) as ValType | RefType; + } + + getInputAsValueType = async (input: ValType | RefType): Promise => { + if (!this.inputIsRefType(input)) { + return input; + } + const attributes = await this.unwrapAttributes(input); + return { + ...input, + savedObjectId: undefined, + attributes, + }; + }; + + getInputAsRefType = async ( + input: ValType | RefType, + saveOptions?: { showSaveModal: boolean; saveModalTitle?: string } | { title: string } + ): Promise => { + if (this.inputIsRefType(input)) { + return input; + } + return new Promise((resolve, reject) => { + const onSave = async (props: OnSaveProps): Promise => { + await this.options.checkForDuplicateTitle(props); + try { + const newAttributes = { ...input[ATTRIBUTE_SERVICE_KEY] }; + newAttributes.title = props.newTitle; + const wrappedInput = (await this.wrapAttributes(newAttributes, true)) as RefType; + + // Remove unneeded attributes from the original input. + delete (input as { [ATTRIBUTE_SERVICE_KEY]?: SavedObjectAttributes })[ + ATTRIBUTE_SERVICE_KEY + ]; + + // Combine input and wrapped input to preserve any passed in explicit Input. + resolve({ ...input, ...wrappedInput }); + return { id: wrappedInput.savedObjectId }; + } catch (error) { + reject(error); + return { error }; + } + }; + if (saveOptions && (saveOptions as { showSaveModal: boolean }).showSaveModal) { + this.showSaveModal( + reject()} + title={get(saveOptions, 'saveModalTitle', input[ATTRIBUTE_SERVICE_KEY].title)} + showCopyOnSave={false} + objectType={this.type} + showDescription={false} + />, + this.i18nContext + ); + } + }); + }; +} diff --git a/src/plugins/embeddable/public/lib/attribute_service/index.ts b/src/plugins/embeddable/public/lib/attribute_service/index.ts new file mode 100644 index 0000000000000..84d4c8a13c31e --- /dev/null +++ b/src/plugins/embeddable/public/lib/attribute_service/index.ts @@ -0,0 +1,20 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export { AttributeService, ATTRIBUTE_SERVICE_KEY } from './attribute_service'; diff --git a/src/plugins/embeddable/public/lib/containers/container.ts b/src/plugins/embeddable/public/lib/containers/container.ts index 38975cc220bc2..9f701f021162a 100644 --- a/src/plugins/embeddable/public/lib/containers/container.ts +++ b/src/plugins/embeddable/public/lib/containers/container.ts @@ -199,8 +199,8 @@ export abstract class Container< return { type: factory.type, explicitInput: { - id: embeddableId, ...explicitInput, + id: embeddableId, } as TEmbeddableInput, }; } diff --git a/src/plugins/embeddable/public/lib/embeddables/embeddable_renderer.test.tsx b/src/plugins/embeddable/public/lib/embeddables/embeddable_renderer.test.tsx index 51213288e47a7..f9be9d5bfade7 100644 --- a/src/plugins/embeddable/public/lib/embeddables/embeddable_renderer.test.tsx +++ b/src/plugins/embeddable/public/lib/embeddables/embeddable_renderer.test.tsx @@ -19,7 +19,7 @@ import React from 'react'; import { wait } from '@testing-library/dom'; -import { cleanup, render } from '@testing-library/react/pure'; +import { render } from '@testing-library/react'; import { HelloWorldEmbeddable, HelloWorldEmbeddableFactoryDefinition, @@ -29,8 +29,6 @@ import { EmbeddableRenderer } from './embeddable_renderer'; import { embeddablePluginMock } from '../../mocks'; describe('', () => { - afterEach(cleanup); - test('Render embeddable', () => { const embeddable = new HelloWorldEmbeddable({ id: 'hello' }); const { getByTestId } = render(); diff --git a/src/plugins/embeddable/public/lib/embeddables/error_embeddable.test.tsx b/src/plugins/embeddable/public/lib/embeddables/error_embeddable.test.tsx index 715827a72c61b..cb14d7ed11dc9 100644 --- a/src/plugins/embeddable/public/lib/embeddables/error_embeddable.test.tsx +++ b/src/plugins/embeddable/public/lib/embeddables/error_embeddable.test.tsx @@ -17,43 +17,33 @@ * under the License. */ import React from 'react'; +import { wait, render } from '@testing-library/react'; import { ErrorEmbeddable } from './error_embeddable'; import { EmbeddableRoot } from './embeddable_root'; -import { mount } from 'enzyme'; test('ErrorEmbeddable renders an embeddable', async () => { const embeddable = new ErrorEmbeddable('some error occurred', { id: '123', title: 'Error' }); - const component = mount(); - expect( - component.getDOMNode().querySelectorAll('[data-test-subj="embeddableStackError"]').length - ).toBe(1); - expect( - component.getDOMNode().querySelectorAll('[data-test-subj="errorMessageMarkdown"]').length - ).toBe(1); - expect( - component - .getDOMNode() - .querySelectorAll('[data-test-subj="errorMessageMarkdown"]')[0] - .innerHTML.includes('some error occurred') - ).toBe(true); + const { getByTestId, getByText } = render(); + + expect(getByTestId('embeddableStackError')).toBeVisible(); + await wait(() => getByTestId('errorMessageMarkdown')); // wait for lazy markdown component + expect(getByText(/some error occurred/i)).toBeVisible(); }); test('ErrorEmbeddable renders an embeddable with markdown message', async () => { const error = '[some link](http://localhost:5601/takeMeThere)'; const embeddable = new ErrorEmbeddable(error, { id: '123', title: 'Error' }); - const component = mount(); - expect( - component.getDOMNode().querySelectorAll('[data-test-subj="embeddableStackError"]').length - ).toBe(1); - expect( - component.getDOMNode().querySelectorAll('[data-test-subj="errorMessageMarkdown"]').length - ).toBe(1); - expect( - component - .getDOMNode() - .querySelectorAll('[data-test-subj="errorMessageMarkdown"]')[0] - .innerHTML.includes( - 'some link' - ) - ).toBe(true); + const { getByTestId, getByText } = render(); + + expect(getByTestId('embeddableStackError')).toBeVisible(); + await wait(() => getByTestId('errorMessageMarkdown')); // wait for lazy markdown component + expect(getByText(/some link/i)).toMatchInlineSnapshot(` + + some link + + `); }); diff --git a/src/plugins/embeddable/public/lib/panel/_embeddable_panel.scss b/src/plugins/embeddable/public/lib/panel/_embeddable_panel.scss index f6057524cb832..cdc0f9f0e0451 100644 --- a/src/plugins/embeddable/public/lib/panel/_embeddable_panel.scss +++ b/src/plugins/embeddable/public/lib/panel/_embeddable_panel.scss @@ -54,12 +54,23 @@ .embPanel__titleInner { overflow: hidden; display: flex; + align-items: center; padding-right: $euiSizeS; } + .embPanel__titleTooltipAnchor { + max-width: 100%; + } + .embPanel__titleText { @include euiTextTruncate; } + + .embPanel__placeholderTitleText { + @include euiTextTruncate; + font-weight: $euiFontWeightRegular; + color: $euiColorMediumShade; + } } .embPanel__dragger:not(.embPanel__title) { @@ -159,4 +170,4 @@ pointer-events: none; filter: grayscale(100%); filter: gray; -} \ No newline at end of file +} diff --git a/src/plugins/embeddable/public/lib/panel/embeddable_error_label.tsx b/src/plugins/embeddable/public/lib/panel/embeddable_error_label.tsx index 1e4604af9dc09..fa4d7f466caee 100644 --- a/src/plugins/embeddable/public/lib/panel/embeddable_error_label.tsx +++ b/src/plugins/embeddable/public/lib/panel/embeddable_error_label.tsx @@ -40,8 +40,10 @@ export function EmbeddableErrorLabel(props: Props) { return (
- - {labelText} + + + {labelText} +
diff --git a/src/plugins/embeddable/public/lib/panel/embeddable_panel.tsx b/src/plugins/embeddable/public/lib/panel/embeddable_panel.tsx index ca5cb5ca4f0d5..137f8c24b1fae 100644 --- a/src/plugins/embeddable/public/lib/panel/embeddable_panel.tsx +++ b/src/plugins/embeddable/public/lib/panel/embeddable_panel.tsx @@ -20,6 +20,7 @@ import { EuiContextMenuPanelDescriptor, EuiPanel, htmlIdGenerator } from '@elast import classNames from 'classnames'; import React from 'react'; import { Subscription } from 'rxjs'; +import deepEqual from 'fast-deep-equal'; import { buildContextMenuForActions, UiActionsService, Action } from '../ui_actions'; import { CoreStart, OverlayStart } from '../../../../../core/public'; import { toMountPoint } from '../../../../kibana_react/public'; @@ -32,7 +33,12 @@ import { EmbeddableContext, contextMenuTrigger, } from '../triggers'; -import { IEmbeddable, EmbeddableOutput, EmbeddableError } from '../embeddables/i_embeddable'; +import { + IEmbeddable, + EmbeddableOutput, + EmbeddableError, + EmbeddableInput, +} from '../embeddables/i_embeddable'; import { ViewMode } from '../types'; import { RemovePanelAction } from './panel_header/panel_actions'; @@ -55,7 +61,7 @@ const removeById = (disabledActions: string[]) => ({ id }: { id: string }) => disabledActions.indexOf(id) === -1; interface Props { - embeddable: IEmbeddable; + embeddable: IEmbeddable; getActions: UiActionsService['getTriggerCompatibleActions']; getEmbeddableFactory: EmbeddableStart['getEmbeddableFactory']; getAllEmbeddableFactories: EmbeddableStart['getEmbeddableFactories']; @@ -72,7 +78,7 @@ interface State { panels: EuiContextMenuPanelDescriptor[]; focusedPanelIndex?: string; viewMode: ViewMode; - hidePanelTitles: boolean; + hidePanelTitle: boolean; closeContextMenu: boolean; badges: Array>; notifications: Array>; @@ -90,17 +96,15 @@ export class EmbeddablePanel extends React.Component { constructor(props: Props) { super(props); const { embeddable } = this.props; - const viewMode = embeddable.getInput().viewMode - ? embeddable.getInput().viewMode - : ViewMode.EDIT; - const hidePanelTitles = embeddable.parent - ? Boolean(embeddable.parent.getInput().hidePanelTitles) - : false; + const viewMode = embeddable.getInput().viewMode ?? ViewMode.EDIT; + const hidePanelTitle = + Boolean(embeddable.parent?.getInput()?.hidePanelTitles) || + Boolean(embeddable.getInput()?.hidePanelTitles); this.state = { panels: [], viewMode, - hidePanelTitles, + hidePanelTitle, closeContextMenu: false, badges: [], notifications: [], @@ -120,9 +124,11 @@ export class EmbeddablePanel extends React.Component { badges = badges.filter((badge) => disabledActions.indexOf(badge.id) === -1); } - this.setState({ - badges, - }); + if (!deepEqual(this.state.badges, badges)) { + this.setState({ + badges, + }); + } } private async refreshNotifications() { @@ -136,9 +142,11 @@ export class EmbeddablePanel extends React.Component { notifications = notifications.filter((badge) => disabledActions.indexOf(badge.id) === -1); } - this.setState({ - notifications, - }); + if (!deepEqual(this.state.notifications, notifications)) { + this.setState({ + notifications, + }); + } } public UNSAFE_componentWillMount() { @@ -150,9 +158,7 @@ export class EmbeddablePanel extends React.Component { embeddable.getInput$().subscribe(async () => { if (this.mounted) { this.setState({ - viewMode: embeddable.getInput().viewMode - ? embeddable.getInput().viewMode - : ViewMode.EDIT, + viewMode: embeddable.getInput().viewMode ?? ViewMode.EDIT, }); this.refreshBadges(); @@ -165,7 +171,9 @@ export class EmbeddablePanel extends React.Component { this.parentSubscription = parent.getInput$().subscribe(async () => { if (this.mounted && parent) { this.setState({ - hidePanelTitles: Boolean(parent.getInput().hidePanelTitles), + hidePanelTitle: + Boolean(embeddable.parent?.getInput()?.hidePanelTitles) || + Boolean(embeddable.getInput()?.hidePanelTitles), }); this.refreshBadges(); @@ -219,7 +227,7 @@ export class EmbeddablePanel extends React.Component { {!this.props.hideHeader && ( { const createGetUserData = (overlays: OverlayStart) => async function getUserData(context: { embeddable: IEmbeddable }) { - return new Promise<{ title: string | undefined }>((resolve) => { + return new Promise<{ title: string | undefined; hideTitle?: boolean }>((resolve) => { const session = overlays.openModal( toMountPoint( { + updateTitle={(title, hideTitle) => { session.close(); - resolve({ title }); + resolve({ title, hideTitle }); }} + cancel={() => session.close()} /> ), { diff --git a/src/plugins/embeddable/public/lib/panel/panel_header/panel_actions/customize_title/customize_panel_action.ts b/src/plugins/embeddable/public/lib/panel/panel_header/panel_actions/customize_title/customize_panel_action.ts index 36957c3b79491..d65539e344a78 100644 --- a/src/plugins/embeddable/public/lib/panel/panel_header/panel_actions/customize_title/customize_panel_action.ts +++ b/src/plugins/embeddable/public/lib/panel/panel_header/panel_actions/customize_title/customize_panel_action.ts @@ -24,7 +24,9 @@ import { IEmbeddable } from '../../../../embeddables'; export const ACTION_CUSTOMIZE_PANEL = 'ACTION_CUSTOMIZE_PANEL'; -type GetUserData = (context: ActionContext) => Promise<{ title: string | undefined }>; +type GetUserData = ( + context: ActionContext +) => Promise<{ title: string | undefined; hideTitle?: boolean }>; interface ActionContext { embeddable: IEmbeddable; @@ -52,7 +54,8 @@ export class CustomizePanelTitleAction implements Action { } public async execute({ embeddable }: ActionContext) { - const customTitle = await this.getDataFromUser({ embeddable }); - embeddable.updateInput(customTitle); + const data = await this.getDataFromUser({ embeddable }); + const { title, hideTitle } = data; + embeddable.updateInput({ title, hidePanelTitles: hideTitle }); } } diff --git a/src/plugins/embeddable/public/lib/panel/panel_header/panel_actions/customize_title/customize_panel_modal.tsx b/src/plugins/embeddable/public/lib/panel/panel_header/panel_actions/customize_title/customize_panel_modal.tsx index b590f20092939..ad986adb619b8 100644 --- a/src/plugins/embeddable/public/lib/panel/panel_header/panel_actions/customize_title/customize_panel_modal.tsx +++ b/src/plugins/embeddable/public/lib/panel/panel_header/panel_actions/customize_title/customize_panel_modal.tsx @@ -36,31 +36,28 @@ import { IEmbeddable } from '../../../../'; interface CustomizePanelProps { embeddable: IEmbeddable; - updateTitle: (newTitle: string | undefined) => void; + updateTitle: (newTitle: string | undefined, hideTitle: boolean | undefined) => void; + cancel: () => void; } interface State { title: string | undefined; - hideTitle: boolean; + hideTitle: boolean | undefined; } export class CustomizePanelModal extends Component { constructor(props: CustomizePanelProps) { super(props); this.state = { - hideTitle: props.embeddable.getOutput().title === '', - title: props.embeddable.getInput().title, + hideTitle: props.embeddable.getInput().hidePanelTitles, + title: props.embeddable.getInput().title ?? this.props.embeddable.getOutput().defaultTitle, }; } - private updateTitle = (title: string | undefined) => { - // An empty string will mean "use the default value", which is represented by setting - // title to undefined (where as an empty string is actually used to indicate "hide title"). - this.setState({ title: title === '' ? undefined : title }); - }; - private reset = () => { - this.setState({ title: undefined }); + this.setState({ + title: this.props.embeddable.getOutput().defaultTitle, + }); }; private onHideTitleToggle = () => { @@ -70,12 +67,11 @@ export class CustomizePanelModal extends Component { }; private save = () => { - if (this.state.hideTitle) { - this.props.updateTitle(''); - } else { - const newTitle = this.state.title === '' ? undefined : this.state.title; - this.props.updateTitle(newTitle); - } + const newTitle = + this.state.title === this.props.embeddable.getOutput().defaultTitle + ? undefined + : this.state.title; + this.props.updateTitle(newTitle, this.state.hideTitle); }; public render() { @@ -116,9 +112,8 @@ export class CustomizePanelModal extends Component { name="min" type="text" disabled={this.state.hideTitle} - placeholder={this.props.embeddable.getOutput().defaultTitle} value={this.state.title || ''} - onChange={(e) => this.updateTitle(e.target.value)} + onChange={(e) => this.setState({ title: e.target.value })} aria-label={i18n.translate( 'embeddableApi.customizePanel.modal.optionsMenuForm.panelTitleInputAriaLabel', { @@ -141,9 +136,7 @@ export class CustomizePanelModal extends Component { - this.props.updateTitle(this.props.embeddable.getOutput().title)} - > + this.props.cancel()}> Promise; + hidePanelTitle: boolean; + getActionContextMenuPanel: () => Promise; closeContextMenu: boolean; badges: Array>; notifications: Array>; embeddable: IEmbeddable; headerId?: string; + showPlaceholderTitle?: boolean; } function renderBadges(badges: Array>, embeddable: IEmbeddable) { @@ -98,22 +99,11 @@ function renderNotifications( }); } -function renderTooltip(description: string) { - return ( - description !== '' && ( - - - - ) - ); -} +type EmbeddableWithDescription = IEmbeddable & { getDescription: () => string }; -const VISUALIZE_EMBEDDABLE_TYPE = 'visualization'; -type VisualizeEmbeddable = any; - -function getViewDescription(embeddable: IEmbeddable | VisualizeEmbeddable) { - if (embeddable.type === VISUALIZE_EMBEDDABLE_TYPE) { - const description = embeddable.getVisualizationDescription(); +function getViewDescription(embeddable: IEmbeddable | EmbeddableWithDescription) { + if ('getDescription' in embeddable) { + const description = embeddable.getDescription(); if (description) { return description; @@ -126,7 +116,7 @@ function getViewDescription(embeddable: IEmbeddable | VisualizeEmbeddable) { export function PanelHeader({ title, isViewMode, - hidePanelTitles, + hidePanelTitle, getActionContextMenuPanel, closeContextMenu, badges, @@ -134,13 +124,32 @@ export function PanelHeader({ embeddable, headerId, }: PanelHeaderProps) { - const viewDescription = getViewDescription(embeddable); - const showTitle = !isViewMode || (title && !hidePanelTitles) || viewDescription !== ''; - const showPanelBar = badges.length > 0 || showTitle; + const description = getViewDescription(embeddable); + const showTitle = !hidePanelTitle && (!isViewMode || title); + const showPanelBar = + !isViewMode || badges.length > 0 || notifications.length > 0 || showTitle || description; const classes = classNames('embPanel__header', { // eslint-disable-next-line @typescript-eslint/naming-convention 'embPanel__header--floater': !showPanelBar, }); + const placeholderTitle = i18n.translate('embeddableApi.panel.placeholderTitle', { + defaultMessage: '[No Title]', + }); + + const getAriaLabel = () => { + return ( + + {showPanelBar && title + ? i18n.translate('embeddableApi.panel.enhancedDashboardPanelAriaLabel', { + defaultMessage: 'Dashboard panel: {title}', + values: { title: title || placeholderTitle }, + }) + : i18n.translate('embeddableApi.panel.dashboardPanelAriaLabel', { + defaultMessage: 'Dashboard panel', + })} + + ); + }; if (!showPanelBar) { return ( @@ -151,44 +160,41 @@ export function PanelHeader({ closeContextMenu={closeContextMenu} title={title} /> + {getAriaLabel()}
); } + const renderTitle = () => { + const titleComponent = showTitle ? ( + + {title || placeholderTitle} + + ) : undefined; + return description ? ( + + + {titleComponent} + + + ) : ( + {titleComponent} + ); + }; + return (
-

- {showTitle ? ( - - - - - {i18n.translate('embeddableApi.panel.enhancedDashboardPanelAriaLabel', { - defaultMessage: 'Dashboard panel: {title}', - values: { title }, - })} - - - {renderTooltip(viewDescription)} - - ) : ( - - - {i18n.translate('embeddableApi.panel.dashboardPanelAriaLabel', { - defaultMessage: 'Dashboard panel', - })} - - - )} +

+ {getAriaLabel()} + {renderTitle()} {renderBadges(badges, embeddable)}

{renderNotifications(notifications, embeddable)} diff --git a/src/plugins/embeddable/public/lib/panel/panel_header/panel_options_menu.tsx b/src/plugins/embeddable/public/lib/panel/panel_header/panel_options_menu.tsx index b4c349600e8f6..629a5f8c880e8 100644 --- a/src/plugins/embeddable/public/lib/panel/panel_header/panel_options_menu.tsx +++ b/src/plugins/embeddable/public/lib/panel/panel_header/panel_options_menu.tsx @@ -28,14 +28,14 @@ import { } from '@elastic/eui'; export interface PanelOptionsMenuProps { - getActionContextMenuPanel: () => Promise; + getActionContextMenuPanel: () => Promise; isViewMode: boolean; closeContextMenu: boolean; title?: string; } interface State { - actionContextMenuPanel?: EuiContextMenuPanelDescriptor; + actionContextMenuPanel?: EuiContextMenuPanelDescriptor[]; isPopoverOpen: boolean; } @@ -117,7 +117,7 @@ export class PanelOptionsMenu extends React.Component ); diff --git a/src/plugins/embeddable/public/lib/state_transfer/embeddable_state_transfer.test.ts b/src/plugins/embeddable/public/lib/state_transfer/embeddable_state_transfer.test.ts index ef79b18acd4f5..4155cb4d3b60c 100644 --- a/src/plugins/embeddable/public/lib/state_transfer/embeddable_state_transfer.test.ts +++ b/src/plugins/embeddable/public/lib/state_transfer/embeddable_state_transfer.test.ts @@ -85,10 +85,10 @@ describe('embeddable state transfer', () => { it('can send an outgoing embeddable package state', async () => { await stateTransfer.navigateToWithEmbeddablePackage(destinationApp, { - state: { type: 'coolestType', id: '150' }, + state: { type: 'coolestType', input: { savedObjectId: '150' } }, }); expect(application.navigateToApp).toHaveBeenCalledWith('superUltraVisualize', { - state: { type: 'coolestType', id: '150' }, + state: { type: 'coolestType', input: { savedObjectId: '150' } }, }); }); @@ -96,12 +96,16 @@ describe('embeddable state transfer', () => { const historyMock = mockHistoryState({ kibanaIsNowForSports: 'extremeSportsKibana' }); stateTransfer = new EmbeddableStateTransfer(application.navigateToApp, historyMock); await stateTransfer.navigateToWithEmbeddablePackage(destinationApp, { - state: { type: 'coolestType', id: '150' }, + state: { type: 'coolestType', input: { savedObjectId: '150' } }, appendToExistingState: true, }); expect(application.navigateToApp).toHaveBeenCalledWith('superUltraVisualize', { path: undefined, - state: { kibanaIsNowForSports: 'extremeSportsKibana', type: 'coolestType', id: '150' }, + state: { + kibanaIsNowForSports: 'extremeSportsKibana', + type: 'coolestType', + input: { savedObjectId: '150' }, + }, }); }); @@ -120,10 +124,13 @@ describe('embeddable state transfer', () => { }); it('can fetch an incoming embeddable package state', async () => { - const historyMock = mockHistoryState({ type: 'skisEmbeddable', id: '123' }); + const historyMock = mockHistoryState({ + type: 'skisEmbeddable', + input: { savedObjectId: '123' }, + }); stateTransfer = new EmbeddableStateTransfer(application.navigateToApp, historyMock); const fetchedState = stateTransfer.getIncomingEmbeddablePackage(); - expect(fetchedState).toEqual({ type: 'skisEmbeddable', id: '123' }); + expect(fetchedState).toEqual({ type: 'skisEmbeddable', input: { savedObjectId: '123' } }); }); it('returns undefined when embeddable package is not in the right shape', async () => { @@ -136,12 +143,12 @@ describe('embeddable state transfer', () => { it('removes all keys in the keysToRemoveAfterFetch array', async () => { const historyMock = mockHistoryState({ type: 'skisEmbeddable', - id: '123', + input: { savedObjectId: '123' }, test1: 'test1', test2: 'test2', }); stateTransfer = new EmbeddableStateTransfer(application.navigateToApp, historyMock); - stateTransfer.getIncomingEmbeddablePackage({ keysToRemoveAfterFetch: ['type', 'id'] }); + stateTransfer.getIncomingEmbeddablePackage({ keysToRemoveAfterFetch: ['type', 'input'] }); expect(historyMock.replace).toHaveBeenCalledWith( expect.objectContaining({ state: { test1: 'test1', test2: 'test2' } }) ); @@ -150,7 +157,7 @@ describe('embeddable state transfer', () => { it('leaves state as is when no keysToRemove are supplied', async () => { const historyMock = mockHistoryState({ type: 'skisEmbeddable', - id: '123', + input: { savedObjectId: '123' }, test1: 'test1', test2: 'test2', }); @@ -158,7 +165,7 @@ describe('embeddable state transfer', () => { stateTransfer.getIncomingEmbeddablePackage(); expect(historyMock.location.state).toEqual({ type: 'skisEmbeddable', - id: '123', + input: { savedObjectId: '123' }, test1: 'test1', test2: 'test2', }); diff --git a/src/plugins/embeddable/public/lib/state_transfer/types.ts b/src/plugins/embeddable/public/lib/state_transfer/types.ts index 3f3456d914728..d8b4f4801bba3 100644 --- a/src/plugins/embeddable/public/lib/state_transfer/types.ts +++ b/src/plugins/embeddable/public/lib/state_transfer/types.ts @@ -17,17 +17,17 @@ * under the License. */ -import { EmbeddableInput } from '..'; +import { Optional } from '@kbn/utility-types'; +import { EmbeddableInput, SavedObjectEmbeddableInput } from '..'; /** - * Represents a state package that contains the last active app id. + * A state package that contains information an editor will need to create or edit an embeddable then redirect back. * @public */ export interface EmbeddableEditorState { originatingApp: string; - byValueMode?: boolean; - valueInput?: EmbeddableInput; embeddableId?: string; + valueInput?: EmbeddableInput; } export function isEmbeddableEditorState(state: unknown): state is EmbeddableEditorState { @@ -35,32 +35,18 @@ export function isEmbeddableEditorState(state: unknown): state is EmbeddableEdit } /** - * Represents a state package that contains all fields necessary to create an embeddable by reference in a container. + * A state package that contains all fields necessary to create or update an embeddable by reference or by value in a container. * @public */ -export interface EmbeddablePackageByReferenceState { +export interface EmbeddablePackageState { type: string; - id: string; -} - -/** - * Represents a state package that contains all fields necessary to create an embeddable by value in a container. - * @public - */ -export interface EmbeddablePackageByValueState { - type: string; - input: EmbeddableInput; + input: Optional | Optional; embeddableId?: string; } -export type EmbeddablePackageState = - | EmbeddablePackageByReferenceState - | EmbeddablePackageByValueState; - export function isEmbeddablePackageState(state: unknown): state is EmbeddablePackageState { return ( - (ensureFieldOfTypeExists('type', state, 'string') && - ensureFieldOfTypeExists('id', state, 'string')) || + ensureFieldOfTypeExists('type', state, 'string') && ensureFieldOfTypeExists('input', state, 'object') ); } diff --git a/src/plugins/embeddable/public/mocks.tsx b/src/plugins/embeddable/public/mocks.tsx index 26c10121adb3d..62063cb480338 100644 --- a/src/plugins/embeddable/public/mocks.tsx +++ b/src/plugins/embeddable/public/mocks.tsx @@ -39,6 +39,7 @@ import { dataPluginMock } from '../../data/public/mocks'; import { inspectorPluginMock } from '../../inspector/public/mocks'; import { uiActionsPluginMock } from '../../ui_actions/public/mocks'; +export { mockAttributeService } from './lib/attribute_service/attribute_service.mock'; export type Setup = jest.Mocked; export type Start = jest.Mocked; @@ -125,6 +126,7 @@ const createStartContract = (): Start => { EmbeddablePanel: jest.fn(), getEmbeddablePanel: jest.fn(), getStateTransfer: jest.fn(() => createEmbeddableStateTransferMock() as EmbeddableStateTransfer), + getAttributeService: jest.fn(), }; return startContract; }; diff --git a/src/plugins/embeddable/public/plugin.tsx b/src/plugins/embeddable/public/plugin.tsx index 00eb923c26662..aa4d66c43c9db 100644 --- a/src/plugins/embeddable/public/plugin.tsx +++ b/src/plugins/embeddable/public/plugin.tsx @@ -20,7 +20,7 @@ import React from 'react'; import { Subscription } from 'rxjs'; import { identity } from 'lodash'; import { DataPublicPluginSetup, DataPublicPluginStart } from '../../data/public'; -import { getSavedObjectFinder } from '../../saved_objects/public'; +import { getSavedObjectFinder, showSaveModal } from '../../saved_objects/public'; import { UiActionsSetup, UiActionsStart } from '../../ui_actions/public'; import { Start as InspectorStart } from '../../inspector/public'; import { @@ -47,6 +47,7 @@ import { defaultEmbeddableFactoryProvider, IEmbeddable, EmbeddablePanel, + SavedObjectEmbeddableInput, } from './lib'; import { EmbeddableFactoryDefinition } from './lib/embeddables/embeddable_factory_definition'; import { EmbeddableStateTransfer } from './lib/state_transfer'; @@ -56,6 +57,8 @@ import { telemetryBaseEmbeddableInput, } from '../common/lib/migrate_base_input'; import { PersistableState, SerializableState } from '../../kibana_utils/common'; +import { ATTRIBUTE_SERVICE_KEY, AttributeService } from './lib/attribute_service'; +import { AttributeServiceOptions } from './lib/attribute_service/attribute_service'; export interface EmbeddableSetupDependencies { data: DataPublicPluginSetup; @@ -93,6 +96,16 @@ export interface EmbeddableStart extends PersistableState { EmbeddablePanel: EmbeddablePanelHOC; getEmbeddablePanel: (stateTransfer?: EmbeddableStateTransfer) => EmbeddablePanelHOC; getStateTransfer: (history?: ScopedHistory) => EmbeddableStateTransfer; + getAttributeService: < + A extends { title: string }, + V extends EmbeddableInput & { [ATTRIBUTE_SERVICE_KEY]: A } = EmbeddableInput & { + [ATTRIBUTE_SERVICE_KEY]: A; + }, + R extends SavedObjectEmbeddableInput = SavedObjectEmbeddableInput + >( + type: string, + options: AttributeServiceOptions + ) => AttributeService; } export type EmbeddablePanelHOC = React.FC<{ embeddable: IEmbeddable; hideHeader?: boolean }>; @@ -178,6 +191,15 @@ export class EmbeddablePublicPlugin implements Plugin + new AttributeService( + type, + showSaveModal, + core.i18n.Context, + core.notifications.toasts, + options, + this.getEmbeddableFactory + ), getStateTransfer: (history?: ScopedHistory) => { return history ? new EmbeddableStateTransfer(core.application.navigateToApp, history, this.appList) diff --git a/src/plugins/embeddable/public/public.api.md b/src/plugins/embeddable/public/public.api.md new file mode 100644 index 0000000000000..6280d3a2e4a50 --- /dev/null +++ b/src/plugins/embeddable/public/public.api.md @@ -0,0 +1,888 @@ +## API Report File for "kibana" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts + +import { Action } from 'history'; +import { Action as Action_3 } from 'src/plugins/ui_actions/public'; +import { ActionExecutionContext as ActionExecutionContext_2 } from 'src/plugins/ui_actions/public'; +import { ApiResponse } from '@elastic/elasticsearch/lib/Transport'; +import { ApiResponse as ApiResponse_2 } from '@elastic/elasticsearch'; +import { ApplicationStart as ApplicationStart_2 } from 'kibana/public'; +import { Assign } from '@kbn/utility-types'; +import { BehaviorSubject } from 'rxjs'; +import Boom from 'boom'; +import { CoreSetup as CoreSetup_2 } from 'src/core/public'; +import { CoreSetup as CoreSetup_3 } from 'kibana/public'; +import { CoreStart as CoreStart_2 } from 'kibana/public'; +import * as CSS from 'csstype'; +import { EmbeddableStart as EmbeddableStart_2 } from 'src/plugins/embeddable/public/plugin'; +import { Ensure } from '@kbn/utility-types'; +import { EnvironmentMode } from '@kbn/config'; +import { ErrorToastOptions as ErrorToastOptions_2 } from 'src/core/public/notifications'; +import { EuiBreadcrumb } from '@elastic/eui'; +import { EuiButtonEmptyProps } from '@elastic/eui'; +import { EuiComboBoxProps } from '@elastic/eui'; +import { EuiConfirmModalProps } from '@elastic/eui'; +import { EuiContextMenuPanelDescriptor } from '@elastic/eui'; +import { EuiGlobalToastListToast } from '@elastic/eui'; +import { ExclusiveUnion } from '@elastic/eui'; +import { ExpressionAstFunction } from 'src/plugins/expressions/common'; +import { History } from 'history'; +import { Href } from 'history'; +import { I18nStart as I18nStart_2 } from 'src/core/public'; +import { IconType } from '@elastic/eui'; +import { ISearchOptions } from 'src/plugins/data/public'; +import { ISearchSource } from 'src/plugins/data/public'; +import { IStorageWrapper } from 'src/plugins/kibana_utils/public'; +import { IUiSettingsClient as IUiSettingsClient_2 } from 'src/core/public'; +import { KibanaClient } from '@elastic/elasticsearch/api/kibana'; +import { KibanaConfigType } from 'src/core/server/kibana_config'; +import { Location } from 'history'; +import { LocationDescriptorObject } from 'history'; +import { Logger } from '@kbn/logging'; +import { LogMeta } from '@kbn/logging'; +import { MaybePromise } from '@kbn/utility-types'; +import { Moment } from 'moment'; +import { NameList } from 'elasticsearch'; +import { NotificationsStart as NotificationsStart_2 } from 'src/core/public'; +import { Observable } from 'rxjs'; +import { Optional } from '@kbn/utility-types'; +import { OverlayStart as OverlayStart_2 } from 'src/core/public'; +import { PackageInfo } from '@kbn/config'; +import { Path } from 'history'; +import { PluginInitializerContext } from 'src/core/public'; +import * as PropTypes from 'prop-types'; +import { PublicMethodsOf } from '@kbn/utility-types'; +import { PublicUiSettingsParams } from 'src/core/server/types'; +import React from 'react'; +import { RecursiveReadonly } from '@kbn/utility-types'; +import { RequestAdapter } from 'src/plugins/inspector/common'; +import { Required } from '@kbn/utility-types'; +import * as Rx from 'rxjs'; +import { SavedObject as SavedObject_2 } from 'src/core/server'; +import { SavedObjectAttributes } from 'kibana/server'; +import { SavedObjectAttributes as SavedObjectAttributes_2 } from 'src/core/public'; +import { SavedObjectAttributes as SavedObjectAttributes_3 } from 'kibana/public'; +import { SavedObjectsClientContract as SavedObjectsClientContract_3 } from 'src/core/public'; +import { Search } from '@elastic/elasticsearch/api/requestParams'; +import { SearchResponse } from 'elasticsearch'; +import { SerializedFieldFormat as SerializedFieldFormat_2 } from 'src/plugins/expressions/common'; +import { ShallowPromise } from '@kbn/utility-types'; +import { SimpleSavedObject as SimpleSavedObject_2 } from 'src/core/public'; +import { ToastInputFields as ToastInputFields_2 } from 'src/core/public/notifications'; +import { ToastsSetup as ToastsSetup_2 } from 'kibana/public'; +import { TransportRequestOptions } from '@elastic/elasticsearch/lib/Transport'; +import { TransportRequestParams } from '@elastic/elasticsearch/lib/Transport'; +import { TransportRequestPromise } from '@elastic/elasticsearch/lib/Transport'; +import { TypeOf } from '@kbn/config-schema'; +import { UiComponent } from 'src/plugins/kibana_utils/public'; +import { UnregisterCallback } from 'history'; +import { UserProvidedValues } from 'src/core/server/types'; + +// Warning: (ae-missing-release-tag) "ACTION_ADD_PANEL" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export const ACTION_ADD_PANEL = "ACTION_ADD_PANEL"; + +// Warning: (ae-missing-release-tag) "ACTION_EDIT_PANEL" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export const ACTION_EDIT_PANEL = "editPanel"; + +// Warning: (ae-missing-release-tag) "Adapters" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export interface Adapters { + // (undocumented) + [key: string]: any; +} + +// Warning: (ae-forgotten-export) The symbol "ActionContext" needs to be exported by the entry point index.d.ts +// Warning: (ae-missing-release-tag) "AddPanelAction" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export class AddPanelAction implements Action_3 { + // Warning: (ae-forgotten-export) The symbol "React" needs to be exported by the entry point index.d.ts + constructor(getFactory: EmbeddableStart_2['getEmbeddableFactory'], getAllFactories: EmbeddableStart_2['getEmbeddableFactories'], overlays: OverlayStart_2, notifications: NotificationsStart_2, SavedObjectFinder: React_2.ComponentType); + // (undocumented) + execute(context: ActionExecutionContext_2): Promise; + // (undocumented) + getDisplayName(): string; + // (undocumented) + getIconType(): string; + // (undocumented) + readonly id = "ACTION_ADD_PANEL"; + // (undocumented) + isCompatible(context: ActionExecutionContext_2): Promise; + // (undocumented) + readonly type = "ACTION_ADD_PANEL"; +} + +// Warning: (ae-missing-release-tag) "ATTRIBUTE_SERVICE_KEY" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export const ATTRIBUTE_SERVICE_KEY = "attributes"; + +// Warning: (ae-missing-release-tag) "AttributeService" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export class AttributeService { + // Warning: (ae-forgotten-export) The symbol "AttributeServiceOptions" needs to be exported by the entry point index.d.ts + constructor(type: string, showSaveModal: (saveModal: React.ReactElement, I18nContext: I18nStart_2['Context']) => void, i18nContext: I18nStart_2['Context'], toasts: NotificationsStart_2['toasts'], options: AttributeServiceOptions, getEmbeddableFactory?: (embeddableFactoryId: string) => EmbeddableFactory); + // (undocumented) + getExplicitInputFromEmbeddable(embeddable: IEmbeddable): ValType | RefType; + // (undocumented) + getInputAsRefType: (input: ValType | RefType, saveOptions?: { + showSaveModal: boolean; + saveModalTitle?: string | undefined; + } | { + title: string; + } | undefined) => Promise; + // (undocumented) + getInputAsValueType: (input: ValType | RefType) => Promise; + // (undocumented) + inputIsRefType: (input: ValType | RefType) => input is RefType; + // (undocumented) + unwrapAttributes(input: RefType | ValType): Promise; + // (undocumented) + wrapAttributes(newAttributes: SavedObjectAttributes, useRefType: boolean, input?: ValType | RefType): Promise>; +} + +// Warning: (ae-missing-release-tag) "ChartActionContext" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type ChartActionContext = ValueClickContext | RangeSelectContext; + +// Warning: (ae-missing-release-tag) "Container" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export abstract class Container = {}, TContainerInput extends ContainerInput = ContainerInput, TContainerOutput extends ContainerOutput = ContainerOutput> extends Embeddable implements IContainer { + constructor(input: TContainerInput, output: TContainerOutput, getFactory: EmbeddableStart['getEmbeddableFactory'], parent?: Container); + // (undocumented) + addNewEmbeddable = IEmbeddable>(type: string, explicitInput: Partial): Promise; + // (undocumented) + protected readonly children: { + [key: string]: IEmbeddable | ErrorEmbeddable; + }; + // (undocumented) + protected createNewPanelState>(factory: EmbeddableFactory, partial?: Partial): PanelState; + // (undocumented) + destroy(): void; + // (undocumented) + getChild(id: string): E; + // (undocumented) + getChildIds(): string[]; + // (undocumented) + protected readonly getFactory: EmbeddableStart['getEmbeddableFactory']; + protected abstract getInheritedInput(id: string): TChildInput; + // (undocumented) + getInputForChild(embeddableId: string): TEmbeddableInput; + // (undocumented) + protected getPanelState(embeddableId: string): PanelState; + // (undocumented) + readonly isContainer: boolean; + // (undocumented) + reload(): void; + // (undocumented) + removeEmbeddable(embeddableId: string): void; + // (undocumented) + untilEmbeddableLoaded(id: string): Promise; + // (undocumented) + updateInputForChild(id: string, changes: Partial): void; +} + +// Warning: (ae-missing-release-tag) "ContainerInput" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export interface ContainerInput extends EmbeddableInput { + // (undocumented) + hidePanelTitles?: boolean; + // (undocumented) + panels: { + [key: string]: PanelState; + }; +} + +// Warning: (ae-missing-release-tag) "ContainerOutput" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export interface ContainerOutput extends EmbeddableOutput { + // (undocumented) + embeddableLoaded: { + [key: string]: boolean; + }; +} + +// Warning: (ae-missing-release-tag) "CONTEXT_MENU_TRIGGER" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export const CONTEXT_MENU_TRIGGER = "CONTEXT_MENU_TRIGGER"; + +// Warning: (ae-forgotten-export) The symbol "Trigger" needs to be exported by the entry point index.d.ts +// Warning: (ae-missing-release-tag) "contextMenuTrigger" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export const contextMenuTrigger: Trigger<'CONTEXT_MENU_TRIGGER'>; + +// Warning: (ae-missing-release-tag) "defaultEmbeddableFactoryProvider" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export const defaultEmbeddableFactoryProvider: = IEmbeddable, T extends SavedObjectAttributes_3 = SavedObjectAttributes_3>(def: EmbeddableFactoryDefinition) => EmbeddableFactory; + +// Warning: (ae-forgotten-export) The symbol "ActionContext" needs to be exported by the entry point index.d.ts +// Warning: (ae-missing-release-tag) "EditPanelAction" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export class EditPanelAction implements Action_3 { + constructor(getEmbeddableFactory: EmbeddableStart['getEmbeddableFactory'], application: ApplicationStart_2, stateTransfer?: EmbeddableStateTransfer | undefined); + // (undocumented) + currentAppId: string | undefined; + // (undocumented) + execute(context: ActionContext_3): Promise; + // Warning: (ae-forgotten-export) The symbol "NavigationContext" needs to be exported by the entry point index.d.ts + // + // (undocumented) + getAppTarget({ embeddable }: ActionContext_3): NavigationContext | undefined; + // (undocumented) + getDisplayName({ embeddable }: ActionContext_3): string; + // (undocumented) + getHref({ embeddable }: ActionContext_3): Promise; + // (undocumented) + getIconType(): string; + // (undocumented) + readonly id = "editPanel"; + // (undocumented) + isCompatible({ embeddable }: ActionContext_3): Promise; + // (undocumented) + order: number; + // (undocumented) + readonly type = "editPanel"; +} + +// Warning: (ae-missing-release-tag) "Embeddable" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export abstract class Embeddable implements IEmbeddable { + constructor(input: TEmbeddableInput, output: TEmbeddableOutput, parent?: IContainer); + destroy(): void; + // (undocumented) + getInput$(): Readonly>; + // (undocumented) + getInput(): Readonly; + getInspectorAdapters(): Adapters | undefined; + // (undocumented) + getIsContainer(): this is IContainer; + // (undocumented) + getOutput$(): Readonly>; + // (undocumented) + getOutput(): Readonly; + getRoot(): IEmbeddable | IContainer; + // (undocumented) + getTitle(): string; + // (undocumented) + readonly id: string; + // (undocumented) + protected input: TEmbeddableInput; + // (undocumented) + readonly isContainer: boolean; + // (undocumented) + protected output: TEmbeddableOutput; + // (undocumented) + readonly parent?: IContainer; + abstract reload(): void; + // (undocumented) + render(el: HTMLElement): void; + // Warning: (ae-forgotten-export) The symbol "RenderCompleteDispatcher" needs to be exported by the entry point index.d.ts + // + // (undocumented) + protected renderComplete: RenderCompleteDispatcher; + // (undocumented) + static runtimeId: number; + // (undocumented) + readonly runtimeId: number; + // Warning: (ae-forgotten-export) The symbol "TriggerContextMapping" needs to be exported by the entry point index.d.ts + // + // (undocumented) + supportedTriggers(): Array; + // (undocumented) + abstract readonly type: string; + // (undocumented) + updateInput(changes: Partial): void; + // (undocumented) + protected updateOutput(outputChanges: Partial): void; +} + +// Warning: (ae-forgotten-export) The symbol "State" needs to be exported by the entry point index.d.ts +// Warning: (ae-missing-release-tag) "EmbeddableChildPanel" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export class EmbeddableChildPanel extends React.Component { + constructor(props: EmbeddableChildPanelProps); + // (undocumented) + [panel: string]: any; + // (undocumented) + componentDidMount(): Promise; + // (undocumented) + componentWillUnmount(): void; + // (undocumented) + embeddable: IEmbeddable | ErrorEmbeddable; + // (undocumented) + mounted: boolean; + // (undocumented) + render(): JSX.Element; + } + +// Warning: (ae-missing-release-tag) "EmbeddableChildPanelProps" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export interface EmbeddableChildPanelProps { + // (undocumented) + className?: string; + // (undocumented) + container: IContainer; + // (undocumented) + embeddableId: string; + // (undocumented) + PanelComponent: EmbeddableStart['EmbeddablePanel']; +} + +// Warning: (ae-missing-release-tag) "EmbeddableContext" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export interface EmbeddableContext { + // (undocumented) + embeddable: IEmbeddable; +} + +// @public +export interface EmbeddableEditorState { + // (undocumented) + embeddableId?: string; + // (undocumented) + originatingApp: string; + // (undocumented) + valueInput?: EmbeddableInput; +} + +// Warning: (ae-forgotten-export) The symbol "PersistableState" needs to be exported by the entry point index.d.ts +// Warning: (ae-missing-release-tag) "EmbeddableFactory" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export interface EmbeddableFactory = IEmbeddable, TSavedObjectAttributes extends SavedObjectAttributes_2 = SavedObjectAttributes_2> extends PersistableState { + canCreateNew(): boolean; + create(initialInput: TEmbeddableInput, parent?: IContainer): Promise; + createFromSavedObject(savedObjectId: string, input: Partial, parent?: IContainer): Promise; + getDefaultInput(partial: Partial): Partial; + getDisplayName(): string; + getExplicitInput(): Promise>; + readonly isContainerType: boolean; + readonly isEditable: () => Promise; + // Warning: (ae-forgotten-export) The symbol "SavedObjectMetaData" needs to be exported by the entry point index.d.ts + // + // (undocumented) + readonly savedObjectMetaData?: SavedObjectMetaData; + // (undocumented) + readonly type: string; +} + +// Warning: (ae-missing-release-tag) "EmbeddableFactoryDefinition" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type EmbeddableFactoryDefinition = IEmbeddable, T extends SavedObjectAttributes = SavedObjectAttributes> = Pick, 'create' | 'type' | 'isEditable' | 'getDisplayName'> & Partial, 'createFromSavedObject' | 'isContainerType' | 'getExplicitInput' | 'savedObjectMetaData' | 'canCreateNew' | 'getDefaultInput' | 'telemetry' | 'extract' | 'inject'>>; + +// Warning: (ae-missing-release-tag) "EmbeddableFactoryNotFoundError" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export class EmbeddableFactoryNotFoundError extends Error { + constructor(type: string); + // (undocumented) + code: string; +} + +// Warning: (ae-missing-release-tag) "EmbeddableInput" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type EmbeddableInput = { + viewMode?: ViewMode; + title?: string; + id: string; + lastReloadRequestTime?: number; + hidePanelTitles?: boolean; + enhancements?: SerializableState; + disabledActions?: string[]; + disableTriggers?: boolean; + timeRange?: TimeRange; + query?: Query; + filters?: Filter[]; +}; + +// Warning: (ae-missing-release-tag) "EmbeddableInstanceConfiguration" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export interface EmbeddableInstanceConfiguration { + // (undocumented) + id: string; + // (undocumented) + savedObjectId?: string; +} + +// Warning: (ae-missing-release-tag) "EmbeddableOutput" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export interface EmbeddableOutput { + // (undocumented) + defaultTitle?: string; + // (undocumented) + editable?: boolean; + // (undocumented) + editApp?: string; + // (undocumented) + editPath?: string; + // (undocumented) + editUrl?: string; + // Warning: (ae-forgotten-export) The symbol "EmbeddableError" needs to be exported by the entry point index.d.ts + // + // (undocumented) + error?: EmbeddableError; + // (undocumented) + loading?: boolean; + // (undocumented) + savedObjectId?: string; + // (undocumented) + title?: string; +} + +// @public +export interface EmbeddablePackageState { + // (undocumented) + embeddableId?: string; + // (undocumented) + input: Optional | Optional; + // (undocumented) + type: string; +} + +// Warning: (ae-forgotten-export) The symbol "Props" needs to be exported by the entry point index.d.ts +// Warning: (ae-forgotten-export) The symbol "State" needs to be exported by the entry point index.d.ts +// Warning: (ae-missing-release-tag) "EmbeddablePanel" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export class EmbeddablePanel extends React.Component { + constructor(props: Props); + // (undocumented) + closeMyContextMenuPanel: () => void; + // (undocumented) + componentDidMount(): void; + // (undocumented) + componentWillUnmount(): void; + // (undocumented) + onBlur: (blurredPanelIndex: string) => void; + // (undocumented) + onFocus: (focusedPanelIndex: string) => void; + // (undocumented) + render(): JSX.Element; + // (undocumented) + UNSAFE_componentWillMount(): void; +} + +// Warning: (ae-missing-release-tag) "EmbeddablePanelHOC" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type EmbeddablePanelHOC = React.FC<{ + embeddable: IEmbeddable; + hideHeader?: boolean; +}>; + +// @public +export const EmbeddableRenderer: (props: EmbeddableRendererProps) => JSX.Element; + +// Warning: (ae-forgotten-export) The symbol "EmbeddableRendererPropsWithEmbeddable" needs to be exported by the entry point index.d.ts +// Warning: (ae-forgotten-export) The symbol "EmbeddableRendererWithFactory" needs to be exported by the entry point index.d.ts +// Warning: (ae-missing-release-tag) "EmbeddableRendererProps" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export type EmbeddableRendererProps = EmbeddableRendererPropsWithEmbeddable | EmbeddableRendererWithFactory; + +// Warning: (ae-forgotten-export) The symbol "Props" needs to be exported by the entry point index.d.ts +// Warning: (ae-missing-release-tag) "EmbeddableRoot" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export class EmbeddableRoot extends React.Component { + constructor(props: Props_2); + // (undocumented) + componentDidMount(): void; + // (undocumented) + componentDidUpdate(prevProps?: Props_2): void; + // (undocumented) + render(): JSX.Element; + // (undocumented) + shouldComponentUpdate(newProps: Props_2): boolean; +} + +// Warning: (ae-missing-release-tag) "EmbeddableSetup" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export interface EmbeddableSetup { + // (undocumented) + registerEmbeddableFactory: = IEmbeddable>(id: string, factory: EmbeddableFactoryDefinition) => () => EmbeddableFactory; + // (undocumented) + registerEnhancement: (enhancement: EnhancementRegistryDefinition) => void; + // Warning: (ae-forgotten-export) The symbol "EmbeddableFactoryProvider" needs to be exported by the entry point index.d.ts + // + // (undocumented) + setCustomEmbeddableFactoryProvider: (customProvider: EmbeddableFactoryProvider) => void; +} + +// Warning: (ae-missing-release-tag) "EmbeddableSetupDependencies" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export interface EmbeddableSetupDependencies { + // Warning: (ae-forgotten-export) The symbol "DataPublicPluginSetup" needs to be exported by the entry point index.d.ts + // + // (undocumented) + data: DataPublicPluginSetup; + // Warning: (ae-forgotten-export) The symbol "UiActionsSetup" needs to be exported by the entry point index.d.ts + // + // (undocumented) + uiActions: UiActionsSetup; +} + +// Warning: (ae-missing-release-tag) "EmbeddableStart" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export interface EmbeddableStart extends PersistableState { + // (undocumented) + EmbeddablePanel: EmbeddablePanelHOC; + // (undocumented) + getAttributeService: (type: string, options: AttributeServiceOptions) => AttributeService; + // (undocumented) + getEmbeddableFactories: () => IterableIterator; + // (undocumented) + getEmbeddableFactory: = IEmbeddable>(embeddableFactoryId: string) => EmbeddableFactory | undefined; + // (undocumented) + getEmbeddablePanel: (stateTransfer?: EmbeddableStateTransfer) => EmbeddablePanelHOC; + // Warning: (ae-forgotten-export) The symbol "ScopedHistory" needs to be exported by the entry point index.d.ts + // + // (undocumented) + getStateTransfer: (history?: ScopedHistory) => EmbeddableStateTransfer; +} + +// Warning: (ae-missing-release-tag) "EmbeddableStartDependencies" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export interface EmbeddableStartDependencies { + // Warning: (ae-forgotten-export) The symbol "DataPublicPluginStart" needs to be exported by the entry point index.d.ts + // + // (undocumented) + data: DataPublicPluginStart; + // Warning: (ae-forgotten-export) The symbol "Start" needs to be exported by the entry point index.d.ts + // + // (undocumented) + inspector: Start; + // Warning: (ae-forgotten-export) The symbol "UiActionsStart" needs to be exported by the entry point index.d.ts + // + // (undocumented) + uiActions: UiActionsStart; +} + +// Warning: (ae-unresolved-link) The @link reference could not be resolved: The package "kibana" does not have an export "ScopedHistory" +// +// @public +export class EmbeddableStateTransfer { + // Warning: (ae-forgotten-export) The symbol "ApplicationStart" needs to be exported by the entry point index.d.ts + // Warning: (ae-forgotten-export) The symbol "PublicAppInfo" needs to be exported by the entry point index.d.ts + constructor(navigateToApp: ApplicationStart['navigateToApp'], scopedHistory?: ScopedHistory | undefined, appList?: ReadonlyMap | undefined); + getAppNameFromId: (appId: string) => string | undefined; + getIncomingEditorState(options?: { + keysToRemoveAfterFetch?: string[]; + }): EmbeddableEditorState | undefined; + getIncomingEmbeddablePackage(options?: { + keysToRemoveAfterFetch?: string[]; + }): EmbeddablePackageState | undefined; + // Warning: (ae-unresolved-link) The @link reference could not be resolved: The package "kibana" does not have an export "ApplicationStart" + navigateToEditor(appId: string, options?: { + path?: string; + state: EmbeddableEditorState; + appendToExistingState?: boolean; + }): Promise; + // Warning: (ae-unresolved-link) The @link reference could not be resolved: The package "kibana" does not have an export "ApplicationStart" + navigateToWithEmbeddablePackage(appId: string, options?: { + path?: string; + state: EmbeddablePackageState; + appendToExistingState?: boolean; + }): Promise; + } + +// Warning: (ae-forgotten-export) The symbol "PersistableStateDefinition" needs to be exported by the entry point index.d.ts +// Warning: (ae-missing-release-tag) "EnhancementRegistryDefinition" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export interface EnhancementRegistryDefinition

extends PersistableStateDefinition

{ + // (undocumented) + id: string; +} + +// Warning: (ae-missing-release-tag) "ErrorEmbeddable" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export class ErrorEmbeddable extends Embeddable { + constructor(error: Error | string, input: EmbeddableInput, parent?: IContainer); + // (undocumented) + destroy(): void; + // (undocumented) + error: Error | string; + // (undocumented) + reload(): void; + // (undocumented) + render(dom: HTMLElement): void; + // (undocumented) + readonly type = "error"; +} + +// Warning: (ae-missing-release-tag) "IContainer" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export interface IContainer = ContainerInput, O extends ContainerOutput = ContainerOutput> extends IEmbeddable { + addNewEmbeddable = Embeddable>(type: string, explicitInput: Partial): Promise; + getChild = Embeddable>(id: string): E; + getInputForChild(id: string): EEI; + removeEmbeddable(embeddableId: string): void; + untilEmbeddableLoaded(id: string): Promise; + updateInputForChild(id: string, changes: Partial): void; +} + +// Warning: (ae-missing-release-tag) "IEmbeddable" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export interface IEmbeddable { + destroy(): void; + enhancements?: object; + getInput$(): Readonly>; + getInput(): Readonly; + getInspectorAdapters(): Adapters | undefined; + getIsContainer(): this is IContainer; + getOutput$(): Readonly>; + getOutput(): Readonly; + getRoot(): IEmbeddable | IContainer; + getTitle(): string | undefined; + readonly id: string; + readonly isContainer: boolean; + readonly parent?: IContainer; + reload(): void; + render(domNode: HTMLElement | Element): void; + readonly runtimeId?: number; + supportedTriggers(): Array; + readonly type: string; + updateInput(changes: Partial): void; +} + +// Warning: (ae-missing-release-tag) "isErrorEmbeddable" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export function isErrorEmbeddable(embeddable: TEmbeddable | ErrorEmbeddable): embeddable is ErrorEmbeddable; + +// Warning: (ae-missing-release-tag) "isRangeSelectTriggerContext" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export const isRangeSelectTriggerContext: (context: ChartActionContext) => context is RangeSelectContext>; + +// Warning: (ae-missing-release-tag) "isReferenceOrValueEmbeddable" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export function isReferenceOrValueEmbeddable(incoming: unknown): incoming is ReferenceOrValueEmbeddable; + +// Warning: (ae-missing-release-tag) "isSavedObjectEmbeddableInput" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export function isSavedObjectEmbeddableInput(input: EmbeddableInput | SavedObjectEmbeddableInput): input is SavedObjectEmbeddableInput; + +// Warning: (ae-missing-release-tag) "isValueClickTriggerContext" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export const isValueClickTriggerContext: (context: ChartActionContext) => context is ValueClickContext>; + +// Warning: (ae-missing-release-tag) "openAddPanelFlyout" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export function openAddPanelFlyout(options: { + embeddable: IContainer; + getFactory: EmbeddableStart['getEmbeddableFactory']; + getAllFactories: EmbeddableStart['getEmbeddableFactories']; + overlays: OverlayStart_2; + notifications: NotificationsStart_2; + SavedObjectFinder: React.ComponentType; +}): Promise; + +// Warning: (ae-missing-release-tag) "OutputSpec" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export interface OutputSpec { + // (undocumented) + [key: string]: PropertySpec; +} + +// Warning: (ae-missing-release-tag) "PANEL_BADGE_TRIGGER" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export const PANEL_BADGE_TRIGGER = "PANEL_BADGE_TRIGGER"; + +// Warning: (ae-missing-release-tag) "PANEL_NOTIFICATION_TRIGGER" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export const PANEL_NOTIFICATION_TRIGGER = "PANEL_NOTIFICATION_TRIGGER"; + +// Warning: (ae-missing-release-tag) "panelBadgeTrigger" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export const panelBadgeTrigger: Trigger<'PANEL_BADGE_TRIGGER'>; + +// Warning: (ae-missing-release-tag) "PanelNotFoundError" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export class PanelNotFoundError extends Error { + constructor(); + // (undocumented) + code: string; +} + +// Warning: (ae-missing-release-tag) "panelNotificationTrigger" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export const panelNotificationTrigger: Trigger<'PANEL_NOTIFICATION_TRIGGER'>; + +// Warning: (ae-missing-release-tag) "PanelState" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export interface PanelState { + // (undocumented) + explicitInput: Partial & { + id: string; + }; + // (undocumented) + type: string; +} + +// Warning: (ae-forgotten-export) The symbol "EmbeddablePublicPlugin" needs to be exported by the entry point index.d.ts +// Warning: (ae-missing-release-tag) "plugin" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export function plugin(initializerContext: PluginInitializerContext): EmbeddablePublicPlugin; + +// Warning: (ae-missing-release-tag) "PropertySpec" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export interface PropertySpec { + // (undocumented) + accessPath: string; + // (undocumented) + description: string; + // (undocumented) + displayName: string; + // (undocumented) + id: string; + // (undocumented) + value?: string; +} + +// Warning: (ae-missing-release-tag) "RangeSelectContext" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export interface RangeSelectContext { + // (undocumented) + data: { + table: KibanaDatatable; + column: number; + range: number[]; + timeFieldName?: string; + }; + // (undocumented) + embeddable?: T; +} + +// @public +export interface ReferenceOrValueEmbeddable { + getInputAsRefType: () => Promise; + getInputAsValueType: () => Promise; + inputIsRefType: (input: ValTypeInput | RefTypeInput) => input is RefTypeInput; +} + +// Warning: (ae-missing-release-tag) "SavedObjectEmbeddableInput" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export interface SavedObjectEmbeddableInput extends EmbeddableInput { + // (undocumented) + savedObjectId: string; +} + +// Warning: (ae-missing-release-tag) "ValueClickContext" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export interface ValueClickContext { + // (undocumented) + data: { + data: Array<{ + table: Pick; + column: number; + row: number; + value: any; + }>; + timeFieldName?: string; + negate?: boolean; + }; + // (undocumented) + embeddable?: T; +} + +// Warning: (ae-missing-release-tag) "ViewMode" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export enum ViewMode { + // (undocumented) + EDIT = "edit", + // (undocumented) + VIEW = "view" +} + +// Warning: (ae-missing-release-tag) "withEmbeddableSubscription" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export const withEmbeddableSubscription: = IEmbeddable, ExtraProps = {}>(WrappedComponent: React.ComponentType<{ + input: I; + output: O; + embeddable: E; +} & ExtraProps>) => React.ComponentType<{ + embeddable: E; +} & ExtraProps>; + + +// Warnings were encountered during analysis: +// +// src/plugins/embeddable/common/types.ts:44:3 - (ae-forgotten-export) The symbol "SerializableState" needs to be exported by the entry point index.d.ts +// src/plugins/embeddable/common/types.ts:59:3 - (ae-forgotten-export) The symbol "TimeRange" needs to be exported by the entry point index.d.ts +// src/plugins/embeddable/common/types.ts:64:3 - (ae-forgotten-export) The symbol "Query" needs to be exported by the entry point index.d.ts +// src/plugins/embeddable/common/types.ts:69:3 - (ae-forgotten-export) The symbol "Filter" needs to be exported by the entry point index.d.ts +// src/plugins/embeddable/public/lib/triggers/triggers.ts:45:5 - (ae-forgotten-export) The symbol "KibanaDatatable" needs to be exported by the entry point index.d.ts + +// (No @packageDocumentation comment for this package) + +``` diff --git a/src/plugins/embeddable/public/tests/apply_filter_action.test.ts b/src/plugins/embeddable/public/tests/apply_filter_action.test.ts deleted file mode 100644 index f8c4a4a7e4b72..0000000000000 --- a/src/plugins/embeddable/public/tests/apply_filter_action.test.ts +++ /dev/null @@ -1,153 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { testPlugin } from './test_plugin'; -import { EmbeddableOutput, isErrorEmbeddable, createFilterAction } from '../lib'; -import { - FilterableContainer, - FilterableContainerInput, - FILTERABLE_CONTAINER, - FilterableEmbeddableFactory, - HelloWorldContainer, - FILTERABLE_EMBEDDABLE, - FilterableEmbeddable, - FilterableContainerFactory, - FilterableEmbeddableInput, -} from '../lib/test_samples'; -import { esFilters } from '../../../data/public'; -import { applyFilterTrigger } from '../../../ui_actions/public'; - -test('ApplyFilterAction applies the filter to the root of the container tree', async () => { - const { doStart, setup } = testPlugin(); - - const factory2 = new FilterableEmbeddableFactory(); - const factory1 = new FilterableContainerFactory(async () => await api.getEmbeddableFactory); - setup.registerEmbeddableFactory(factory2.type, factory2); - setup.registerEmbeddableFactory(factory1.type, factory1); - - const api = doStart(); - - const applyFilterAction = createFilterAction(); - - const root = new FilterableContainer( - { id: 'root', panels: {}, filters: [] }, - api.getEmbeddableFactory - ); - - const node1 = await root.addNewEmbeddable< - FilterableContainerInput, - EmbeddableOutput, - FilterableContainer - >(FILTERABLE_CONTAINER, { panels: {}, id: 'node1' }); - - const node2 = await root.addNewEmbeddable< - FilterableContainerInput, - EmbeddableOutput, - FilterableContainer - >(FILTERABLE_CONTAINER, { panels: {}, id: 'Node2' }); - - if (isErrorEmbeddable(node1) || isErrorEmbeddable(node2)) { - throw new Error(); - } - - const embeddable = await node2.addNewEmbeddable< - FilterableEmbeddableInput, - EmbeddableOutput, - FilterableEmbeddable - >(FILTERABLE_EMBEDDABLE, { id: 'leaf' }); - - if (isErrorEmbeddable(embeddable)) { - throw new Error(); - } - - const filter: any = { - $state: { store: esFilters.FilterStateStore.APP_STATE }, - meta: { - disabled: false, - negate: false, - alias: '', - }, - query: { match: { extension: { query: 'foo' } } }, - }; - - await applyFilterAction.execute({ embeddable, filters: [filter], trigger: applyFilterTrigger }); - expect(root.getInput().filters.length).toBe(1); - expect(node1.getInput().filters.length).toBe(1); - expect(embeddable.getInput().filters.length).toBe(1); - expect(node2.getInput().filters.length).toBe(1); -}); - -test('ApplyFilterAction is incompatible if the root container does not accept a filter as input', async () => { - const { doStart, setup } = testPlugin(); - - const factory = new FilterableEmbeddableFactory(); - setup.registerEmbeddableFactory(factory.type, factory); - const api = doStart(); - const applyFilterAction = createFilterAction(); - - const parent = new HelloWorldContainer({ id: 'root', panels: {} }, { - getEmbeddableFactory: api.getEmbeddableFactory, - } as any); - const embeddable = await parent.addNewEmbeddable< - FilterableContainerInput, - EmbeddableOutput, - FilterableContainer - >(FILTERABLE_EMBEDDABLE, { id: 'leaf' }); - - if (isErrorEmbeddable(embeddable)) { - throw new Error(); - } - - // @ts-ignore - expect(await applyFilterAction.isCompatible({ embeddable })).toBe(false); -}); - -test('trying to execute on incompatible context throws an error ', async () => { - const { doStart, setup } = testPlugin(); - - const factory = new FilterableEmbeddableFactory(); - setup.registerEmbeddableFactory(factory.type, factory); - - const api = doStart(); - const applyFilterAction = createFilterAction(); - - const parent = new HelloWorldContainer({ id: 'root', panels: {} }, { - getEmbeddableFactory: api.getEmbeddableFactory, - } as any); - - const embeddable = await parent.addNewEmbeddable< - FilterableContainerInput, - EmbeddableOutput, - FilterableContainer - >(FILTERABLE_EMBEDDABLE, { id: 'leaf' }); - - if (isErrorEmbeddable(embeddable)) { - throw new Error(); - } - - async function check() { - await applyFilterAction.execute({ embeddable } as any); - } - await expect(check()).rejects.toThrow(Error); -}); - -test('gets title', async () => { - const applyFilterAction = createFilterAction(); - expect(applyFilterAction.getDisplayName({} as any)).toBeDefined(); -}); diff --git a/src/plugins/embeddable/public/tests/customize_panel_modal.test.tsx b/src/plugins/embeddable/public/tests/customize_panel_modal.test.tsx index d12a55dd827e6..24d94020af4dc 100644 --- a/src/plugins/embeddable/public/tests/customize_panel_modal.test.tsx +++ b/src/plugins/embeddable/public/tests/customize_panel_modal.test.tsx @@ -33,9 +33,9 @@ import { HelloWorldContainer } from '../lib/test_samples/embeddables/hello_world import { coreMock } from '../../../../core/public/mocks'; import { testPlugin } from './test_plugin'; import { CustomizePanelModal } from '../lib/panel/panel_header/panel_actions/customize_title/customize_panel_modal'; -import { mount } from 'enzyme'; import { EmbeddableStart } from '../plugin'; import { createEmbeddablePanelMock } from '../mocks'; +import { mountWithIntl } from '../../../../test_utils/public/enzyme_helpers'; let api: EmbeddableStart; let container: Container; @@ -84,19 +84,20 @@ beforeEach(async () => { } }); -test('Is initialized with the embeddables title', async () => { - const component = mount( {}} />); +test('Value is initialized with the embeddables title', async () => { + const component = mountWithIntl( + {}} cancel={() => {}} /> + ); const inputField = findTestSubject(component, 'customEmbeddablePanelTitleInput').find('input'); - expect(inputField.props().placeholder).toBe(embeddable.getOutput().title); - expect(inputField.props().placeholder).toBe(embeddable.getOutput().defaultTitle); - expect(inputField.props().value).toBe(''); + expect(inputField.props().value).toBe(embeddable.getOutput().title); + expect(inputField.props().value).toBe(embeddable.getOutput().defaultTitle); }); test('Calls updateTitle with a new title', async () => { const updateTitle = jest.fn(); - const component = mount( - + const component = mountWithIntl( + {}} /> ); const inputField = findTestSubject(component, 'customEmbeddablePanelTitleInput').find('input'); @@ -105,15 +106,15 @@ test('Calls updateTitle with a new title', async () => { findTestSubject(component, 'saveNewTitleButton').simulate('click'); - expect(updateTitle).toBeCalledWith('new title'); + expect(updateTitle).toBeCalledWith('new title', undefined); }); test('Input value shows custom title if one given', async () => { embeddable.updateInput({ title: 'new title' }); const updateTitle = jest.fn(); - const component = mount( - + const component = mountWithIntl( + {}} /> ); const inputField = findTestSubject(component, 'customEmbeddablePanelTitleInput').find('input'); @@ -122,12 +123,12 @@ test('Input value shows custom title if one given', async () => { expect(inputField.props().value).toBe('new title'); }); -test('Reset updates the input with the default title when the embeddable has no title override', async () => { +test('Reset updates the input value with the default title when the embeddable has a title override', async () => { const updateTitle = jest.fn(); embeddable.updateInput({ title: 'my custom title' }); - const component = mount( - + const component = mountWithIntl( + {}} /> ); const inputField = findTestSubject(component, 'customEmbeddablePanelTitleInput').find('input'); @@ -135,13 +136,14 @@ test('Reset updates the input with the default title when the embeddable has no inputField.simulate('change', event); findTestSubject(component, 'resetCustomEmbeddablePanelTitle').simulate('click'); - expect(inputField.props().placeholder).toBe(embeddable.getOutput().defaultTitle); + const inputAfter = findTestSubject(component, 'customEmbeddablePanelTitleInput').find('input'); + expect(inputAfter.props().value).toBe(embeddable.getOutput().defaultTitle); }); -test('Reset updates the input with the default title when the embeddable has a title override', async () => { +test('Reset updates the input with the default title when the embeddable has no title override', async () => { const updateTitle = jest.fn(); - const component = mount( - + const component = mountWithIntl( + {}} /> ); const inputField = findTestSubject(component, 'customEmbeddablePanelTitleInput').find('input'); @@ -149,13 +151,14 @@ test('Reset updates the input with the default title when the embeddable has a t inputField.simulate('change', event); findTestSubject(component, 'resetCustomEmbeddablePanelTitle').simulate('click'); - expect(inputField.props().placeholder).toBe(embeddable.getOutput().defaultTitle); + await component.update(); + expect(inputField.props().value).toBe(embeddable.getOutput().defaultTitle); }); test('Reset calls updateTitle with undefined', async () => { const updateTitle = jest.fn(); - const component = mount( - + const component = mountWithIntl( + {}} /> ); const inputField = findTestSubject(component, 'customEmbeddablePanelTitleInput').find('input'); @@ -165,19 +168,21 @@ test('Reset calls updateTitle with undefined', async () => { findTestSubject(component, 'resetCustomEmbeddablePanelTitle').simulate('click'); findTestSubject(component, 'saveNewTitleButton').simulate('click'); - expect(updateTitle).toBeCalledWith(undefined); + expect(updateTitle).toBeCalledWith(undefined, undefined); }); test('Can set title to an empty string', async () => { const updateTitle = jest.fn(); - const component = mount( - + const component = mountWithIntl( + {}} /> ); - const inputField = findTestSubject(component, 'customizePanelHideTitle'); - inputField.simulate('click'); + const inputField = findTestSubject(component, 'customEmbeddablePanelTitleInput'); + const event = { target: { value: '' } }; + inputField.simulate('change', event); findTestSubject(component, 'saveNewTitleButton').simulate('click'); - expect(inputField.props().value).toBeUndefined(); - expect(updateTitle).toBeCalledWith(''); + const inputFieldAfter = findTestSubject(component, 'customEmbeddablePanelTitleInput'); + expect(inputFieldAfter.props().value).toBe(''); + expect(updateTitle).toBeCalledWith('', undefined); }); diff --git a/src/plugins/embeddable/scripts/storybook.js b/src/plugins/embeddable/scripts/storybook.js deleted file mode 100644 index 0d7712fe973f4..0000000000000 --- a/src/plugins/embeddable/scripts/storybook.js +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { join } from 'path'; - -// eslint-disable-next-line -require('@kbn/storybook').runStorybookCli({ - name: 'embeddable', - storyGlobs: [join(__dirname, '..', 'public', 'components', '**', '*.examples.tsx')], -}); diff --git a/src/plugins/embeddable/server/plugin.ts b/src/plugins/embeddable/server/plugin.ts index f79c4b7620110..1e93561e4d063 100644 --- a/src/plugins/embeddable/server/plugin.ts +++ b/src/plugins/embeddable/server/plugin.ts @@ -35,6 +35,7 @@ import { SerializableState } from '../../kibana_utils/common'; import { EmbeddableInput } from '../common/types'; export interface EmbeddableSetup { + getAttributeService: any; registerEmbeddableFactory: (factory: EmbeddableRegistryDefinition) => void; registerEnhancement: (enhancement: EnhancementRegistryDefinition) => void; } diff --git a/src/plugins/embeddable/server/server.api.md b/src/plugins/embeddable/server/server.api.md new file mode 100644 index 0000000000000..d051793382ab7 --- /dev/null +++ b/src/plugins/embeddable/server/server.api.md @@ -0,0 +1,52 @@ +## API Report File for "kibana" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts + +import { CoreSetup } from 'kibana/server'; +import { CoreStart } from 'kibana/server'; +import { Plugin } from 'kibana/server'; +import { SavedObjectReference as SavedObjectReference_2 } from 'kibana/server'; + +// Warning: (ae-forgotten-export) The symbol "EmbeddableInput" needs to be exported by the entry point index.d.ts +// Warning: (ae-forgotten-export) The symbol "PersistableStateDefinition" needs to be exported by the entry point index.d.ts +// Warning: (ae-missing-release-tag) "EmbeddableRegistryDefinition" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export interface EmbeddableRegistryDefinition

extends PersistableStateDefinition

{ + // (undocumented) + id: string; +} + +// Warning: (ae-missing-release-tag) "EmbeddableSetup" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export interface EmbeddableSetup { + // (undocumented) + getAttributeService: any; + // (undocumented) + registerEmbeddableFactory: (factory: EmbeddableRegistryDefinition) => void; + // (undocumented) + registerEnhancement: (enhancement: EnhancementRegistryDefinition) => void; +} + +// Warning: (ae-forgotten-export) The symbol "SerializableState" needs to be exported by the entry point index.d.ts +// Warning: (ae-missing-release-tag) "EnhancementRegistryDefinition" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export interface EnhancementRegistryDefinition

extends PersistableStateDefinition

-
-
- - - -

- -

-
-
- - - - - Add data - - - - -
-
-
+ + } + />
- 0 @@ -73,115 +42,36 @@ exports[`home change home route should render a link to change the default route aria-hidden="true" margin="xl" /> -
- - - - - - - - - - - - -
+
`; exports[`home directories should not render directory entry when showOnHomePage is false 1`] = `
-
-
- - - -

- -

-
-
- - - - - Add data - - - - - Manage - - - - -
-
-
+ + } + />
- 0 @@ -202,92 +92,36 @@ exports[`home directories should not render directory entry when showOnHomePage aria-hidden="true" margin="xl" /> -
- - - - - - - - -
+
`; exports[`home directories should render ADMIN directory entry in "Manage your data" panel 1`] = `
-
-
- - - -

- -

-
-
- - - - - Add data - - - - -
-
-
+ + } + />
- 0 @@ -320,92 +154,36 @@ exports[`home directories should render ADMIN directory entry in "Manage your da aria-hidden="true" margin="xl" /> -
- - - - - - - - -
+
`; exports[`home directories should render DATA directory entry in "Ingest your data" panel 1`] = `
-
-
- - - -

- -

-
-
- - - - - Add data - - - - -
-
-
+ + } + />
- 0 @@ -438,97 +216,43 @@ exports[`home directories should render DATA directory entry in "Ingest your dat aria-hidden="true" margin="xl" /> -
- - - - - - - - -
+
`; exports[`home directories should render solutions in the "solution section" 1`] = `
-
-
- - - -

- -

-
-
- - - - - Add data - - - - -
-
-
+ + } + />
`; exports[`home header render 1`] = `
-
-
- - - -

- -

-
-
- - - - - Add data - - - - -
-
-
+ + } + />
- 0 @@ -700,102 +368,36 @@ exports[`home header render 1`] = ` aria-hidden="true" margin="xl" /> -
- - - - - - - - -
+
`; exports[`home header should show "Dev tools" link if console is available 1`] = `
-
-
- - - -

- -

-
-
- - - - - Add data - - - - - Dev tools - - - - -
-
-
+ + } + />
- 0 @@ -828,103 +430,36 @@ exports[`home header should show "Dev tools" link if console is available 1`] = aria-hidden="true" margin="xl" /> -
- - - - - - - - -
+
`; exports[`home header should show "Manage" link if stack management is available 1`] = `
-
-
- - - -

- -

-
-
- - - - - Add data - - - - - Manage - - - - -
-
-
+ + } + />
- 0 @@ -945,92 +480,36 @@ exports[`home header should show "Manage" link if stack management is available aria-hidden="true" margin="xl" /> -
- - - - - - - - -
+
`; exports[`home isNewKibanaInstance should safely handle execeptions 1`] = `
-
-
- - - -

- -

-
-
- - - - - Add data - - - - -
-
-
+ + } + />
- 0 @@ -1051,92 +530,36 @@ exports[`home isNewKibanaInstance should safely handle execeptions 1`] = ` aria-hidden="true" margin="xl" /> -
- - - - - - - - -
+
`; exports[`home isNewKibanaInstance should set isNewKibanaInstance to false when there are index patterns 1`] = `
-
-
- - - -

- -

-
-
- - - - - Add data - - - - -
-
-
+ + } + />
- 0 @@ -1157,92 +580,36 @@ exports[`home isNewKibanaInstance should set isNewKibanaInstance to false when t aria-hidden="true" margin="xl" /> -
- - - - - - - - -
+
`; exports[`home isNewKibanaInstance should set isNewKibanaInstance to true when there are no index patterns 1`] = `
-
-
- - - -

- -

-
-
- - - - - Add data - - - - -
-
-
+ + } + />
- 0 @@ -1263,92 +630,36 @@ exports[`home isNewKibanaInstance should set isNewKibanaInstance to true when th aria-hidden="true" margin="xl" /> -
- - - - - - - - -
+
`; exports[`home should render home component 1`] = `
-
-
- - - -

- -

-
-
- - - - - Add data - - - - -
-
-
+ + } + />
- 0 @@ -1369,92 +680,36 @@ exports[`home should render home component 1`] = ` aria-hidden="true" margin="xl" /> -
- - - - - - - - -
+
`; exports[`home welcome should show the normal home page if loading fails 1`] = `
-
-
- - - -

- -

-
-
- - - - - Add data - - - - -
-
-
+ + } + />
- 0 @@ -1475,92 +730,36 @@ exports[`home welcome should show the normal home page if loading fails 1`] = ` aria-hidden="true" margin="xl" /> -
- - - - - - - - -
+
`; exports[`home welcome should show the normal home page if welcome screen is disabled locally 1`] = `
-
-
- - - -

- -

-
-
- - - - - Add data - - - - -
-
-
+ + } + />
- 0 @@ -1581,35 +780,10 @@ exports[`home welcome should show the normal home page if welcome screen is disa aria-hidden="true" margin="xl" /> -
- - - - - - - - -
+
`; @@ -1623,57 +797,26 @@ exports[`home welcome should show the welcome screen if enabled, and there are n exports[`home welcome stores skip welcome setting if skipped 1`] = `
-
-
- - - -

- -

-
-
- - - - - Add data - - - - -
-
-
+ + } + />
- 0 @@ -1694,35 +837,10 @@ exports[`home welcome stores skip welcome setting if skipped 1`] = ` aria-hidden="true" margin="xl" /> -
- - - - - - - - -
+
`; diff --git a/src/plugins/home/public/application/components/__snapshots__/synopsis.test.js.snap b/src/plugins/home/public/application/components/__snapshots__/synopsis.test.js.snap index 190985f70659d..ec192ce1eb32f 100644 --- a/src/plugins/home/public/application/components/__snapshots__/synopsis.test.js.snap +++ b/src/plugins/home/public/application/components/__snapshots__/synopsis.test.js.snap @@ -9,6 +9,7 @@ exports[`props iconType 1`] = ` href="link_to_item" icon={ - - - +
+ + + +
= ({ addBasePath, features }) => (
- +

@@ -43,18 +43,21 @@ export const AddData: FC = ({ addBasePath, features }) => ( - - - - + +
+ + + +
diff --git a/src/plugins/home/public/application/components/app_navigation_handler.ts b/src/plugins/home/public/application/components/app_navigation_handler.ts index 61d85c033b544..b6230bc9f1e38 100644 --- a/src/plugins/home/public/application/components/app_navigation_handler.ts +++ b/src/plugins/home/public/application/components/app_navigation_handler.ts @@ -24,12 +24,7 @@ export const createAppNavigationHandler = (targetUrl: string) => (event: MouseEv if (event.altKey || event.metaKey || event.ctrlKey) { return; } - if (targetUrl.startsWith('/app/')) { - const [, appId, path] = /\/app\/(.*?)((\/|\?|#|$).*)/.exec(targetUrl) || []; - if (!appId) { - return; - } - event.preventDefault(); - getServices().application.navigateToApp(appId, { path }); - } + const { application, addBasePath } = getServices(); + event.preventDefault(); + application.navigateToUrl(addBasePath(targetUrl)); }; diff --git a/src/plugins/home/public/application/components/home.js b/src/plugins/home/public/application/components/home.js index becafb2560217..054f5a5344df4 100644 --- a/src/plugins/home/public/application/components/home.js +++ b/src/plugins/home/public/application/components/home.js @@ -20,18 +20,16 @@ import React, { Component } from 'react'; import PropTypes from 'prop-types'; import { FormattedMessage } from '@kbn/i18n/react'; -import { - EuiButtonEmpty, - EuiTitle, - EuiFlexGroup, - EuiFlexItem, - EuiHorizontalRule, -} from '@elastic/eui'; +import { EuiFlexGroup, EuiFlexItem, EuiHorizontalRule } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; +import { + OverviewPageFooter, + OverviewPageHeader, +} from '../../../../../../src/plugins/kibana_react/public'; +import { HOME_APP_BASE_PATH } from '../../../common/constants'; import { FeatureCatalogueCategory } from '../../services'; import { getServices } from '../kibana_services'; import { AddData } from './add_data'; -import { createAppNavigationHandler } from './app_navigation_handler'; import { ManageData } from './manage_data'; import { SolutionsSection } from './solutions_section'; import { Welcome } from './welcome'; @@ -121,12 +119,9 @@ export class Home extends Component { .sort((directoryA, directoryB) => directoryA.order - directoryB.order); renderNormal() { - const { addBasePath, solutions } = this.props; + const { addBasePath, solutions, directories } = this.props; const devTools = this.findDirectoryById('console'); - const stackManagement = this.findDirectoryById('stack-management'); - const advancedSettings = this.findDirectoryById('advanced_settings'); - const addDataFeatures = this.getFeaturesByCategory(FeatureCatalogueCategory.DATA); const manageDataFeatures = this.getFeaturesByCategory(FeatureCatalogueCategory.ADMIN); @@ -136,68 +131,27 @@ export class Home extends Component { } return ( -
-
-
- - - -

- -

-
-
- - - - - - {i18n.translate('home.pageHeader.addDataButtonLabel', { - defaultMessage: 'Add data', - })} - - - - {stackManagement ? ( - - - {i18n.translate('home.pageHeader.stackManagementButtonLabel', { - defaultMessage: 'Manage', - })} - - - ) : null} - - {devTools ? ( - - - {i18n.translate('home.pageHeader.devToolsButtonLabel', { - defaultMessage: 'Dev tools', - })} - - - ) : null} - - -
-
-
+
+ } + />
- {solutions.length && } + {solutions.length ? ( + + ) : null}
); @@ -294,12 +214,14 @@ Home.propTypes = { PropTypes.shape({ id: PropTypes.string.isRequired, title: PropTypes.string.isRequired, + subtitle: PropTypes.string, description: PropTypes.string.isRequired, icon: PropTypes.string.isRequired, path: PropTypes.string.isRequired, showOnHomePage: PropTypes.bool.isRequired, category: PropTypes.string.isRequired, order: PropTypes.number, + solutionId: PropTypes.string, }) ), solutions: PropTypes.arrayOf( @@ -307,7 +229,8 @@ Home.propTypes = { id: PropTypes.string.isRequired, title: PropTypes.string.isRequired, subtitle: PropTypes.string.isRequired, - descriptions: PropTypes.arrayOf(PropTypes.string).isRequired, + description: PropTypes.string, + appDescriptions: PropTypes.arrayOf(PropTypes.string).isRequired, icon: PropTypes.string.isRequired, path: PropTypes.string.isRequired, order: PropTypes.number, diff --git a/src/plugins/home/public/application/components/home.test.js b/src/plugins/home/public/application/components/home.test.js index 0d7596d92a5a1..9c73bbf9b75ba 100644 --- a/src/plugins/home/public/application/components/home.test.js +++ b/src/plugins/home/public/application/components/home.test.js @@ -35,6 +35,11 @@ jest.mock('../kibana_services', () => ({ }), })); +jest.mock('../../../../../../src/plugins/kibana_react/public', () => ({ + OverviewPageFooter: jest.fn().mockReturnValue(<>), + OverviewPageHeader: jest.fn().mockReturnValue(<>), +})); + describe('home', () => { let defaultProps; @@ -142,7 +147,7 @@ describe('home', () => { id: 'kibana', title: 'Kibana', subtitle: 'Visualize & analyze', - descriptions: ['Analyze data in dashboards'], + appDescriptions: ['Analyze data in dashboards'], icon: 'logoKibana', path: 'kibana_landing_page', order: 1, @@ -151,7 +156,7 @@ describe('home', () => { id: 'solution-2', title: 'Solution two', subtitle: 'Subtitle for solution two', - descriptions: ['Example use case'], + appDescriptions: ['Example use case'], icon: 'empty', path: 'path-to-solution-two', order: 2, @@ -160,7 +165,7 @@ describe('home', () => { id: 'solution-3', title: 'Solution three', subtitle: 'Subtitle for solution three', - descriptions: ['Example use case'], + appDescriptions: ['Example use case'], icon: 'empty', path: 'path-to-solution-three', order: 3, @@ -169,7 +174,7 @@ describe('home', () => { id: 'solution-4', title: 'Solution four', subtitle: 'Subtitle for solution four', - descriptions: ['Example use case'], + appDescriptions: ['Example use case'], icon: 'empty', path: 'path-to-solution-four', order: 4, diff --git a/src/plugins/home/public/application/components/home_app.js b/src/plugins/home/public/application/components/home_app.js index 69cd68d553d03..7fe4f4351c35b 100644 --- a/src/plugins/home/public/application/components/home_app.js +++ b/src/plugins/home/public/application/components/home_app.js @@ -104,12 +104,14 @@ HomeApp.propTypes = { PropTypes.shape({ id: PropTypes.string.isRequired, title: PropTypes.string.isRequired, + subtitle: PropTypes.string, description: PropTypes.string.isRequired, icon: PropTypes.string.isRequired, path: PropTypes.string.isRequired, showOnHomePage: PropTypes.bool.isRequired, category: PropTypes.string.isRequired, order: PropTypes.number, + solutionId: PropTypes.string, }) ), solutions: PropTypes.arrayOf( @@ -117,7 +119,8 @@ HomeApp.propTypes = { id: PropTypes.string.isRequired, title: PropTypes.string.isRequired, subtitle: PropTypes.string.isRequired, - descriptions: PropTypes.arrayOf(PropTypes.string).isRequired, + description: PropTypes.string, + appDescriptions: PropTypes.arrayOf(PropTypes.string).isRequired, icon: PropTypes.string.isRequired, path: PropTypes.string.isRequired, order: PropTypes.number, diff --git a/src/plugins/home/public/application/components/manage_data/manage_data.test.tsx b/src/plugins/home/public/application/components/manage_data/manage_data.test.tsx index 0e86bf7dd3d84..18a58e86eaa3f 100644 --- a/src/plugins/home/public/application/components/manage_data/manage_data.test.tsx +++ b/src/plugins/home/public/application/components/manage_data/manage_data.test.tsx @@ -37,7 +37,6 @@ const mockFeatures = [ { category: 'admin', description: 'Control who has access and what tasks they can perform.', - homePageSection: 'manage_data', icon: 'securityApp', id: 'security', order: 600, @@ -48,7 +47,6 @@ const mockFeatures = [ { category: 'admin', description: 'Track the real-time health and performance of your deployment.', - homePageSection: 'manage_data', icon: 'monitoringApp', id: 'monitoring', order: 610, @@ -60,7 +58,6 @@ const mockFeatures = [ category: 'admin', description: 'Save snapshots to a backup repository, and restore to recover index and cluster state.', - homePageSection: 'manage_data', icon: 'storage', id: 'snapshot_restore', order: 630, @@ -71,7 +68,6 @@ const mockFeatures = [ { category: 'admin', description: 'Define lifecycle policies to automatically perform operations as an index ages.', - homePageSection: 'manage_data', icon: 'indexSettings', id: 'index_lifecycle_management', order: 640, diff --git a/src/plugins/home/public/application/components/sample_data/index.tsx b/src/plugins/home/public/application/components/sample_data/index.tsx index 2a51b48b08469..5f15994acc1cb 100644 --- a/src/plugins/home/public/application/components/sample_data/index.tsx +++ b/src/plugins/home/public/application/components/sample_data/index.tsx @@ -30,8 +30,8 @@ import { EuiButton, EuiButtonEmpty, } from '@elastic/eui'; - import { FormattedMessage } from '@kbn/i18n/react'; +import { getServices } from '../../kibana_services'; interface Props { urlBasePath: string; @@ -40,22 +40,29 @@ interface Props { } export function SampleDataCard({ urlBasePath, onDecline, onConfirm }: Props) { + const IS_DARK_THEME = getServices().uiSettings.get('theme:darkMode'); + const cardGraphicFile = !IS_DARK_THEME + ? 'illustration_integrations_lightmode.png' + : 'illustration_integrations_darkmode.png'; + const cardGraphicURL = `${urlBasePath}/plugins/home/assets/common/${cardGraphicFile}`; + return ( } + title={ + + } description={ } footer={
- +

diff --git a/src/plugins/home/public/application/components/solutions_section/__snapshots__/solutions_section.test.tsx.snap b/src/plugins/home/public/application/components/solutions_section/__snapshots__/solutions_section.test.tsx.snap index 7015ebb40a71d..4052ffca9e56f 100644 --- a/src/plugins/home/public/application/components/solutions_section/__snapshots__/solutions_section.test.tsx.snap +++ b/src/plugins/home/public/application/components/solutions_section/__snapshots__/solutions_section.test.tsx.snap @@ -7,19 +7,15 @@ exports[`SolutionsSection only renders a spacer if no solutions are available 1` className="homSolutions" > - -

- -

-
+ +

- -

- -

-
+ +

- -

- -

-
+ +
- -

- -

-
+ +
- descriptions.map(getDescriptionText).reduce(addSpacersBetweenElementsReducer, []); +const getDescriptions = (appDescriptions: string[]) => + appDescriptions + .map(getDescriptionText) + .reduce(addSpacersBetweenElementsReducer, []); interface Props { addBasePath: (path: string) => string; solution: FeatureCatalogueSolution; + apps?: FeatureCatalogueEntry[]; } -export const SolutionPanel: FC = ({ addBasePath, solution }) => ( +export const SolutionPanel: FC = ({ addBasePath, solution, apps = [] }) => ( = ({ addBasePath, solution }) => ( href={addBasePath(solution.path)} onClick={createAppNavigationHandler(solution.path)} > - + = ({ addBasePath, solution }) => ( - {getDescriptions(solution.descriptions)} + {getDescriptions( + apps.length ? apps.map(({ subtitle = '' }) => subtitle) : solution.appDescriptions + )} diff --git a/src/plugins/home/public/application/components/solutions_section/solution_title.tsx b/src/plugins/home/public/application/components/solutions_section/solution_title.tsx index fb833a40807d2..a9874ff7ddbe7 100644 --- a/src/plugins/home/public/application/components/solutions_section/solution_title.tsx +++ b/src/plugins/home/public/application/components/solutions_section/solution_title.tsx @@ -45,7 +45,7 @@ export const SolutionTitle: FC = ({ title, subtitle, iconType }) => ( className="homSolutionPanel__icon" /> - +

{title}

diff --git a/src/plugins/home/public/application/components/solutions_section/solutions_section.test.tsx b/src/plugins/home/public/application/components/solutions_section/solutions_section.test.tsx index 17d721cc96c02..9ec5bf695b35c 100644 --- a/src/plugins/home/public/application/components/solutions_section/solutions_section.test.tsx +++ b/src/plugins/home/public/application/components/solutions_section/solutions_section.test.tsx @@ -20,12 +20,13 @@ import React from 'react'; import { shallow } from 'enzyme'; import { SolutionsSection } from './solutions_section'; +import { FeatureCatalogueCategory } from '../../../services'; const solutionEntry1 = { id: 'kibana', title: 'Kibana', subtitle: 'Visualize & analyze', - descriptions: ['Analyze data in dashboards'], + appDescriptions: ['Analyze data in dashboards'], icon: 'logoKibana', path: 'kibana_landing_page', order: 1, @@ -34,7 +35,8 @@ const solutionEntry2 = { id: 'solution-2', title: 'Solution two', subtitle: 'Subtitle for solution two', - descriptions: ['Example use case'], + description: 'Description for solution two', + appDescriptions: ['Example use case'], icon: 'empty', path: 'path-to-solution-two', order: 2, @@ -43,7 +45,8 @@ const solutionEntry3 = { id: 'solution-3', title: 'Solution three', subtitle: 'Subtitle for solution three', - descriptions: ['Example use case'], + description: 'Description for solution three', + appDescriptions: ['Example use case'], icon: 'empty', path: 'path-to-solution-three', order: 3, @@ -52,23 +55,64 @@ const solutionEntry4 = { id: 'solution-4', title: 'Solution four', subtitle: 'Subtitle for solution four', - descriptions: ['Example use case'], + description: 'Description for solution four', + appDescriptions: ['Example use case'], icon: 'empty', path: 'path-to-solution-four', order: 4, }; +const mockDirectories = [ + { + id: 'dashboard', + title: 'Dashboard', + description: 'Description of dashboard', + icon: 'dashboardApp', + path: 'dashboard_landing_page', + showOnHomePage: false, + category: FeatureCatalogueCategory.DATA, + }, + { + id: 'discover', + title: 'Discover', + description: 'Description of discover', + icon: 'discoverApp', + path: 'discover_landing_page', + showOnHomePage: false, + category: FeatureCatalogueCategory.DATA, + }, + { + id: 'canvas', + title: 'Canvas', + description: 'Description of canvas', + icon: 'canvasApp', + path: 'canvas_landing_page', + showOnHomePage: false, + category: FeatureCatalogueCategory.DATA, + }, +]; + const addBasePathMock = (path: string) => (path ? path : 'path'); describe('SolutionsSection', () => { test('only renders a spacer if no solutions are available', () => { - const component = shallow(); + const component = shallow( + + ); expect(component).toMatchSnapshot(); }); test('renders a single solution', () => { const component = shallow( - + ); expect(component).toMatchSnapshot(); }); @@ -78,6 +122,7 @@ describe('SolutionsSection', () => { ); expect(component).toMatchSnapshot(); @@ -87,6 +132,7 @@ describe('SolutionsSection', () => { ); expect(component).toMatchSnapshot(); diff --git a/src/plugins/home/public/application/components/solutions_section/solutions_section.tsx b/src/plugins/home/public/application/components/solutions_section/solutions_section.tsx index 1a78a6c71030a..13b70383147eb 100644 --- a/src/plugins/home/public/application/components/solutions_section/solutions_section.tsx +++ b/src/plugins/home/public/application/components/solutions_section/solutions_section.tsx @@ -19,16 +19,10 @@ import React, { FC } from 'react'; import PropTypes from 'prop-types'; -import { - EuiFlexGroup, - EuiFlexItem, - EuiHorizontalRule, - EuiScreenReaderOnly, - EuiTitle, -} from '@elastic/eui'; +import { EuiFlexGroup, EuiFlexItem, EuiHorizontalRule, EuiScreenReaderOnly } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; import { SolutionPanel } from './solution_panel'; -import { FeatureCatalogueSolution } from '../../../'; +import { FeatureCatalogueEntry, FeatureCatalogueSolution } from '../../../'; const sortByOrder = ( { order: orderA = 0 }: FeatureCatalogueSolution, @@ -38,25 +32,25 @@ const sortByOrder = ( interface Props { addBasePath: (path: string) => string; solutions: FeatureCatalogueSolution[]; + directories: FeatureCatalogueEntry[]; } -export const SolutionsSection: FC = ({ addBasePath, solutions }) => { +export const SolutionsSection: FC = ({ addBasePath, solutions, directories }) => { // Separate Kibana from other solutions const kibana = solutions.find(({ id }) => id === 'kibana'); + const kibanaApps = directories.filter(({ solutionId }) => solutionId === 'kibana'); solutions = solutions.sort(sortByOrder).filter(({ id }) => id !== 'kibana'); return ( <>
- -

- -

-
+

+ +

@@ -69,7 +63,13 @@ export const SolutionsSection: FC = ({ addBasePath, solutions }) => { ) : null} - {kibana ? : null} + {kibana ? ( + + ) : null}
@@ -79,12 +79,28 @@ export const SolutionsSection: FC = ({ addBasePath, solutions }) => { }; SolutionsSection.propTypes = { + addBasePath: PropTypes.func.isRequired, + directories: PropTypes.arrayOf( + PropTypes.shape({ + id: PropTypes.string.isRequired, + title: PropTypes.string.isRequired, + subtitle: PropTypes.string, + description: PropTypes.string.isRequired, + icon: PropTypes.string.isRequired, + path: PropTypes.string.isRequired, + showOnHomePage: PropTypes.bool.isRequired, + category: PropTypes.string.isRequired, + order: PropTypes.number, + solutionId: PropTypes.string, + }) + ), solutions: PropTypes.arrayOf( PropTypes.shape({ id: PropTypes.string.isRequired, title: PropTypes.string.isRequired, subtitle: PropTypes.string.isRequired, - descriptions: PropTypes.arrayOf(PropTypes.string).isRequired, + description: PropTypes.string, + appDescriptions: PropTypes.arrayOf(PropTypes.string).isRequired, icon: PropTypes.string.isRequired, path: PropTypes.string.isRequired, order: PropTypes.number, diff --git a/src/plugins/home/public/application/components/synopsis.js b/src/plugins/home/public/application/components/synopsis.js index fbe3bb3ed6769..0777c0db7210e 100644 --- a/src/plugins/home/public/application/components/synopsis.js +++ b/src/plugins/home/public/application/components/synopsis.js @@ -38,7 +38,7 @@ export function Synopsis({ if (iconUrl) { optionalImg = ; } else if (iconType) { - optionalImg = ; + optionalImg = ; } const classes = classNames('homSynopsis__card', { diff --git a/src/plugins/home/public/application/components/welcome.tsx b/src/plugins/home/public/application/components/welcome.tsx index 404185de3d2ea..a758f1af39946 100644 --- a/src/plugins/home/public/application/components/welcome.tsx +++ b/src/plugins/home/public/application/components/welcome.tsx @@ -58,8 +58,8 @@ export class Welcome extends React.Component { } }; - private redirecToSampleData() { - const path = this.services.addBasePath('#/tutorial_directory/sampleData'); + private redirecToAddData() { + const path = this.services.addBasePath('#/tutorial_directory'); window.location.href = path; } @@ -70,7 +70,7 @@ export class Welcome extends React.Component { private onSampleDataConfirm = () => { this.services.trackUiMetric(METRIC_TYPE.CLICK, 'sampleDataConfirm'); - this.redirecToSampleData(); + this.redirecToAddData(); }; componentDidMount() { diff --git a/src/plugins/home/public/assets/auditd_logs/screenshot.png b/src/plugins/home/public/assets/auditd_logs/screenshot.png new file mode 100644 index 0000000000000..732afa18dc11c Binary files /dev/null and b/src/plugins/home/public/assets/auditd_logs/screenshot.png differ diff --git a/src/plugins/home/public/assets/common/illustration_integrations_darkmode.png b/src/plugins/home/public/assets/common/illustration_integrations_darkmode.png new file mode 100644 index 0000000000000..0ca4dd25982ae Binary files /dev/null and b/src/plugins/home/public/assets/common/illustration_integrations_darkmode.png differ diff --git a/src/plugins/home/public/assets/common/illustration_integrations_lightmode.png b/src/plugins/home/public/assets/common/illustration_integrations_lightmode.png new file mode 100644 index 0000000000000..dd1aaeb2d26b3 Binary files /dev/null and b/src/plugins/home/public/assets/common/illustration_integrations_lightmode.png differ diff --git a/src/plugins/home/public/assets/coredns_logs/screenshot.png b/src/plugins/home/public/assets/coredns_logs/screenshot.png new file mode 100644 index 0000000000000..70921fa9bafb2 Binary files /dev/null and b/src/plugins/home/public/assets/coredns_logs/screenshot.png differ diff --git a/src/plugins/home/public/assets/crowdstrike_logs/screenshot.png b/src/plugins/home/public/assets/crowdstrike_logs/screenshot.png new file mode 100644 index 0000000000000..b74edfe2293f9 Binary files /dev/null and b/src/plugins/home/public/assets/crowdstrike_logs/screenshot.png differ diff --git a/src/plugins/home/public/assets/googlecloud_logs/screenshot.png b/src/plugins/home/public/assets/googlecloud_logs/screenshot.png new file mode 100644 index 0000000000000..4f68932e9f709 Binary files /dev/null and b/src/plugins/home/public/assets/googlecloud_logs/screenshot.png differ diff --git a/src/plugins/home/public/assets/haproxy_logs/screenshot.png b/src/plugins/home/public/assets/haproxy_logs/screenshot.png new file mode 100644 index 0000000000000..85a24bf01f3aa Binary files /dev/null and b/src/plugins/home/public/assets/haproxy_logs/screenshot.png differ diff --git a/src/plugins/home/public/assets/icinga_logs/screenshot.png b/src/plugins/home/public/assets/icinga_logs/screenshot.png new file mode 100644 index 0000000000000..013b20fcf166e Binary files /dev/null and b/src/plugins/home/public/assets/icinga_logs/screenshot.png differ diff --git a/src/plugins/home/public/assets/illustration_elastic_heart.png b/src/plugins/home/public/assets/illustration_elastic_heart.png deleted file mode 100644 index f4bf5b09ed7af..0000000000000 Binary files a/src/plugins/home/public/assets/illustration_elastic_heart.png and /dev/null differ diff --git a/src/plugins/home/public/assets/logos/barracuda.svg b/src/plugins/home/public/assets/logos/barracuda.svg new file mode 100644 index 0000000000000..555cdd6f8a32b --- /dev/null +++ b/src/plugins/home/public/assets/logos/barracuda.svg @@ -0,0 +1,100 @@ + + + + + + + + + diff --git a/src/plugins/home/public/assets/logos/checkpoint.svg b/src/plugins/home/public/assets/logos/checkpoint.svg new file mode 100644 index 0000000000000..e71866e78c293 --- /dev/null +++ b/src/plugins/home/public/assets/logos/checkpoint.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/plugins/home/public/assets/logos/crowdstrike.svg b/src/plugins/home/public/assets/logos/crowdstrike.svg new file mode 100644 index 0000000000000..1b2195a2244f9 --- /dev/null +++ b/src/plugins/home/public/assets/logos/crowdstrike.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/plugins/home/public/assets/logos/cylance.svg b/src/plugins/home/public/assets/logos/cylance.svg new file mode 100644 index 0000000000000..ccd6004d19e76 --- /dev/null +++ b/src/plugins/home/public/assets/logos/cylance.svg @@ -0,0 +1,82 @@ + + + + +Cylance_BB_Logo_RGB_Vert_Black + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/plugins/home/public/assets/logos/f5.svg b/src/plugins/home/public/assets/logos/f5.svg new file mode 100644 index 0000000000000..d985bde96291f --- /dev/null +++ b/src/plugins/home/public/assets/logos/f5.svg @@ -0,0 +1 @@ +Asset 1 \ No newline at end of file diff --git a/src/plugins/home/public/assets/logos/fortinet.svg b/src/plugins/home/public/assets/logos/fortinet.svg new file mode 100644 index 0000000000000..d6a8448f320bc --- /dev/null +++ b/src/plugins/home/public/assets/logos/fortinet.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/src/plugins/home/public/assets/logos/icinga.svg b/src/plugins/home/public/assets/logos/icinga.svg new file mode 100644 index 0000000000000..88161d61ca75e --- /dev/null +++ b/src/plugins/home/public/assets/logos/icinga.svg @@ -0,0 +1,87 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/plugins/home/public/assets/logos/infoblox.svg b/src/plugins/home/public/assets/logos/infoblox.svg new file mode 100644 index 0000000000000..57b4d23b16812 --- /dev/null +++ b/src/plugins/home/public/assets/logos/infoblox.svg @@ -0,0 +1,93 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/plugins/home/public/assets/logos/juniper.svg b/src/plugins/home/public/assets/logos/juniper.svg new file mode 100644 index 0000000000000..8802414a5aafe --- /dev/null +++ b/src/plugins/home/public/assets/logos/juniper.svg @@ -0,0 +1,72 @@ + +image/svg+xml \ No newline at end of file diff --git a/src/plugins/home/public/assets/logos/linux.svg b/src/plugins/home/public/assets/logos/linux.svg new file mode 100644 index 0000000000000..c0a92e0c0f404 --- /dev/null +++ b/src/plugins/home/public/assets/logos/linux.svg @@ -0,0 +1,1532 @@ + + + + Tux + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + Tux + 20 June 2012 + + + Garrett LeSage + + + + + + Larry Ewing, the creator of the original Tux graphic + + + + + tux + Linux + penguin + logo + + + + + Larry Ewing, Garrett LeSage + + + https://github.com/garrett/Tux + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/plugins/home/public/assets/logos/microsoft.svg b/src/plugins/home/public/assets/logos/microsoft.svg new file mode 100644 index 0000000000000..5334aa7ca6864 --- /dev/null +++ b/src/plugins/home/public/assets/logos/microsoft.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/plugins/home/public/assets/logos/misp.svg b/src/plugins/home/public/assets/logos/misp.svg new file mode 100644 index 0000000000000..1cc61eda0b608 --- /dev/null +++ b/src/plugins/home/public/assets/logos/misp.svg @@ -0,0 +1,167 @@ + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + Threat Sharing + + + + + + + + + + + + diff --git a/src/plugins/home/public/assets/logos/netscout.svg b/src/plugins/home/public/assets/logos/netscout.svg new file mode 100644 index 0000000000000..cbd25cd92594a --- /dev/null +++ b/src/plugins/home/public/assets/logos/netscout.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/src/plugins/home/public/assets/logos/o365.svg b/src/plugins/home/public/assets/logos/o365.svg new file mode 100644 index 0000000000000..3763f267ffc7a --- /dev/null +++ b/src/plugins/home/public/assets/logos/o365.svg @@ -0,0 +1,16 @@ + + + logo-integrations-Desktop HD Copy 2 + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/plugins/home/public/assets/logos/okta.svg b/src/plugins/home/public/assets/logos/okta.svg new file mode 100644 index 0000000000000..d806cb7dc6451 --- /dev/null +++ b/src/plugins/home/public/assets/logos/okta.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/plugins/home/public/assets/logos/oracle.svg b/src/plugins/home/public/assets/logos/oracle.svg new file mode 100644 index 0000000000000..1056521d9d5b3 --- /dev/null +++ b/src/plugins/home/public/assets/logos/oracle.svg @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/plugins/home/public/assets/logos/osquery.svg b/src/plugins/home/public/assets/logos/osquery.svg new file mode 100755 index 0000000000000..c2bf733d35931 --- /dev/null +++ b/src/plugins/home/public/assets/logos/osquery.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/plugins/home/public/assets/logos/paloalto.svg b/src/plugins/home/public/assets/logos/paloalto.svg new file mode 100644 index 0000000000000..8c8e71ae0d9fc --- /dev/null +++ b/src/plugins/home/public/assets/logos/paloalto.svg @@ -0,0 +1,29 @@ + + + logo-integrations-Desktop HD + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/plugins/home/public/assets/logos/rabbitmq.svg b/src/plugins/home/public/assets/logos/rabbitmq.svg new file mode 100644 index 0000000000000..dabd2a5744cb4 --- /dev/null +++ b/src/plugins/home/public/assets/logos/rabbitmq.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/plugins/home/public/assets/logos/radware.svg b/src/plugins/home/public/assets/logos/radware.svg new file mode 100644 index 0000000000000..6252efef77624 --- /dev/null +++ b/src/plugins/home/public/assets/logos/radware.svg @@ -0,0 +1,66 @@ + +image/svg+xml \ No newline at end of file diff --git a/src/plugins/home/public/assets/logos/sonicwall.svg b/src/plugins/home/public/assets/logos/sonicwall.svg new file mode 100644 index 0000000000000..fb1aded68a29e --- /dev/null +++ b/src/plugins/home/public/assets/logos/sonicwall.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/plugins/home/public/assets/logos/sophos.svg b/src/plugins/home/public/assets/logos/sophos.svg new file mode 100644 index 0000000000000..1f2cfc3a7f036 --- /dev/null +++ b/src/plugins/home/public/assets/logos/sophos.svg @@ -0,0 +1,69 @@ + + + +image/svg+xml \ No newline at end of file diff --git a/src/plugins/home/public/assets/logos/tomcat.svg b/src/plugins/home/public/assets/logos/tomcat.svg new file mode 100644 index 0000000000000..410a468872e17 --- /dev/null +++ b/src/plugins/home/public/assets/logos/tomcat.svg @@ -0,0 +1,107 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/plugins/home/public/assets/logos/zscaler.svg b/src/plugins/home/public/assets/logos/zscaler.svg new file mode 100644 index 0000000000000..b8a21a2fa6eed --- /dev/null +++ b/src/plugins/home/public/assets/logos/zscaler.svg @@ -0,0 +1 @@ +Zscaler-Logo-TM-Blue-RGB-May2019 \ No newline at end of file diff --git a/src/plugins/home/public/assets/microsoft_logs/screenshot.png b/src/plugins/home/public/assets/microsoft_logs/screenshot.png new file mode 100644 index 0000000000000..7df250e2ae885 Binary files /dev/null and b/src/plugins/home/public/assets/microsoft_logs/screenshot.png differ diff --git a/src/plugins/home/public/assets/misp_logs/screenshot.png b/src/plugins/home/public/assets/misp_logs/screenshot.png new file mode 100644 index 0000000000000..a02068ddf3038 Binary files /dev/null and b/src/plugins/home/public/assets/misp_logs/screenshot.png differ diff --git a/src/plugins/home/public/assets/mongodb_logs/screenshot.png b/src/plugins/home/public/assets/mongodb_logs/screenshot.png new file mode 100644 index 0000000000000..c77c37d5ce05b Binary files /dev/null and b/src/plugins/home/public/assets/mongodb_logs/screenshot.png differ diff --git a/src/plugins/home/public/assets/o365_logs/screenshot.png b/src/plugins/home/public/assets/o365_logs/screenshot.png new file mode 100644 index 0000000000000..a2413e7b909bc Binary files /dev/null and b/src/plugins/home/public/assets/o365_logs/screenshot.png differ diff --git a/src/plugins/home/public/assets/okta_logs/screenshot.png b/src/plugins/home/public/assets/okta_logs/screenshot.png new file mode 100644 index 0000000000000..6a28b4363b05b Binary files /dev/null and b/src/plugins/home/public/assets/okta_logs/screenshot.png differ diff --git a/src/plugins/home/public/assets/panw_logs/screenshot.png b/src/plugins/home/public/assets/panw_logs/screenshot.png new file mode 100644 index 0000000000000..ef9d5f706eca6 Binary files /dev/null and b/src/plugins/home/public/assets/panw_logs/screenshot.png differ diff --git a/src/plugins/home/public/assets/santa_logs/screenshot.png b/src/plugins/home/public/assets/santa_logs/screenshot.png new file mode 100644 index 0000000000000..31abdeb270a35 Binary files /dev/null and b/src/plugins/home/public/assets/santa_logs/screenshot.png differ diff --git a/src/plugins/home/public/index.ts b/src/plugins/home/public/index.ts index 4459d187eead7..e4ca6fb1439e8 100644 --- a/src/plugins/home/public/index.ts +++ b/src/plugins/home/public/index.ts @@ -24,6 +24,7 @@ export { EnvironmentSetup, TutorialSetup, HomePublicPluginSetup, + HomePublicPluginStart, } from './plugin'; export { FeatureCatalogueEntry, diff --git a/src/plugins/home/public/plugin.test.ts b/src/plugins/home/public/plugin.test.ts index 7b56c6ec89b77..f8ff7c95aae08 100644 --- a/src/plugins/home/public/plugin.test.ts +++ b/src/plugins/home/public/plugin.test.ts @@ -52,23 +52,6 @@ describe('HomePublicPlugin', () => { ); }); - test('registers kibana solution to feature catalogue', async () => { - const setup = await new HomePublicPlugin(mockInitializerContext).setup( - coreMock.createSetup() as any, - { - urlForwarding: urlForwardingPluginMock.createSetupContract(), - } - ); - expect(setup).toHaveProperty('featureCatalogue'); - expect(setup.featureCatalogue.registerSolution).toHaveBeenCalledTimes(1); - expect(setup.featureCatalogue.registerSolution).toHaveBeenCalledWith( - expect.objectContaining({ - icon: 'logoKibana', - id: 'kibana', - }) - ); - }); - test('wires up and returns registry', async () => { const setup = await new HomePublicPlugin(mockInitializerContext).setup( coreMock.createSetup() as any, diff --git a/src/plugins/home/public/plugin.ts b/src/plugins/home/public/plugin.ts index b62ceae3d0d37..90f2f939101cb 100644 --- a/src/plugins/home/public/plugin.ts +++ b/src/plugins/home/public/plugin.ts @@ -58,7 +58,12 @@ export interface HomePluginSetupDependencies { export class HomePublicPlugin implements - Plugin { + Plugin< + HomePublicPluginSetup, + HomePublicPluginStart, + HomePluginSetupDependencies, + HomePluginStartDependencies + > { private readonly featuresCatalogueRegistry = new FeatureCatalogueRegistry(); private readonly environmentService = new EnvironmentService(); private readonly tutorialService = new TutorialService(); @@ -128,39 +133,6 @@ export class HomePublicPlugin order: 500, }); - featureCatalogue.registerSolution({ - id: 'kibana', - title: i18n.translate('home.kibana.featureCatalogue.title', { - defaultMessage: 'Kibana', - }), - subtitle: i18n.translate('home.kibana.featureCatalogue.subtitle', { - defaultMessage: 'Visualize & analyze', - }), - descriptions: [ - i18n.translate('home.kibana.featureCatalogueDescription1', { - defaultMessage: 'Analyze data in dashboards.', - }), - i18n.translate('home.kibana.featureCatalogueDescription2', { - defaultMessage: 'Search and find insights.', - }), - i18n.translate('home.kibana.featureCatalogueDescription3', { - defaultMessage: 'Design pixel-perfect reports.', - }), - i18n.translate('home.kibana.featureCatalogueDescription4', { - defaultMessage: 'Plot geographic data.', - }), - i18n.translate('home.kibana.featureCatalogueDescription5', { - defaultMessage: 'Model, predict, and detect.', - }), - i18n.translate('home.kibana.featureCatalogueDescription6', { - defaultMessage: 'Reveal patterns and relationships.', - }), - ], - icon: 'logoKibana', - path: '/app/dashboards', - order: 400, - }); - return { featureCatalogue, environment: { ...this.environmentService.setup() }, @@ -188,6 +160,8 @@ export class HomePublicPlugin } }); } + + return { featureCatalogue: this.featuresCatalogueRegistry }; } } @@ -212,3 +186,6 @@ export interface HomePublicPluginSetup { environment: EnvironmentSetup; } +export interface HomePublicPluginStart { + featureCatalogue: FeatureCatalogueRegistry; +} diff --git a/src/plugins/home/public/services/feature_catalogue/feature_catalogue_registry.mock.ts b/src/plugins/home/public/services/feature_catalogue/feature_catalogue_registry.mock.ts index 23f36cef89ee6..e1a415ba2d571 100644 --- a/src/plugins/home/public/services/feature_catalogue/feature_catalogue_registry.mock.ts +++ b/src/plugins/home/public/services/feature_catalogue/feature_catalogue_registry.mock.ts @@ -36,6 +36,7 @@ const createMock = (): jest.Mocked> => start: jest.fn(), get: jest.fn(() => []), getSolutions: jest.fn(() => []), + removeFeature: jest.fn(), }; service.setup.mockImplementation(createSetupMock); return service; diff --git a/src/plugins/home/public/services/feature_catalogue/feature_catalogue_registry.test.ts b/src/plugins/home/public/services/feature_catalogue/feature_catalogue_registry.test.ts index b9902e0b10fb1..b009041bbf15b 100644 --- a/src/plugins/home/public/services/feature_catalogue/feature_catalogue_registry.test.ts +++ b/src/plugins/home/public/services/feature_catalogue/feature_catalogue_registry.test.ts @@ -38,7 +38,7 @@ const KIBANA_SOLUTION: FeatureCatalogueSolution = { id: 'kibana', title: 'Kibana', subtitle: 'Visualize & analyze', - descriptions: ['Analyze data in dashboards.', 'Search and find insights.'], + appDescriptions: ['Analyze data in dashboards.', 'Search and find insights.'], icon: 'kibanaApp', path: `/app/home`, }; diff --git a/src/plugins/home/public/services/feature_catalogue/feature_catalogue_registry.ts b/src/plugins/home/public/services/feature_catalogue/feature_catalogue_registry.ts index d965042b65cef..845070da0db9f 100644 --- a/src/plugins/home/public/services/feature_catalogue/feature_catalogue_registry.ts +++ b/src/plugins/home/public/services/feature_catalogue/feature_catalogue_registry.ts @@ -35,6 +35,8 @@ export interface FeatureCatalogueEntry { readonly title: string; /** {@link FeatureCatalogueCategory} to display this feature in. */ readonly category: FeatureCatalogueCategory; + /** A tagline of feature displayed to the user. */ + readonly subtitle?: string; /** One-line description of feature displayed to the user. */ readonly description: string; /** EUI `IconType` for icon to be displayed to the user. EUI supports any known EUI icon, SVG URL, or ReactElement. */ @@ -47,6 +49,8 @@ export interface FeatureCatalogueEntry { readonly order?: number; /** Optional function to control visibility of this feature. */ readonly visible?: () => boolean; + /** Unique string identifier of the solution this feature belongs to */ + readonly solutionId?: string; } /** @public */ @@ -57,8 +61,10 @@ export interface FeatureCatalogueSolution { readonly title: string; /** The tagline of the solution displayed to the user. */ readonly subtitle: string; + /** One-line description of the solution displayed to the user. */ + readonly description?: string; /** A list of use cases for this solution displayed to the user. */ - readonly descriptions: string[]; + readonly appDescriptions: string[]; /** EUI `IconType` for icon to be displayed to the user. EUI supports any known EUI icon, SVG URL, or ReactElement. */ readonly icon: IconType; /** URL path to link to this future. Should not include the basePath. */ @@ -99,7 +105,7 @@ export class FeatureCatalogueRegistry { this.capabilities = capabilities; } - public get(): readonly FeatureCatalogueEntry[] { + public get(): FeatureCatalogueEntry[] { if (this.capabilities === null) { throw new Error('Catalogue entries are only available after start phase'); } @@ -112,7 +118,7 @@ export class FeatureCatalogueRegistry { .sort(compareByKey('title')); } - public getSolutions(): readonly FeatureCatalogueSolution[] { + public getSolutions(): FeatureCatalogueSolution[] { if (this.capabilities === null) { throw new Error('Catalogue entries are only available after start phase'); } @@ -121,6 +127,10 @@ export class FeatureCatalogueRegistry { .filter((solution) => capabilities.catalogue[solution.id] !== false) .sort(compareByKey('title')); } + + public removeFeature(appId: string) { + this.features.delete(appId); + } } export type FeatureCatalogueRegistrySetup = ReturnType; diff --git a/src/plugins/home/server/services/sample_data/sample_data_registry.ts b/src/plugins/home/server/services/sample_data/sample_data_registry.ts index 356c886436413..c9e65b292a00d 100644 --- a/src/plugins/home/server/services/sample_data/sample_data_registry.ts +++ b/src/plugins/home/server/services/sample_data/sample_data_registry.ts @@ -52,7 +52,7 @@ export class SampleDataRegistry { } const usageTracker = usage( core.getStartServices().then(([coreStart]) => coreStart.savedObjects), - this.initContext.logger.get('sample_data', 'telemetry') + this.initContext.logger.get('sample_data', 'usage') ); const router = core.http.createRouter(); createListRoute(router, this.sampleDatasets); diff --git a/src/plugins/home/server/services/sample_data/usage/collector.ts b/src/plugins/home/server/services/sample_data/usage/collector.ts index d819d67a8d432..1cece375ce59b 100644 --- a/src/plugins/home/server/services/sample_data/usage/collector.ts +++ b/src/plugins/home/server/services/sample_data/usage/collector.ts @@ -38,12 +38,12 @@ export async function makeSampleDataUsageCollector( fetch: fetchProvider(index), isReady: () => true, schema: { - installed: { type: 'keyword' }, + installed: { type: 'array', items: { type: 'keyword' } }, last_install_date: { type: 'date' }, last_install_set: { type: 'keyword' }, last_uninstall_date: { type: 'date' }, last_uninstall_set: { type: 'keyword' }, - uninstalled: { type: 'keyword' }, + uninstalled: { type: 'array', items: { type: 'keyword' } }, }, }); diff --git a/src/plugins/home/server/tutorials/activemq_logs/index.ts b/src/plugins/home/server/tutorials/activemq_logs/index.ts index c11c070637ae1..b0214f7a6422b 100644 --- a/src/plugins/home/server/tutorials/activemq_logs/index.ts +++ b/src/plugins/home/server/tutorials/activemq_logs/index.ts @@ -53,11 +53,11 @@ export function activemqLogsSpecProvider(context: TutorialContext): TutorialSche artifacts: { dashboards: [ { - id: '26434790-1464-11ea-8fd8-030a13064883', + id: 'ffe86390-145f-11ea-8fd8-030a13064883', linkLabel: i18n.translate('home.tutorials.activemqLogs.artifacts.dashboards.linkLabel', { - defaultMessage: 'ActiveMQ Application Events', + defaultMessage: 'ActiveMQ Audit Events', }), - isOverview: true, + isOverview: false, }, ], exportedFields: { diff --git a/src/plugins/home/server/tutorials/auditd_logs/index.ts b/src/plugins/home/server/tutorials/auditd_logs/index.ts new file mode 100644 index 0000000000000..365a7dcca44fe --- /dev/null +++ b/src/plugins/home/server/tutorials/auditd_logs/index.ts @@ -0,0 +1,74 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { i18n } from '@kbn/i18n'; +import { TutorialsCategory } from '../../services/tutorials'; +import { + onPremInstructions, + cloudInstructions, + onPremCloudInstructions, +} from '../instructions/filebeat_instructions'; +import { + TutorialContext, + TutorialSchema, +} from '../../services/tutorials/lib/tutorials_registry_types'; + +export function auditdLogsSpecProvider(context: TutorialContext): TutorialSchema { + const moduleName = 'auditd'; + const platforms = ['DEB', 'RPM'] as const; + return { + id: 'auditdLogs', + name: i18n.translate('home.tutorials.auditdLogs.nameTitle', { + defaultMessage: 'Auditd logs', + }), + moduleName, + category: TutorialsCategory.SECURITY_SOLUTION, + shortDescription: i18n.translate('home.tutorials.auditdLogs.shortDescription', { + defaultMessage: 'Collect logs from the Linux auditd daemon.', + }), + longDescription: i18n.translate('home.tutorials.auditdLogs.longDescription', { + defaultMessage: + 'The module collects and parses logs from the audit daemon ( `auditd`). \ +[Learn more]({learnMoreLink}).', + values: { + learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-auditd.html', + }, + }), + euiIconType: '/plugins/home/assets/logos/linux.svg', + artifacts: { + dashboards: [ + { + id: 'dfbb49f0-0a0f-11e7-8a62-2d05eaaac5cb-ecs', + linkLabel: i18n.translate('home.tutorials.auditdLogs.artifacts.dashboards.linkLabel', { + defaultMessage: 'Audit Events', + }), + isOverview: true, + }, + ], + exportedFields: { + documentationUrl: '{config.docs.beats.filebeat}/exported-fields-auditd.html', + }, + }, + completionTimeMinutes: 10, + previewImagePath: '/plugins/home/assets/auditd_logs/screenshot.png', + onPrem: onPremInstructions(moduleName, platforms, context), + elasticCloud: cloudInstructions(moduleName, platforms), + onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), + }; +} diff --git a/src/plugins/home/server/tutorials/barracuda_logs/index.ts b/src/plugins/home/server/tutorials/barracuda_logs/index.ts new file mode 100644 index 0000000000000..b5792b7535cc3 --- /dev/null +++ b/src/plugins/home/server/tutorials/barracuda_logs/index.ts @@ -0,0 +1,71 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { i18n } from '@kbn/i18n'; +import { TutorialsCategory } from '../../services/tutorials'; +import { + onPremInstructions, + cloudInstructions, + onPremCloudInstructions, +} from '../instructions/filebeat_instructions'; +import { + TutorialContext, + TutorialSchema, +} from '../../services/tutorials/lib/tutorials_registry_types'; + +export function barracudaLogsSpecProvider(context: TutorialContext): TutorialSchema { + const moduleName = 'barracuda'; + const platforms = ['OSX', 'DEB', 'RPM', 'WINDOWS'] as const; + return { + id: 'barracudaLogs', + name: i18n.translate('home.tutorials.barracudaLogs.nameTitle', { + defaultMessage: 'Barracuda logs', + }), + moduleName, + category: TutorialsCategory.SECURITY_SOLUTION, + shortDescription: i18n.translate('home.tutorials.barracudaLogs.shortDescription', { + defaultMessage: 'Collect Barracuda Web Application Firewall logs over syslog or from a file.', + }), + longDescription: i18n.translate('home.tutorials.barracudaLogs.longDescription', { + defaultMessage: + 'This is a module for receiving Barracuda Web Application Firewall logs over Syslog or a file. \ +[Learn more]({learnMoreLink}).', + values: { + learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-barracuda.html', + }, + }), + euiIconType: '/plugins/home/assets/logos/barracuda.svg', + artifacts: { + dashboards: [], + application: { + path: '/app/security', + label: i18n.translate('home.tutorials.barracudaLogs.artifacts.dashboards.linkLabel', { + defaultMessage: 'Security App', + }), + }, + exportedFields: { + documentationUrl: '{config.docs.beats.filebeat}/exported-fields-barracuda.html', + }, + }, + completionTimeMinutes: 10, + onPrem: onPremInstructions(moduleName, platforms, context), + elasticCloud: cloudInstructions(moduleName, platforms), + onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), + }; +} diff --git a/src/plugins/home/server/tutorials/bluecoat_logs/index.ts b/src/plugins/home/server/tutorials/bluecoat_logs/index.ts new file mode 100644 index 0000000000000..5e55b6b2c6455 --- /dev/null +++ b/src/plugins/home/server/tutorials/bluecoat_logs/index.ts @@ -0,0 +1,71 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { i18n } from '@kbn/i18n'; +import { TutorialsCategory } from '../../services/tutorials'; +import { + onPremInstructions, + cloudInstructions, + onPremCloudInstructions, +} from '../instructions/filebeat_instructions'; +import { + TutorialContext, + TutorialSchema, +} from '../../services/tutorials/lib/tutorials_registry_types'; + +export function bluecoatLogsSpecProvider(context: TutorialContext): TutorialSchema { + const moduleName = 'bluecoat'; + const platforms = ['OSX', 'DEB', 'RPM', 'WINDOWS'] as const; + return { + id: 'bluecoatLogs', + name: i18n.translate('home.tutorials.bluecoatLogs.nameTitle', { + defaultMessage: 'Bluecoat logs', + }), + moduleName, + category: TutorialsCategory.SECURITY_SOLUTION, + shortDescription: i18n.translate('home.tutorials.bluecoatLogs.shortDescription', { + defaultMessage: 'Collect Blue Coat Director logs over syslog or from a file.', + }), + longDescription: i18n.translate('home.tutorials.bluecoatLogs.longDescription', { + defaultMessage: + 'This is a module for receiving Blue Coat Director logs over Syslog or a file. \ +[Learn more]({learnMoreLink}).', + values: { + learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-bluecoat.html', + }, + }), + euiIconType: 'logoLogging', + artifacts: { + dashboards: [], + application: { + path: '/app/security', + label: i18n.translate('home.tutorials.bluecoatLogs.artifacts.dashboards.linkLabel', { + defaultMessage: 'Security App', + }), + }, + exportedFields: { + documentationUrl: '{config.docs.beats.filebeat}/exported-fields-bluecoat.html', + }, + }, + completionTimeMinutes: 10, + onPrem: onPremInstructions(moduleName, platforms, context), + elasticCloud: cloudInstructions(moduleName, platforms), + onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), + }; +} diff --git a/src/plugins/home/server/tutorials/cef_logs/index.ts b/src/plugins/home/server/tutorials/cef_logs/index.ts new file mode 100644 index 0000000000000..6395f0ae76d5e --- /dev/null +++ b/src/plugins/home/server/tutorials/cef_logs/index.ts @@ -0,0 +1,78 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { i18n } from '@kbn/i18n'; +import { TutorialsCategory } from '../../services/tutorials'; +import { + onPremInstructions, + cloudInstructions, + onPremCloudInstructions, +} from '../instructions/filebeat_instructions'; +import { + TutorialContext, + TutorialSchema, +} from '../../services/tutorials/lib/tutorials_registry_types'; + +export function cefLogsSpecProvider(context: TutorialContext): TutorialSchema { + const moduleName = 'cef'; + const platforms = ['OSX', 'DEB', 'RPM', 'WINDOWS'] as const; + return { + id: 'cefLogs', + name: i18n.translate('home.tutorials.cefLogs.nameTitle', { + defaultMessage: 'CEF logs', + }), + moduleName, + category: TutorialsCategory.SECURITY_SOLUTION, + shortDescription: i18n.translate('home.tutorials.cefLogs.shortDescription', { + defaultMessage: 'Collect Common Event Format (CEF) log data over syslog.', + }), + longDescription: i18n.translate('home.tutorials.cefLogs.longDescription', { + defaultMessage: + 'This is a module for receiving Common Event Format (CEF) data over \ + Syslog. When messages are received over the syslog protocol the syslog \ + input will parse the header and set the timestamp value. Then the \ + processor is applied to parse the CEF encoded data. The decoded data \ + is written into a `cef` object field. Lastly any Elastic Common Schema \ + (ECS) fields that can be populated with the CEF data are populated. \ + [Learn more]({learnMoreLink}).', + values: { + learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-cef.html', + }, + }), + euiIconType: 'logoLogging', + artifacts: { + dashboards: [ + { + id: 'dd0bc9af-2e89-4150-9b42-62517ea56b71', + linkLabel: i18n.translate('home.tutorials.cefLogs.artifacts.dashboards.linkLabel', { + defaultMessage: 'CEF Network Overview Dashboard', + }), + isOverview: true, + }, + ], + exportedFields: { + documentationUrl: '{config.docs.beats.filebeat}/exported-fields-cef.html', + }, + }, + completionTimeMinutes: 10, + onPrem: onPremInstructions(moduleName, platforms, context), + elasticCloud: cloudInstructions(moduleName, platforms), + onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), + }; +} diff --git a/src/plugins/home/server/tutorials/checkpoint_logs/index.ts b/src/plugins/home/server/tutorials/checkpoint_logs/index.ts new file mode 100644 index 0000000000000..ed7051f63a32f --- /dev/null +++ b/src/plugins/home/server/tutorials/checkpoint_logs/index.ts @@ -0,0 +1,71 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { i18n } from '@kbn/i18n'; +import { TutorialsCategory } from '../../services/tutorials'; +import { + onPremInstructions, + cloudInstructions, + onPremCloudInstructions, +} from '../instructions/filebeat_instructions'; +import { + TutorialContext, + TutorialSchema, +} from '../../services/tutorials/lib/tutorials_registry_types'; + +export function checkpointLogsSpecProvider(context: TutorialContext): TutorialSchema { + const moduleName = 'checkpoint'; + const platforms = ['OSX', 'DEB', 'RPM', 'WINDOWS'] as const; + return { + id: 'checkpointLogs', + name: i18n.translate('home.tutorials.checkpointLogs.nameTitle', { + defaultMessage: 'Check Point logs', + }), + moduleName, + category: TutorialsCategory.SECURITY_SOLUTION, + shortDescription: i18n.translate('home.tutorials.checkpointLogs.shortDescription', { + defaultMessage: 'Collect Check Point firewall logs.', + }), + longDescription: i18n.translate('home.tutorials.checkpointLogs.longDescription', { + defaultMessage: + 'This is a module for Check Point firewall logs. It supports logs from the Log Exporter in the Syslog format. \ +[Learn more]({learnMoreLink}).', + values: { + learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-checkpoint.html', + }, + }), + euiIconType: '/plugins/home/assets/logos/checkpoint.svg', + artifacts: { + dashboards: [], + application: { + path: '/app/security', + label: i18n.translate('home.tutorials.checkpointLogs.artifacts.dashboards.linkLabel', { + defaultMessage: 'Security App', + }), + }, + exportedFields: { + documentationUrl: '{config.docs.beats.filebeat}/exported-fields-checkpoint.html', + }, + }, + completionTimeMinutes: 10, + onPrem: onPremInstructions(moduleName, platforms, context), + elasticCloud: cloudInstructions(moduleName, platforms), + onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), + }; +} diff --git a/src/plugins/home/server/tutorials/cisco_logs/index.ts b/src/plugins/home/server/tutorials/cisco_logs/index.ts index b771744a069c3..b60a2137d680e 100644 --- a/src/plugins/home/server/tutorials/cisco_logs/index.ts +++ b/src/plugins/home/server/tutorials/cisco_logs/index.ts @@ -35,17 +35,16 @@ export function ciscoLogsSpecProvider(context: TutorialContext): TutorialSchema return { id: 'ciscoLogs', name: i18n.translate('home.tutorials.ciscoLogs.nameTitle', { - defaultMessage: 'Cisco', + defaultMessage: 'Cisco logs', }), moduleName, category: TutorialsCategory.SECURITY_SOLUTION, shortDescription: i18n.translate('home.tutorials.ciscoLogs.shortDescription', { - defaultMessage: 'Collect and parse logs received from Cisco ASA firewalls.', + defaultMessage: 'Collect Cisco network device logs over syslog or from a file.', }), longDescription: i18n.translate('home.tutorials.ciscoLogs.longDescription', { defaultMessage: - 'This is a module for Cisco network device’s logs. Currently \ -supports the "asa" fileset for Cisco ASA firewall logs received over syslog or read from a file. \ + 'This is a module for Cisco network devices logs (ASA, FTD, IOS, Nexus). It includes the following filesets for receiving logs over syslog or read from a file: \ [Learn more]({learnMoreLink}).', values: { learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-cisco.html', @@ -53,13 +52,15 @@ supports the "asa" fileset for Cisco ASA firewall logs received over syslog or r }), euiIconType: '/plugins/home/assets/logos/cisco.svg', artifacts: { - dashboards: [], - application: { - path: '/app/security', - label: i18n.translate('home.tutorials.ciscoLogs.artifacts.dashboards.linkLabel', { - defaultMessage: 'Security App', - }), - }, + dashboards: [ + { + id: 'a555b160-4987-11e9-b8ce-ed898b5ef295', + linkLabel: i18n.translate('home.tutorials.ciscoLogs.artifacts.dashboards.linkLabel', { + defaultMessage: 'ASA Firewall Dashboard', + }), + isOverview: true, + }, + ], exportedFields: { documentationUrl: '{config.docs.beats.filebeat}/exported-fields-cisco.html', }, diff --git a/src/plugins/home/server/tutorials/coredns_logs/index.ts b/src/plugins/home/server/tutorials/coredns_logs/index.ts index 7fc8a2402d216..13467e628c7fb 100644 --- a/src/plugins/home/server/tutorials/coredns_logs/index.ts +++ b/src/plugins/home/server/tutorials/coredns_logs/index.ts @@ -31,7 +31,7 @@ import { export function corednsLogsSpecProvider(context: TutorialContext): TutorialSchema { const moduleName = 'coredns'; - const platforms = ['OSX', 'DEB', 'RPM'] as const; + const platforms = ['OSX', 'DEB', 'RPM', 'WINDOWS'] as const; return { id: 'corednsLogs', name: i18n.translate('home.tutorials.corednsLogs.nameTitle', { @@ -40,12 +40,11 @@ export function corednsLogsSpecProvider(context: TutorialContext): TutorialSchem moduleName, category: TutorialsCategory.SECURITY_SOLUTION, shortDescription: i18n.translate('home.tutorials.corednsLogs.shortDescription', { - defaultMessage: 'Collect the logs created by Coredns.', + defaultMessage: 'Collect CoreDNS logs.', }), longDescription: i18n.translate('home.tutorials.corednsLogs.longDescription', { defaultMessage: - 'The `coredns` Filebeat module collects the logs from \ -[CoreDNS](https://coredns.io/manual/toc/). \ + 'This is a filebeat module for CoreDNS. It supports both standalone CoreDNS deployment and CoreDNS deployment in Kubernetes. \ [Learn more]({learnMoreLink}).', values: { learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-coredns.html', @@ -57,7 +56,7 @@ export function corednsLogsSpecProvider(context: TutorialContext): TutorialSchem { id: '53aa1f70-443e-11e9-8548-ab7fbe04f038', linkLabel: i18n.translate('home.tutorials.corednsLogs.artifacts.dashboards.linkLabel', { - defaultMessage: 'CoreDNS logs dashboard', + defaultMessage: '[Filebeat CoreDNS] Overview', }), isOverview: true, }, @@ -67,7 +66,7 @@ export function corednsLogsSpecProvider(context: TutorialContext): TutorialSchem }, }, completionTimeMinutes: 10, - previewImagePath: '/plugins/home/assets/coredns_logs/screenshot.jpg', + previewImagePath: '/plugins/home/assets/coredns_logs/screenshot.png', onPrem: onPremInstructions(moduleName, platforms, context), elasticCloud: cloudInstructions(moduleName, platforms), onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), diff --git a/src/plugins/home/server/tutorials/crowdstrike_logs/index.ts b/src/plugins/home/server/tutorials/crowdstrike_logs/index.ts new file mode 100644 index 0000000000000..e4dd2bc6bb9c2 --- /dev/null +++ b/src/plugins/home/server/tutorials/crowdstrike_logs/index.ts @@ -0,0 +1,74 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { i18n } from '@kbn/i18n'; +import { TutorialsCategory } from '../../services/tutorials'; +import { + onPremInstructions, + cloudInstructions, + onPremCloudInstructions, +} from '../instructions/filebeat_instructions'; +import { + TutorialContext, + TutorialSchema, +} from '../../services/tutorials/lib/tutorials_registry_types'; + +export function crowdstrikeLogsSpecProvider(context: TutorialContext): TutorialSchema { + const moduleName = 'crowdstrike'; + const platforms = ['OSX', 'DEB', 'RPM', 'WINDOWS'] as const; + return { + id: 'crowdstrikeLogs', + name: i18n.translate('home.tutorials.crowdstrikeLogs.nameTitle', { + defaultMessage: 'CrowdStrike logs', + }), + moduleName, + category: TutorialsCategory.SECURITY_SOLUTION, + shortDescription: i18n.translate('home.tutorials.crowdstrikeLogs.shortDescription', { + defaultMessage: 'Collect CrowdStrike Falcon logs using the Falcon SIEM Connector.', + }), + longDescription: i18n.translate('home.tutorials.crowdstrikeLogs.longDescription', { + defaultMessage: + 'This is the Filebeat module for CrowdStrike Falcon using the Falcon \ + [SIEM Connector](https://www.crowdstrike.com/blog/tech-center/integrate-with-your-siem). \ + This module collects this data, converts it to ECS, and ingests it to view in the SIEM. \ + By default, the Falcon SIEM connector outputs JSON formatted Falcon Streaming API event data. \ +[Learn more]({learnMoreLink}).', + values: { + learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-crowdstrike.html', + }, + }), + euiIconType: '/plugins/home/assets/logos/crowdstrike.svg', + artifacts: { + dashboards: [], + application: { + path: '/app/security', + label: i18n.translate('home.tutorials.crowdstrikeLogs.artifacts.dashboards.linkLabel', { + defaultMessage: 'Security App', + }), + }, + exportedFields: { + documentationUrl: '{config.docs.beats.filebeat}/exported-fields-crowdstrike.html', + }, + }, + completionTimeMinutes: 10, + onPrem: onPremInstructions(moduleName, platforms, context), + elasticCloud: cloudInstructions(moduleName, platforms), + onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), + }; +} diff --git a/src/plugins/home/server/tutorials/cylance_logs/index.ts b/src/plugins/home/server/tutorials/cylance_logs/index.ts new file mode 100644 index 0000000000000..387a56febb83b --- /dev/null +++ b/src/plugins/home/server/tutorials/cylance_logs/index.ts @@ -0,0 +1,71 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { i18n } from '@kbn/i18n'; +import { TutorialsCategory } from '../../services/tutorials'; +import { + onPremInstructions, + cloudInstructions, + onPremCloudInstructions, +} from '../instructions/filebeat_instructions'; +import { + TutorialContext, + TutorialSchema, +} from '../../services/tutorials/lib/tutorials_registry_types'; + +export function cylanceLogsSpecProvider(context: TutorialContext): TutorialSchema { + const moduleName = 'cylance'; + const platforms = ['OSX', 'DEB', 'RPM', 'WINDOWS'] as const; + return { + id: 'cylanceLogs', + name: i18n.translate('home.tutorials.cylanceLogs.nameTitle', { + defaultMessage: 'CylancePROTECT logs', + }), + moduleName, + category: TutorialsCategory.SECURITY_SOLUTION, + shortDescription: i18n.translate('home.tutorials.cylanceLogs.shortDescription', { + defaultMessage: 'Collect CylancePROTECT logs over syslog or from a file.', + }), + longDescription: i18n.translate('home.tutorials.cylanceLogs.longDescription', { + defaultMessage: + 'This is a module for receiving CylancePROTECT logs over Syslog or a file. \ +[Learn more]({learnMoreLink}).', + values: { + learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-cylance.html', + }, + }), + euiIconType: '/plugins/home/assets/logos/cylance.svg', + artifacts: { + dashboards: [], + application: { + path: '/app/security', + label: i18n.translate('home.tutorials.cylanceLogs.artifacts.dashboards.linkLabel', { + defaultMessage: 'Security App', + }), + }, + exportedFields: { + documentationUrl: '{config.docs.beats.filebeat}/exported-fields-cylance.html', + }, + }, + completionTimeMinutes: 10, + onPrem: onPremInstructions(moduleName, platforms, context), + elasticCloud: cloudInstructions(moduleName, platforms), + onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), + }; +} diff --git a/src/plugins/home/server/tutorials/elasticsearch_logs/index.ts b/src/plugins/home/server/tutorials/elasticsearch_logs/index.ts index f6c280d29f67f..b30457ea7848b 100644 --- a/src/plugins/home/server/tutorials/elasticsearch_logs/index.ts +++ b/src/plugins/home/server/tutorials/elasticsearch_logs/index.ts @@ -65,6 +65,7 @@ export function elasticsearchLogsSpecProvider(context: TutorialContext): Tutoria }, }, completionTimeMinutes: 10, + previewImagePath: '/plugins/home/assets/elasticsearch_logs/screenshot.png', onPrem: onPremInstructions(moduleName, platforms, context), elasticCloud: cloudInstructions(moduleName, platforms), onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), diff --git a/src/plugins/home/server/tutorials/envoyproxy_logs/index.ts b/src/plugins/home/server/tutorials/envoyproxy_logs/index.ts index 0cf032e6b90c1..94b5af143447f 100644 --- a/src/plugins/home/server/tutorials/envoyproxy_logs/index.ts +++ b/src/plugins/home/server/tutorials/envoyproxy_logs/index.ts @@ -35,17 +35,16 @@ export function envoyproxyLogsSpecProvider(context: TutorialContext): TutorialSc return { id: 'envoyproxyLogs', name: i18n.translate('home.tutorials.envoyproxyLogs.nameTitle', { - defaultMessage: 'Envoyproxy', + defaultMessage: 'Envoy Proxy logs', }), moduleName, category: TutorialsCategory.SECURITY_SOLUTION, shortDescription: i18n.translate('home.tutorials.envoyproxyLogs.shortDescription', { - defaultMessage: 'Collect and parse logs received from the Envoy proxy.', + defaultMessage: 'Collect Envoy Proxy logs.', }), longDescription: i18n.translate('home.tutorials.envoyproxyLogs.longDescription', { defaultMessage: - 'This is a filebeat module for [Envoy proxy access log](https://www.envoyproxy.io/docs/envoy/v1.10.0/configuration/access_log). \ -It supports both standalone deployment and Envoy proxy deployment in Kubernetes. \ + 'This is a Filebeat module for Envoy proxy access log ( https://www.envoyproxy.io/docs/envoy/v1.10.0/configuration/access_log). It supports both standalone deployment and Envoy proxy deployment in Kubernetes. \ [Learn more]({learnMoreLink}).', values: { learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-envoyproxy.html', @@ -53,13 +52,18 @@ It supports both standalone deployment and Envoy proxy deployment in Kubernetes. }), euiIconType: '/plugins/home/assets/logos/envoyproxy.svg', artifacts: { - dashboards: [], - application: { - path: '/app/security', - label: i18n.translate('home.tutorials.envoyproxyLogs.artifacts.dashboards.linkLabel', { - defaultMessage: 'Security App', - }), - }, + dashboards: [ + { + id: '0c610510-5cbd-11e9-8477-077ec9664dbd', + linkLabel: i18n.translate( + 'home.tutorials.envoyproxyLogs.artifacts.dashboards.linkLabel', + { + defaultMessage: 'Envoy Proxy Overview', + } + ), + isOverview: true, + }, + ], exportedFields: { documentationUrl: '{config.docs.beats.filebeat}/exported-fields-envoyproxy.html', }, diff --git a/src/plugins/home/server/tutorials/f5_logs/index.ts b/src/plugins/home/server/tutorials/f5_logs/index.ts new file mode 100644 index 0000000000000..4b4ae367ab46e --- /dev/null +++ b/src/plugins/home/server/tutorials/f5_logs/index.ts @@ -0,0 +1,72 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { i18n } from '@kbn/i18n'; +import { TutorialsCategory } from '../../services/tutorials'; +import { + onPremInstructions, + cloudInstructions, + onPremCloudInstructions, +} from '../instructions/filebeat_instructions'; +import { + TutorialContext, + TutorialSchema, +} from '../../services/tutorials/lib/tutorials_registry_types'; + +export function f5LogsSpecProvider(context: TutorialContext): TutorialSchema { + const moduleName = 'f5'; + const platforms = ['OSX', 'DEB', 'RPM', 'WINDOWS'] as const; + return { + id: 'f5Logs', + name: i18n.translate('home.tutorials.f5Logs.nameTitle', { + defaultMessage: 'F5 logs', + }), + moduleName, + category: TutorialsCategory.SECURITY_SOLUTION, + shortDescription: i18n.translate('home.tutorials.f5Logs.shortDescription', { + defaultMessage: 'Collect F5 Big-IP Access Policy Manager logs over syslog or from a file.', + }), + longDescription: i18n.translate('home.tutorials.f5Logs.longDescription', { + defaultMessage: + 'This is a module for receiving Big-IP Access Policy Manager logs over Syslog or a file. \ +[Learn more]({learnMoreLink}).', + values: { + learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-f5.html', + }, + }), + euiIconType: '/plugins/home/assets/logos/f5.svg', + artifacts: { + dashboards: [], + application: { + path: '/app/security', + label: i18n.translate('home.tutorials.f5Logs.artifacts.dashboards.linkLabel', { + defaultMessage: 'Security App', + }), + }, + exportedFields: { + documentationUrl: '{config.docs.beats.filebeat}/exported-fields-f5.html', + }, + }, + completionTimeMinutes: 10, + previewImagePath: '/plugins/home/assets/f5_logs/screenshot.png', + onPrem: onPremInstructions(moduleName, platforms, context), + elasticCloud: cloudInstructions(moduleName, platforms), + onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), + }; +} diff --git a/src/plugins/home/server/tutorials/fortinet_logs/index.ts b/src/plugins/home/server/tutorials/fortinet_logs/index.ts new file mode 100644 index 0000000000000..d60d383016295 --- /dev/null +++ b/src/plugins/home/server/tutorials/fortinet_logs/index.ts @@ -0,0 +1,71 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { i18n } from '@kbn/i18n'; +import { TutorialsCategory } from '../../services/tutorials'; +import { + onPremInstructions, + cloudInstructions, + onPremCloudInstructions, +} from '../instructions/filebeat_instructions'; +import { + TutorialContext, + TutorialSchema, +} from '../../services/tutorials/lib/tutorials_registry_types'; + +export function fortinetLogsSpecProvider(context: TutorialContext): TutorialSchema { + const moduleName = 'fortinet'; + const platforms = ['OSX', 'DEB', 'RPM', 'WINDOWS'] as const; + return { + id: 'fortinetLogs', + name: i18n.translate('home.tutorials.fortinetLogs.nameTitle', { + defaultMessage: 'Fortinet logs', + }), + moduleName, + category: TutorialsCategory.SECURITY_SOLUTION, + shortDescription: i18n.translate('home.tutorials.fortinetLogs.shortDescription', { + defaultMessage: 'Collect Fortinet FortiOS logs over syslog.', + }), + longDescription: i18n.translate('home.tutorials.fortinetLogs.longDescription', { + defaultMessage: + 'This is a module for Fortinet FortiOS logs sent in the syslog format. \ +[Learn more]({learnMoreLink}).', + values: { + learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-fortinet.html', + }, + }), + euiIconType: '/plugins/home/assets/logos/fortinet.svg', + artifacts: { + dashboards: [], + application: { + path: '/app/security', + label: i18n.translate('home.tutorials.fortinetLogs.artifacts.dashboards.linkLabel', { + defaultMessage: 'Security App', + }), + }, + exportedFields: { + documentationUrl: '{config.docs.beats.filebeat}/exported-fields-fortinet.html', + }, + }, + completionTimeMinutes: 10, + onPrem: onPremInstructions(moduleName, platforms, context), + elasticCloud: cloudInstructions(moduleName, platforms), + onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), + }; +} diff --git a/src/plugins/home/server/tutorials/googlecloud_logs/index.ts b/src/plugins/home/server/tutorials/googlecloud_logs/index.ts new file mode 100644 index 0000000000000..482ad38ddfbcd --- /dev/null +++ b/src/plugins/home/server/tutorials/googlecloud_logs/index.ts @@ -0,0 +1,79 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { i18n } from '@kbn/i18n'; +import { TutorialsCategory } from '../../services/tutorials'; +import { + onPremInstructions, + cloudInstructions, + onPremCloudInstructions, +} from '../instructions/filebeat_instructions'; +import { + TutorialContext, + TutorialSchema, +} from '../../services/tutorials/lib/tutorials_registry_types'; + +export function googlecloudLogsSpecProvider(context: TutorialContext): TutorialSchema { + const moduleName = 'googlecloud'; + const platforms = ['OSX', 'DEB', 'RPM', 'WINDOWS'] as const; + return { + id: 'googlecloudLogs', + name: i18n.translate('home.tutorials.googlecloudLogs.nameTitle', { + defaultMessage: 'Google Cloud logs', + }), + moduleName, + category: TutorialsCategory.SECURITY_SOLUTION, + shortDescription: i18n.translate('home.tutorials.googlecloudLogs.shortDescription', { + defaultMessage: 'Collect Google Cloud audit, firewall, and VPC flow logs.', + }), + longDescription: i18n.translate('home.tutorials.googlecloudLogs.longDescription', { + defaultMessage: + 'This is a module for Google Cloud logs. It supports reading audit, VPC flow, \ + and firewall logs that have been exported from Stackdriver to a Google Pub/Sub \ + topic sink. \ +[Learn more]({learnMoreLink}).', + values: { + learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-googlecloud.html', + }, + }), + euiIconType: 'logoGoogleG', + artifacts: { + dashboards: [ + { + id: '6576c480-73a2-11ea-a345-f985c61fe654', + linkLabel: i18n.translate( + 'home.tutorials.googlecloudLogs.artifacts.dashboards.linkLabel', + { + defaultMessage: 'Audit Logs Dashbaord', + } + ), + isOverview: true, + }, + ], + exportedFields: { + documentationUrl: '{config.docs.beats.filebeat}/exported-fields-googlecloud.html', + }, + }, + completionTimeMinutes: 10, + previewImagePath: '/plugins/home/assets/googlecloud_logs/screenshot.png', + onPrem: onPremInstructions(moduleName, platforms, context), + elasticCloud: cloudInstructions(moduleName, platforms), + onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), + }; +} diff --git a/src/plugins/home/server/tutorials/gsuite_logs/index.ts b/src/plugins/home/server/tutorials/gsuite_logs/index.ts new file mode 100644 index 0000000000000..0f7c0d7077d39 --- /dev/null +++ b/src/plugins/home/server/tutorials/gsuite_logs/index.ts @@ -0,0 +1,71 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { i18n } from '@kbn/i18n'; +import { TutorialsCategory } from '../../services/tutorials'; +import { + onPremInstructions, + cloudInstructions, + onPremCloudInstructions, +} from '../instructions/filebeat_instructions'; +import { + TutorialContext, + TutorialSchema, +} from '../../services/tutorials/lib/tutorials_registry_types'; + +export function gsuiteLogsSpecProvider(context: TutorialContext): TutorialSchema { + const moduleName = 'gsuite'; + const platforms = ['OSX', 'DEB', 'RPM', 'WINDOWS'] as const; + return { + id: 'gsuiteLogs', + name: i18n.translate('home.tutorials.gsuiteLogs.nameTitle', { + defaultMessage: 'GSuite logs', + }), + moduleName, + category: TutorialsCategory.SECURITY_SOLUTION, + shortDescription: i18n.translate('home.tutorials.gsuiteLogs.shortDescription', { + defaultMessage: 'Collect GSuite activity reports.', + }), + longDescription: i18n.translate('home.tutorials.gsuiteLogs.longDescription', { + defaultMessage: + 'This is a module for ingesting data from the different GSuite audit reports APIs. \ +[Learn more]({learnMoreLink}).', + values: { + learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-gsuite.html', + }, + }), + euiIconType: 'logoGoogleG', + artifacts: { + dashboards: [], + application: { + path: '/app/security', + label: i18n.translate('home.tutorials.gsuiteLogs.artifacts.dashboards.linkLabel', { + defaultMessage: 'Security App', + }), + }, + exportedFields: { + documentationUrl: '{config.docs.beats.filebeat}/exported-fields-gsuite.html', + }, + }, + completionTimeMinutes: 10, + onPrem: onPremInstructions(moduleName, platforms, context), + elasticCloud: cloudInstructions(moduleName, platforms), + onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), + }; +} diff --git a/src/plugins/home/server/tutorials/haproxy_logs/index.ts b/src/plugins/home/server/tutorials/haproxy_logs/index.ts new file mode 100644 index 0000000000000..82ef405ffe839 --- /dev/null +++ b/src/plugins/home/server/tutorials/haproxy_logs/index.ts @@ -0,0 +1,74 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { i18n } from '@kbn/i18n'; +import { TutorialsCategory } from '../../services/tutorials'; +import { + onPremInstructions, + cloudInstructions, + onPremCloudInstructions, +} from '../instructions/filebeat_instructions'; +import { + TutorialContext, + TutorialSchema, +} from '../../services/tutorials/lib/tutorials_registry_types'; + +export function haproxyLogsSpecProvider(context: TutorialContext): TutorialSchema { + const moduleName = 'haproxy'; + const platforms = ['OSX', 'DEB', 'RPM', 'WINDOWS'] as const; + return { + id: 'haproxyLogs', + name: i18n.translate('home.tutorials.haproxyLogs.nameTitle', { + defaultMessage: 'HAProxy logs', + }), + moduleName, + category: TutorialsCategory.SECURITY_SOLUTION, + shortDescription: i18n.translate('home.tutorials.haproxyLogs.shortDescription', { + defaultMessage: 'Collect HAProxy logs.', + }), + longDescription: i18n.translate('home.tutorials.haproxyLogs.longDescription', { + defaultMessage: + 'The module collects and parses logs from a ( `haproxy`) process. \ +[Learn more]({learnMoreLink}).', + values: { + learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-haproxy.html', + }, + }), + euiIconType: 'logoHAproxy', + artifacts: { + dashboards: [ + { + id: '3560d580-aa34-11e8-9c06-877f0445e3e0-ecs', + linkLabel: i18n.translate('home.tutorials.haproxyLogs.artifacts.dashboards.linkLabel', { + defaultMessage: 'HAProxy Overview', + }), + isOverview: true, + }, + ], + exportedFields: { + documentationUrl: '{config.docs.beats.filebeat}/exported-fields-haproxy.html', + }, + }, + completionTimeMinutes: 10, + previewImagePath: '/plugins/home/assets/haproxy_logs/screenshot.png', + onPrem: onPremInstructions(moduleName, platforms, context), + elasticCloud: cloudInstructions(moduleName, platforms), + onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), + }; +} diff --git a/src/plugins/home/server/tutorials/icinga_logs/index.ts b/src/plugins/home/server/tutorials/icinga_logs/index.ts new file mode 100644 index 0000000000000..de494e5a15046 --- /dev/null +++ b/src/plugins/home/server/tutorials/icinga_logs/index.ts @@ -0,0 +1,74 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { i18n } from '@kbn/i18n'; +import { TutorialsCategory } from '../../services/tutorials'; +import { + onPremInstructions, + cloudInstructions, + onPremCloudInstructions, +} from '../instructions/filebeat_instructions'; +import { + TutorialContext, + TutorialSchema, +} from '../../services/tutorials/lib/tutorials_registry_types'; + +export function icingaLogsSpecProvider(context: TutorialContext): TutorialSchema { + const moduleName = 'icinga'; + const platforms = ['OSX', 'DEB', 'RPM', 'WINDOWS'] as const; + return { + id: 'icingaLogs', + name: i18n.translate('home.tutorials.icingaLogs.nameTitle', { + defaultMessage: 'Icinga logs', + }), + moduleName, + category: TutorialsCategory.SECURITY_SOLUTION, + shortDescription: i18n.translate('home.tutorials.icingaLogs.shortDescription', { + defaultMessage: 'Collect Icinga main, debug, and startup logs.', + }), + longDescription: i18n.translate('home.tutorials.icingaLogs.longDescription', { + defaultMessage: + 'The module parses the main, debug, and startup logs of [Icinga](https://www.icinga.com/products/icinga-2/). \ +[Learn more]({learnMoreLink}).', + values: { + learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-icinga.html', + }, + }), + euiIconType: '/plugins/home/assets/logos/icinga.svg', + artifacts: { + dashboards: [ + { + id: 'f693d260-2417-11e7-a83b-d5f4cebac9ff-ecs', + linkLabel: i18n.translate('home.tutorials.icingaLogs.artifacts.dashboards.linkLabel', { + defaultMessage: 'Icinga Main Log', + }), + isOverview: true, + }, + ], + exportedFields: { + documentationUrl: '{config.docs.beats.filebeat}/exported-fields-icinga.html', + }, + }, + completionTimeMinutes: 10, + previewImagePath: '/plugins/home/assets/icinga_logs/screenshot.png', + onPrem: onPremInstructions(moduleName, platforms, context), + elasticCloud: cloudInstructions(moduleName, platforms), + onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), + }; +} diff --git a/src/plugins/home/server/tutorials/imperva_logs/index.ts b/src/plugins/home/server/tutorials/imperva_logs/index.ts new file mode 100644 index 0000000000000..d723a4c2f49ef --- /dev/null +++ b/src/plugins/home/server/tutorials/imperva_logs/index.ts @@ -0,0 +1,71 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { i18n } from '@kbn/i18n'; +import { TutorialsCategory } from '../../services/tutorials'; +import { + onPremInstructions, + cloudInstructions, + onPremCloudInstructions, +} from '../instructions/filebeat_instructions'; +import { + TutorialContext, + TutorialSchema, +} from '../../services/tutorials/lib/tutorials_registry_types'; + +export function impervaLogsSpecProvider(context: TutorialContext): TutorialSchema { + const moduleName = 'imperva'; + const platforms = ['OSX', 'DEB', 'RPM', 'WINDOWS'] as const; + return { + id: 'impervaLogs', + name: i18n.translate('home.tutorials.impervaLogs.nameTitle', { + defaultMessage: 'Imperva logs', + }), + moduleName, + category: TutorialsCategory.SECURITY_SOLUTION, + shortDescription: i18n.translate('home.tutorials.impervaLogs.shortDescription', { + defaultMessage: 'Collect Imperva SecureSphere logs over syslog or from a file.', + }), + longDescription: i18n.translate('home.tutorials.impervaLogs.longDescription', { + defaultMessage: + 'This is a module for receiving Imperva SecureSphere logs over Syslog or a file. \ +[Learn more]({learnMoreLink}).', + values: { + learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-imperva.html', + }, + }), + euiIconType: 'logoLogging', + artifacts: { + dashboards: [], + application: { + path: '/app/security', + label: i18n.translate('home.tutorials.impervaLogs.artifacts.dashboards.linkLabel', { + defaultMessage: 'Security App', + }), + }, + exportedFields: { + documentationUrl: '{config.docs.beats.filebeat}/exported-fields-imperva.html', + }, + }, + completionTimeMinutes: 10, + onPrem: onPremInstructions(moduleName, platforms, context), + elasticCloud: cloudInstructions(moduleName, platforms), + onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), + }; +} diff --git a/src/plugins/home/server/tutorials/infoblox_logs/index.ts b/src/plugins/home/server/tutorials/infoblox_logs/index.ts new file mode 100644 index 0000000000000..811f3110e7871 --- /dev/null +++ b/src/plugins/home/server/tutorials/infoblox_logs/index.ts @@ -0,0 +1,71 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { i18n } from '@kbn/i18n'; +import { TutorialsCategory } from '../../services/tutorials'; +import { + onPremInstructions, + cloudInstructions, + onPremCloudInstructions, +} from '../instructions/filebeat_instructions'; +import { + TutorialContext, + TutorialSchema, +} from '../../services/tutorials/lib/tutorials_registry_types'; + +export function infobloxLogsSpecProvider(context: TutorialContext): TutorialSchema { + const moduleName = 'infoblox'; + const platforms = ['OSX', 'DEB', 'RPM', 'WINDOWS'] as const; + return { + id: 'infobloxLogs', + name: i18n.translate('home.tutorials.infobloxLogs.nameTitle', { + defaultMessage: 'Infoblox logs', + }), + moduleName, + category: TutorialsCategory.SECURITY_SOLUTION, + shortDescription: i18n.translate('home.tutorials.infobloxLogs.shortDescription', { + defaultMessage: 'Collect Infoblox NIOS logs over syslog or from a file.', + }), + longDescription: i18n.translate('home.tutorials.infobloxLogs.longDescription', { + defaultMessage: + 'This is a module for receiving Infoblox NIOS logs over Syslog or a file. \ +[Learn more]({learnMoreLink}).', + values: { + learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-infoblox.html', + }, + }), + euiIconType: '/plugins/home/assets/logos/infoblox.svg', + artifacts: { + dashboards: [], + application: { + path: '/app/security', + label: i18n.translate('home.tutorials.infobloxLogs.artifacts.dashboards.linkLabel', { + defaultMessage: 'Security App', + }), + }, + exportedFields: { + documentationUrl: '{config.docs.beats.filebeat}/exported-fields-infoblox.html', + }, + }, + completionTimeMinutes: 10, + onPrem: onPremInstructions(moduleName, platforms, context), + elasticCloud: cloudInstructions(moduleName, platforms), + onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), + }; +} diff --git a/src/plugins/home/server/tutorials/iptables_logs/index.ts b/src/plugins/home/server/tutorials/iptables_logs/index.ts index b3be133767447..dc44ae6107b1e 100644 --- a/src/plugins/home/server/tutorials/iptables_logs/index.ts +++ b/src/plugins/home/server/tutorials/iptables_logs/index.ts @@ -31,37 +31,39 @@ import { export function iptablesLogsSpecProvider(context: TutorialContext): TutorialSchema { const moduleName = 'iptables'; - const platforms = ['DEB', 'RPM'] as const; + const platforms = ['OSX', 'DEB', 'RPM', 'WINDOWS'] as const; return { id: 'iptablesLogs', name: i18n.translate('home.tutorials.iptablesLogs.nameTitle', { - defaultMessage: 'Iptables / Ubiquiti', + defaultMessage: 'Iptables logs', }), moduleName, category: TutorialsCategory.SECURITY_SOLUTION, shortDescription: i18n.translate('home.tutorials.iptablesLogs.shortDescription', { - defaultMessage: 'Collect and parse iptables and ip6tables logs or from Ubiqiti firewalls.', + defaultMessage: 'Collect iptables and ip6tables logs.', }), longDescription: i18n.translate('home.tutorials.iptablesLogs.longDescription', { defaultMessage: - 'This is a module for iptables and ip6tables logs. It parses logs \ -received over the network via syslog or from a file. Also, it understands the \ -prefix added by some Ubiquiti firewalls, which includes the rule set name, rule \ -number and the action performed on the traffic (allow/deny).. \ -[Learn more]({learnMoreLink}).', + 'This is a module for iptables and ip6tables logs. It parses logs received \ + over the network via syslog or from a file. Also, it understands the prefix \ + added by some Ubiquiti firewalls, which includes the rule set name, rule \ + number and the action performed on the traffic (allow/deny). \ + [Learn more]({learnMoreLink}).', values: { learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-iptables.html', }, }), - euiIconType: '/plugins/home/assets/logos/ubiquiti.svg', + euiIconType: '/plugins/home/assets/logos/linux.svg', artifacts: { - dashboards: [], - application: { - path: '/app/security', - label: i18n.translate('home.tutorials.iptablesLogs.artifacts.dashboards.linkLabel', { - defaultMessage: 'Security App', - }), - }, + dashboards: [ + { + id: 'ceefb9e0-1f51-11e9-93ed-f7e068f4aebb-ecs', + linkLabel: i18n.translate('home.tutorials.iptablesLogs.artifacts.dashboards.linkLabel', { + defaultMessage: 'Iptables Overview', + }), + isOverview: true, + }, + ], exportedFields: { documentationUrl: '{config.docs.beats.filebeat}/exported-fields-iptables.html', }, diff --git a/src/plugins/home/server/tutorials/juniper_logs/index.ts b/src/plugins/home/server/tutorials/juniper_logs/index.ts new file mode 100644 index 0000000000000..45688baa5bcdf --- /dev/null +++ b/src/plugins/home/server/tutorials/juniper_logs/index.ts @@ -0,0 +1,71 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { i18n } from '@kbn/i18n'; +import { TutorialsCategory } from '../../services/tutorials'; +import { + onPremInstructions, + cloudInstructions, + onPremCloudInstructions, +} from '../instructions/filebeat_instructions'; +import { + TutorialContext, + TutorialSchema, +} from '../../services/tutorials/lib/tutorials_registry_types'; + +export function juniperLogsSpecProvider(context: TutorialContext): TutorialSchema { + const moduleName = 'juniper'; + const platforms = ['OSX', 'DEB', 'RPM', 'WINDOWS'] as const; + return { + id: 'juniperLogs', + name: i18n.translate('home.tutorials.juniperLogs.nameTitle', { + defaultMessage: 'Juniper Logs', + }), + moduleName, + category: TutorialsCategory.SECURITY_SOLUTION, + shortDescription: i18n.translate('home.tutorials.juniperLogs.shortDescription', { + defaultMessage: 'Collect Juniper JUNOS logs over syslog or from a file.', + }), + longDescription: i18n.translate('home.tutorials.juniperLogs.longDescription', { + defaultMessage: + 'This is a module for receiving Juniper JUNOS logs over Syslog or a file. \ +[Learn more]({learnMoreLink}).', + values: { + learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-juniper.html', + }, + }), + euiIconType: '/plugins/home/assets/logos/juniper.svg', + artifacts: { + dashboards: [], + application: { + path: '/app/security', + label: i18n.translate('home.tutorials.juniperLogs.artifacts.dashboards.linkLabel', { + defaultMessage: 'Security App', + }), + }, + exportedFields: { + documentationUrl: '{config.docs.beats.filebeat}/exported-fields-juniper.html', + }, + }, + completionTimeMinutes: 10, + onPrem: onPremInstructions(moduleName, platforms, context), + elasticCloud: cloudInstructions(moduleName, platforms), + onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), + }; +} diff --git a/src/plugins/home/server/tutorials/kibana_logs/index.ts b/src/plugins/home/server/tutorials/kibana_logs/index.ts new file mode 100644 index 0000000000000..88286a230f771 --- /dev/null +++ b/src/plugins/home/server/tutorials/kibana_logs/index.ts @@ -0,0 +1,70 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { i18n } from '@kbn/i18n'; +import { TutorialsCategory } from '../../services/tutorials'; +import { + onPremInstructions, + cloudInstructions, + onPremCloudInstructions, +} from '../instructions/filebeat_instructions'; +import { + TutorialContext, + TutorialSchema, +} from '../../services/tutorials/lib/tutorials_registry_types'; + +export function kibanaLogsSpecProvider(context: TutorialContext): TutorialSchema { + const moduleName = 'kibana'; + const platforms = ['OSX', 'DEB', 'RPM', 'WINDOWS'] as const; + return { + id: 'kibanaLogs', + name: i18n.translate('home.tutorials.kibanaLogs.nameTitle', { + defaultMessage: 'Kibana Logs', + }), + moduleName, + category: TutorialsCategory.LOGGING, + shortDescription: i18n.translate('home.tutorials.kibanaLogs.shortDescription', { + defaultMessage: 'Collect Kibana logs.', + }), + longDescription: i18n.translate('home.tutorials.kibanaLogs.longDescription', { + defaultMessage: 'This is the Kibana module. \ +[Learn more]({learnMoreLink}).', + values: { + learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-kibana.html', + }, + }), + euiIconType: 'logoKibana', + artifacts: { + dashboards: [], + application: { + label: i18n.translate('home.tutorials.kibanaLogs.artifacts.application.label', { + defaultMessage: 'Discover', + }), + path: '/app/discover#/', + }, + exportedFields: { + documentationUrl: '{config.docs.beats.filebeat}/exported-fields-kibana.html', + }, + }, + completionTimeMinutes: 10, + onPrem: onPremInstructions(moduleName, platforms, context), + elasticCloud: cloudInstructions(moduleName, platforms), + onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), + }; +} diff --git a/src/plugins/home/server/tutorials/logstash_logs/index.ts b/src/plugins/home/server/tutorials/logstash_logs/index.ts index 32982cd1055a4..6998aaf9001e6 100644 --- a/src/plugins/home/server/tutorials/logstash_logs/index.ts +++ b/src/plugins/home/server/tutorials/logstash_logs/index.ts @@ -38,13 +38,13 @@ export function logstashLogsSpecProvider(context: TutorialContext): TutorialSche defaultMessage: 'Logstash logs', }), moduleName, - category: TutorialsCategory.LOGGING, + category: TutorialsCategory.SECURITY_SOLUTION, shortDescription: i18n.translate('home.tutorials.logstashLogs.shortDescription', { - defaultMessage: 'Collect and parse debug and slow logs created by Logstash itself.', + defaultMessage: 'Collect Logstash main and slow logs.', }), longDescription: i18n.translate('home.tutorials.logstashLogs.longDescription', { defaultMessage: - 'The `logstash` Filebeat module parses debug and slow logs created by Logstash itself. \ + 'The modules parse Logstash regular logs and the slow log, it will support the plain text format and the JSON format. \ [Learn more]({learnMoreLink}).', values: { learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-logstash.html', @@ -56,7 +56,7 @@ export function logstashLogsSpecProvider(context: TutorialContext): TutorialSche { id: 'Filebeat-Logstash-Log-Dashboard-ecs', linkLabel: i18n.translate('home.tutorials.logstashLogs.artifacts.dashboards.linkLabel', { - defaultMessage: 'Logstash logs dashboard', + defaultMessage: 'Logstash Logs', }), isOverview: true, }, @@ -66,7 +66,6 @@ export function logstashLogsSpecProvider(context: TutorialContext): TutorialSche }, }, completionTimeMinutes: 10, - previewImagePath: '/plugins/home/assets/logstash_logs/screenshot.png', onPrem: onPremInstructions(moduleName, platforms, context), elasticCloud: cloudInstructions(moduleName, platforms), onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), diff --git a/src/plugins/home/server/tutorials/microsoft_logs/index.ts b/src/plugins/home/server/tutorials/microsoft_logs/index.ts new file mode 100644 index 0000000000000..28739a5817ae7 --- /dev/null +++ b/src/plugins/home/server/tutorials/microsoft_logs/index.ts @@ -0,0 +1,74 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { i18n } from '@kbn/i18n'; +import { TutorialsCategory } from '../../services/tutorials'; +import { + onPremInstructions, + cloudInstructions, + onPremCloudInstructions, +} from '../instructions/filebeat_instructions'; +import { + TutorialContext, + TutorialSchema, +} from '../../services/tutorials/lib/tutorials_registry_types'; + +export function microsoftLogsSpecProvider(context: TutorialContext): TutorialSchema { + const moduleName = 'microsoft'; + const platforms = ['OSX', 'DEB', 'RPM', 'WINDOWS'] as const; + return { + id: 'microsoftLogs', + name: i18n.translate('home.tutorials.microsoftLogs.nameTitle', { + defaultMessage: 'Microsoft Defender ATP logs', + }), + moduleName, + category: TutorialsCategory.SECURITY_SOLUTION, + shortDescription: i18n.translate('home.tutorials.microsoftLogs.shortDescription', { + defaultMessage: 'Collect Microsoft Defender ATP alerts.', + }), + longDescription: i18n.translate('home.tutorials.microsoftLogs.longDescription', { + defaultMessage: + 'Collect Microsoft Defender ATP alerts for use with Elastic Security. \ +[Learn more]({learnMoreLink}).', + values: { + learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-microsoft.html', + }, + }), + euiIconType: '/plugins/home/assets/logos/microsoft.svg', + artifacts: { + dashboards: [ + { + id: '65402c30-ca6a-11ea-9d4d-9737a63aaa55', + linkLabel: i18n.translate('home.tutorials.microsoftLogs.artifacts.dashboards.linkLabel', { + defaultMessage: 'Microsoft ATP Overview', + }), + isOverview: true, + }, + ], + exportedFields: { + documentationUrl: '{config.docs.beats.filebeat}/exported-fields-microsoft.html', + }, + }, + completionTimeMinutes: 10, + previewImagePath: '/plugins/home/assets/microsoft_logs/screenshot.png', + onPrem: onPremInstructions(moduleName, platforms, context), + elasticCloud: cloudInstructions(moduleName, platforms), + onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), + }; +} diff --git a/src/plugins/home/server/tutorials/misp_logs/index.ts b/src/plugins/home/server/tutorials/misp_logs/index.ts new file mode 100644 index 0000000000000..050c22fb39523 --- /dev/null +++ b/src/plugins/home/server/tutorials/misp_logs/index.ts @@ -0,0 +1,74 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { i18n } from '@kbn/i18n'; +import { TutorialsCategory } from '../../services/tutorials'; +import { + onPremInstructions, + cloudInstructions, + onPremCloudInstructions, +} from '../instructions/filebeat_instructions'; +import { + TutorialContext, + TutorialSchema, +} from '../../services/tutorials/lib/tutorials_registry_types'; + +export function mispLogsSpecProvider(context: TutorialContext): TutorialSchema { + const moduleName = 'misp'; + const platforms = ['OSX', 'DEB', 'RPM', 'WINDOWS'] as const; + return { + id: 'mispLogs', + name: i18n.translate('home.tutorials.mispLogs.nameTitle', { + defaultMessage: 'MISP threat intel logs', + }), + moduleName, + category: TutorialsCategory.SECURITY_SOLUTION, + shortDescription: i18n.translate('home.tutorials.mispLogs.shortDescription', { + defaultMessage: 'Collect MISP threat intelligence data with Filebeat.', + }), + longDescription: i18n.translate('home.tutorials.mispLogs.longDescription', { + defaultMessage: + 'This is a filebeat module for reading threat intel information from the MISP platform ( https://www.circl.lu/doc/misp/). It uses the httpjson input to access the MISP REST API interface. \ +[Learn more]({learnMoreLink}).', + values: { + learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-misp.html', + }, + }), + euiIconType: '/plugins/home/assets/logos/misp.svg', + artifacts: { + dashboards: [ + { + id: 'c6cac9e0-f105-11e9-9a88-690b10c8ee99', + linkLabel: i18n.translate('home.tutorials.mispLogs.artifacts.dashboards.linkLabel', { + defaultMessage: 'MISP Overview', + }), + isOverview: true, + }, + ], + exportedFields: { + documentationUrl: '{config.docs.beats.filebeat}/exported-fields-misp.html', + }, + }, + completionTimeMinutes: 10, + previewImagePath: '/plugins/home/assets/misp_logs/screenshot.png', + onPrem: onPremInstructions(moduleName, platforms, context), + elasticCloud: cloudInstructions(moduleName, platforms), + onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), + }; +} diff --git a/src/plugins/home/server/tutorials/mongodb_logs/index.ts b/src/plugins/home/server/tutorials/mongodb_logs/index.ts new file mode 100644 index 0000000000000..1c8db19a3873b --- /dev/null +++ b/src/plugins/home/server/tutorials/mongodb_logs/index.ts @@ -0,0 +1,74 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { i18n } from '@kbn/i18n'; +import { TutorialsCategory } from '../../services/tutorials'; +import { + onPremInstructions, + cloudInstructions, + onPremCloudInstructions, +} from '../instructions/filebeat_instructions'; +import { + TutorialContext, + TutorialSchema, +} from '../../services/tutorials/lib/tutorials_registry_types'; + +export function mongodbLogsSpecProvider(context: TutorialContext): TutorialSchema { + const moduleName = 'mongodb'; + const platforms = ['OSX', 'DEB', 'RPM', 'WINDOWS'] as const; + return { + id: 'mongodbLogs', + name: i18n.translate('home.tutorials.mongodbLogs.nameTitle', { + defaultMessage: 'MongoDB logs', + }), + moduleName, + category: TutorialsCategory.LOGGING, + shortDescription: i18n.translate('home.tutorials.mongodbLogs.shortDescription', { + defaultMessage: 'Collect MongoDB logs.', + }), + longDescription: i18n.translate('home.tutorials.mongodbLogs.longDescription', { + defaultMessage: + 'The module collects and parses logs created by [MongoDB](https://www.mongodb.com/). \ +[Learn more]({learnMoreLink}).', + values: { + learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-mongodb.html', + }, + }), + euiIconType: 'logoMongodb', + artifacts: { + dashboards: [ + { + id: 'abcf35b0-0a82-11e8-bffe-ff7d4f68cf94-ecs', + linkLabel: i18n.translate('home.tutorials.mongodbLogs.artifacts.dashboards.linkLabel', { + defaultMessage: 'MongoDB Overview', + }), + isOverview: true, + }, + ], + exportedFields: { + documentationUrl: '{config.docs.beats.filebeat}/exported-fields-mongodb.html', + }, + }, + completionTimeMinutes: 10, + previewImagePath: '/plugins/home/assets/mongodb_logs/screenshot.png', + onPrem: onPremInstructions(moduleName, platforms, context), + elasticCloud: cloudInstructions(moduleName, platforms), + onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), + }; +} diff --git a/src/plugins/home/server/tutorials/mssql_logs/index.ts b/src/plugins/home/server/tutorials/mssql_logs/index.ts new file mode 100644 index 0000000000000..8a18da20f2e6a --- /dev/null +++ b/src/plugins/home/server/tutorials/mssql_logs/index.ts @@ -0,0 +1,71 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { i18n } from '@kbn/i18n'; +import { TutorialsCategory } from '../../services/tutorials'; +import { + onPremInstructions, + cloudInstructions, + onPremCloudInstructions, +} from '../instructions/filebeat_instructions'; +import { + TutorialContext, + TutorialSchema, +} from '../../services/tutorials/lib/tutorials_registry_types'; + +export function mssqlLogsSpecProvider(context: TutorialContext): TutorialSchema { + const moduleName = 'mssql'; + const platforms = ['DEB', 'RPM', 'WINDOWS'] as const; + return { + id: 'mssqlLogs', + name: i18n.translate('home.tutorials.mssqlLogs.nameTitle', { + defaultMessage: 'MSSQL logs', + }), + moduleName, + category: TutorialsCategory.LOGGING, + shortDescription: i18n.translate('home.tutorials.mssqlLogs.shortDescription', { + defaultMessage: 'Collect MSSQL logs.', + }), + longDescription: i18n.translate('home.tutorials.mssqlLogs.longDescription', { + defaultMessage: + 'The module parses error logs created by MSSQL. \ +[Learn more]({learnMoreLink}).', + values: { + learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-mssql.html', + }, + }), + euiIconType: '/plugins/home/assets/logos/microsoft.svg', + artifacts: { + dashboards: [], + application: { + label: i18n.translate('home.tutorials.mssqlLogs.artifacts.application.label', { + defaultMessage: 'Discover', + }), + path: '/app/discover#/', + }, + exportedFields: { + documentationUrl: '{config.docs.beats.filebeat}/exported-fields-mssql.html', + }, + }, + completionTimeMinutes: 10, + onPrem: onPremInstructions(moduleName, platforms, context), + elasticCloud: cloudInstructions(moduleName, platforms), + onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), + }; +} diff --git a/src/plugins/home/server/tutorials/netflow/common_instructions.ts b/src/plugins/home/server/tutorials/netflow/common_instructions.ts deleted file mode 100644 index 8fe24ba9c7994..0000000000000 --- a/src/plugins/home/server/tutorials/netflow/common_instructions.ts +++ /dev/null @@ -1,281 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { i18n } from '@kbn/i18n'; - -export function createCommonNetflowInstructions() { - return { - CONFIG: { - ON_PREM: { - OSX: [ - { - title: i18n.translate('home.tutorials.netflow.common.config.onPrem.osxTitle', { - defaultMessage: 'Edit the configuration', - }), - textPre: i18n.translate('home.tutorials.netflow.common.config.onPrem.osxTextPre', { - defaultMessage: 'Modify {logstashConfigPath} to set the configuration parameters:', - values: { - logstashConfigPath: '`config/logstash.yml`', - }, - }), - commands: ['modules:', ' - name: netflow', ' var.input.udp.port: '], - textPost: i18n.translate('home.tutorials.netflow.common.config.onPrem.osxTextPost', { - defaultMessage: - 'Where {udpPort} is the UDP port on which Logstash will receive Netflow data.', - values: { - udpPort: '``', - }, - }), - }, - ], - WINDOWS: [ - { - title: i18n.translate('home.tutorials.netflow.common.config.onPrem.windowsTitle', { - defaultMessage: 'Edit the configuration', - }), - textPre: i18n.translate('home.tutorials.netflow.common.config.onPrem.windowsTextPre', { - defaultMessage: 'Modify {logstashConfigPath} to set the configuration parameters:', - values: { - logstashConfigPath: '`config\\logstash.yml`', - }, - }), - commands: ['modules:', ' - name: netflow', ' var.input.udp.port: '], - textPost: i18n.translate( - 'home.tutorials.netflow.common.config.onPrem.windowsTextPost', - { - defaultMessage: - 'Where {udpPort} is the UDP port on which Logstash will receive Netflow data.', - values: { - udpPort: '``', - }, - } - ), - }, - ], - }, - ON_PREM_ELASTIC_CLOUD: { - OSX: [ - { - title: i18n.translate( - 'home.tutorials.netflow.common.config.onPremElasticCloud.osxTitle', - { - defaultMessage: 'Edit the configuration', - } - ), - textPre: i18n.translate( - 'home.tutorials.netflow.common.config.onPremElasticCloud.osxTextPre', - { - defaultMessage: 'Modify {logstashConfigPath} to set the configuration parameters:', - values: { - logstashConfigPath: '`config/logstash.yml`', - }, - } - ), - commands: [ - 'modules:', - ' - name: netflow', - ' var.input.udp.port: ', - ' var.elasticsearch.hosts: [ "" ]', - ' var.elasticsearch.username: elastic', - ' var.elasticsearch.password: ', - ], - textPost: i18n.translate( - 'home.tutorials.netflow.common.config.onPremElasticCloud.osxTextPost', - { - defaultMessage: - 'Where {udpPort} is the UDP port on which Logstash will receive Netflow data, \ - {esUrl} is the URL of Elasticsearch running on Elastic Cloud, and \ - {password} is the password of the {elastic} user.', - values: { - elastic: '`elastic`', - esUrl: '``', - password: '``', - udpPort: '``', - }, - } - ), - }, - ], - WINDOWS: [ - { - title: i18n.translate( - 'home.tutorials.netflow.common.config.onPremElasticCloud.windowsTitle', - { - defaultMessage: 'Edit the configuration', - } - ), - textPre: i18n.translate( - 'home.tutorials.netflow.common.config.onPremElasticCloud.windowsTextPre', - { - defaultMessage: 'Modify {logstashConfigPath} to set the configuration parameters:', - values: { - logstashConfigPath: '`config\\logstash.yml`', - }, - } - ), - commands: [ - 'modules:', - ' - name: netflow', - ' var.input.udp.port: ', - ' var.elasticsearch.hosts: [ "" ]', - ' var.elasticsearch.username: elastic', - ' var.elasticsearch.password: ', - ], - textPost: i18n.translate( - 'home.tutorials.netflow.common.config.onPremElasticCloud.windowsTextPost', - { - defaultMessage: - 'Where {udpPort} is the UDP port on which Logstash will receive Netflow data, \ - {esUrl} is the URL of Elasticsearch running on Elastic Cloud, and \ - {password} is the password of the {elastic} user.', - values: { - elastic: '`elastic`', - esUrl: '``', - password: '``', - udpPort: '``', - }, - } - ), - }, - ], - }, - ELASTIC_CLOUD: { - OSX: [ - { - title: i18n.translate('home.tutorials.netflow.common.config.elasticCloud.osxTitle', { - defaultMessage: 'Edit the configuration', - }), - textPre: i18n.translate( - 'home.tutorials.netflow.common.config.elasticCloud.osxTextPre', - { - defaultMessage: 'Modify {logstashConfigPath} to set the configuration parameters:', - values: { - logstashConfigPath: '`config/logstash.yml`', - }, - } - ), - commands: [ - 'cloud.id: "{config.cloud.id}"', - 'cloud.auth: "elastic:"', - ' ', - 'modules:', - ' - name: netflow', - ' var.input.udp.port: ', - ], - textPost: i18n.translate( - 'home.tutorials.netflow.common.config.elasticCloud.osxTextPost', - { - defaultMessage: - 'Where {udpPort} is the UDP port on which Logstash will receive Netflow data and \ - {password} is the password of the {elastic} user.', - values: { - elastic: '`elastic`', - password: '``', - udpPort: '``', - }, - } - ), - }, - ], - WINDOWS: [ - { - title: i18n.translate( - 'home.tutorials.netflow.common.config.elasticCloud.windowsTitle', - { - defaultMessage: 'Edit the configuration', - } - ), - textPre: i18n.translate( - 'home.tutorials.netflow.common.config.elasticCloud.windowsTextPre', - { - defaultMessage: 'Modify {logstashConfigPath} to set the configuration parameters:', - values: { - logstashConfigPath: '`config\\logstash.yml`', - }, - } - ), - commands: [ - 'cloud.id: "{config.cloud.id}"', - 'cloud.auth: "elastic:"', - ' ', - 'modules:', - ' - name: netflow', - ' var.input.udp.port: ', - ], - textPost: i18n.translate( - 'home.tutorials.netflow.common.config.elasticCloud.windowsTextPost', - { - defaultMessage: - 'Where {udpPort} is the UDP port on which Logstash will receive Netflow data and \ - {password} is the password of the {elastic} user.', - values: { - elastic: '`elastic`', - password: '``', - udpPort: '``', - }, - } - ), - }, - ], - }, - }, - SETUP: { - OSX: [ - { - title: i18n.translate('home.tutorials.netflow.common.setup.osxTitle', { - defaultMessage: 'Run the Netflow module', - }), - textPre: i18n.translate('home.tutorials.netflow.common.setup.osxTextPre', { - defaultMessage: 'Run:', - }), - commands: ['./bin/logstash --modules netflow --setup'], - textPost: i18n.translate('home.tutorials.netflow.common.setup.osxTextPost', { - defaultMessage: - 'The {setupOption} option creates a {netflowPrefix} index pattern in Elasticsearch and imports \ - Kibana dashboards and visualizations. Omit this option for subsequent runs to avoid overwriting existing dashboards.', - values: { - setupOption: '`--setup`', - netflowPrefix: '`netflow-*`', - }, - }), - }, - ], - WINDOWS: [ - { - title: i18n.translate('home.tutorials.netflow.common.setup.windowsTitle', { - defaultMessage: 'Run the Netflow module', - }), - textPre: i18n.translate('home.tutorials.netflow.common.setup.windowsTextPre', { - defaultMessage: 'Run:', - }), - commands: ['bin\\logstash --modules netflow --setup'], - textPost: i18n.translate('home.tutorials.netflow.common.setup.windowsTextPost', { - defaultMessage: - 'The {setupOption} option creates a {netflowPrefix} index pattern in Elasticsearch and imports \ - Kibana dashboards and visualizations. Omit this option for subsequent runs to avoid overwriting existing dashboards.', - values: { - setupOption: '`--setup`', - netflowPrefix: '`netflow-*`', - }, - }), - }, - ], - }, - }; -} diff --git a/src/plugins/home/server/tutorials/netflow/elastic_cloud.ts b/src/plugins/home/server/tutorials/netflow/elastic_cloud.ts deleted file mode 100644 index fbedc6abfbb8a..0000000000000 --- a/src/plugins/home/server/tutorials/netflow/elastic_cloud.ts +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { i18n } from '@kbn/i18n'; - -import { INSTRUCTION_VARIANT } from '../../../common/instruction_variant'; -import { createLogstashInstructions } from '../instructions/logstash_instructions'; -import { createCommonNetflowInstructions } from './common_instructions'; - -// TODO: compare with onPremElasticCloud and onPrem scenarios and extract out common bits -export function createElasticCloudInstructions() { - const COMMON_NETFLOW_INSTRUCTIONS = createCommonNetflowInstructions(); - const LOGSTASH_INSTRUCTIONS = createLogstashInstructions(); - - return { - instructionSets: [ - { - title: i18n.translate('home.tutorials.netflow.elasticCloudInstructions.title', { - defaultMessage: 'Getting Started', - }), - instructionVariants: [ - { - id: INSTRUCTION_VARIANT.OSX, - instructions: [ - ...LOGSTASH_INSTRUCTIONS.INSTALL.OSX, - ...COMMON_NETFLOW_INSTRUCTIONS.CONFIG.ELASTIC_CLOUD.OSX, - ...COMMON_NETFLOW_INSTRUCTIONS.SETUP.OSX, - ], - }, - { - id: INSTRUCTION_VARIANT.WINDOWS, - instructions: [ - ...LOGSTASH_INSTRUCTIONS.INSTALL.WINDOWS, - ...COMMON_NETFLOW_INSTRUCTIONS.CONFIG.ELASTIC_CLOUD.WINDOWS, - ...COMMON_NETFLOW_INSTRUCTIONS.SETUP.WINDOWS, - ], - }, - ], - }, - ], - }; -} diff --git a/src/plugins/home/server/tutorials/netflow/index.ts b/src/plugins/home/server/tutorials/netflow/index.ts deleted file mode 100644 index 5be30bbb152b7..0000000000000 --- a/src/plugins/home/server/tutorials/netflow/index.ts +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { i18n } from '@kbn/i18n'; - -import { TutorialsCategory } from '../../services/tutorials'; -import { createOnPremInstructions } from './on_prem'; -import { createElasticCloudInstructions } from './elastic_cloud'; -import { createOnPremElasticCloudInstructions } from './on_prem_elastic_cloud'; - -export function netflowSpecProvider() { - const moduleName = 'netflow'; - return { - id: 'netflow', - name: 'Netflow', - moduleName, - category: TutorialsCategory.SECURITY_SOLUTION, - shortDescription: i18n.translate('home.tutorials.netflow.tutorialShortDescription', { - defaultMessage: 'Collect Netflow records sent by a Netflow exporter.', - }), - longDescription: i18n.translate('home.tutorials.netflow.tutorialLongDescription', { - defaultMessage: - 'The Logstash Netflow module collects and parses network flow data, \ -indexes the events into Elasticsearch, and installs a suite of Kibana dashboards. \ -This module support Netflow Version 5 and 9. [Learn more]({linkUrl}).', - values: { - linkUrl: '{config.docs.logstash}/netflow-module.html', - }, - }), - completionTimeMinutes: 10, - // previewImagePath: 'kibana-apache.png', TODO - onPrem: createOnPremInstructions(), - elasticCloud: createElasticCloudInstructions(), - onPremElasticCloud: createOnPremElasticCloudInstructions(), - }; -} diff --git a/src/plugins/home/server/tutorials/netflow/on_prem.ts b/src/plugins/home/server/tutorials/netflow/on_prem.ts deleted file mode 100644 index ef8c3e172af87..0000000000000 --- a/src/plugins/home/server/tutorials/netflow/on_prem.ts +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { i18n } from '@kbn/i18n'; - -import { INSTRUCTION_VARIANT } from '../../../common/instruction_variant'; -import { createLogstashInstructions } from '../instructions/logstash_instructions'; -import { createCommonNetflowInstructions } from './common_instructions'; - -// TODO: compare with onPremElasticCloud and elasticCloud scenarios and extract out common bits -export function createOnPremInstructions() { - const COMMON_NETFLOW_INSTRUCTIONS = createCommonNetflowInstructions(); - const LOGSTASH_INSTRUCTIONS = createLogstashInstructions(); - - return { - instructionSets: [ - { - title: i18n.translate('home.tutorials.netflow.onPremInstructions.title', { - defaultMessage: 'Getting Started', - }), - instructionVariants: [ - { - id: INSTRUCTION_VARIANT.OSX, - instructions: [ - ...LOGSTASH_INSTRUCTIONS.INSTALL.OSX, - ...COMMON_NETFLOW_INSTRUCTIONS.CONFIG.ON_PREM.OSX, - ...COMMON_NETFLOW_INSTRUCTIONS.SETUP.OSX, - ], - }, - { - id: INSTRUCTION_VARIANT.WINDOWS, - instructions: [ - ...LOGSTASH_INSTRUCTIONS.INSTALL.WINDOWS, - ...COMMON_NETFLOW_INSTRUCTIONS.CONFIG.ON_PREM.WINDOWS, - ...COMMON_NETFLOW_INSTRUCTIONS.SETUP.WINDOWS, - ], - }, - ], - }, - ], - }; -} diff --git a/src/plugins/home/server/tutorials/netflow/on_prem_elastic_cloud.ts b/src/plugins/home/server/tutorials/netflow/on_prem_elastic_cloud.ts deleted file mode 100644 index 85aa694970491..0000000000000 --- a/src/plugins/home/server/tutorials/netflow/on_prem_elastic_cloud.ts +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { i18n } from '@kbn/i18n'; - -import { INSTRUCTION_VARIANT } from '../../../common/instruction_variant'; -import { createLogstashInstructions } from '../instructions/logstash_instructions'; -import { - createTrycloudOption1, - createTrycloudOption2, -} from '../instructions/onprem_cloud_instructions'; -import { createCommonNetflowInstructions } from './common_instructions'; - -// TODO: compare with onPrem and elasticCloud scenarios and extract out common bits -export function createOnPremElasticCloudInstructions() { - const COMMON_NETFLOW_INSTRUCTIONS = createCommonNetflowInstructions(); - const TRYCLOUD_OPTION1 = createTrycloudOption1(); - const TRYCLOUD_OPTION2 = createTrycloudOption2(); - const LOGSTASH_INSTRUCTIONS = createLogstashInstructions(); - - return { - instructionSets: [ - { - title: i18n.translate('home.tutorials.netflow.onPremElasticCloudInstructions.title', { - defaultMessage: 'Getting Started', - }), - instructionVariants: [ - { - id: INSTRUCTION_VARIANT.OSX, - instructions: [ - TRYCLOUD_OPTION1, - TRYCLOUD_OPTION2, - ...LOGSTASH_INSTRUCTIONS.INSTALL.OSX, - ...COMMON_NETFLOW_INSTRUCTIONS.CONFIG.ON_PREM_ELASTIC_CLOUD.OSX, - ...COMMON_NETFLOW_INSTRUCTIONS.SETUP.OSX, - ], - }, - { - id: INSTRUCTION_VARIANT.WINDOWS, - instructions: [ - TRYCLOUD_OPTION1, - TRYCLOUD_OPTION2, - ...LOGSTASH_INSTRUCTIONS.INSTALL.WINDOWS, - ...COMMON_NETFLOW_INSTRUCTIONS.CONFIG.ON_PREM_ELASTIC_CLOUD.WINDOWS, - ...COMMON_NETFLOW_INSTRUCTIONS.SETUP.WINDOWS, - ], - }, - ], - }, - ], - }; -} diff --git a/src/plugins/home/server/tutorials/netflow_logs/index.ts b/src/plugins/home/server/tutorials/netflow_logs/index.ts new file mode 100644 index 0000000000000..0e36bcafae580 --- /dev/null +++ b/src/plugins/home/server/tutorials/netflow_logs/index.ts @@ -0,0 +1,73 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { i18n } from '@kbn/i18n'; +import { TutorialsCategory } from '../../services/tutorials'; +import { + onPremInstructions, + cloudInstructions, + onPremCloudInstructions, +} from '../instructions/filebeat_instructions'; +import { + TutorialContext, + TutorialSchema, +} from '../../services/tutorials/lib/tutorials_registry_types'; + +export function netflowLogsSpecProvider(context: TutorialContext): TutorialSchema { + const moduleName = 'netflow'; + const platforms = ['OSX', 'DEB', 'RPM', 'WINDOWS'] as const; + return { + id: 'netflowLogs', + name: i18n.translate('home.tutorials.netflowLogs.nameTitle', { + defaultMessage: 'NetFlow / IPFIX Collector', + }), + moduleName, + category: TutorialsCategory.SECURITY_SOLUTION, + shortDescription: i18n.translate('home.tutorials.netflowLogs.shortDescription', { + defaultMessage: 'Collect NetFlow and IPFIX flow records.', + }), + longDescription: i18n.translate('home.tutorials.netflowLogs.longDescription', { + defaultMessage: + 'This is a module for receiving NetFlow and IPFIX flow records over UDP. This input supports NetFlow versions 1, 5, 6, 7, 8 and 9, as well as IPFIX. For NetFlow versions older than 9, fields are mapped automatically to NetFlow v9. \ +[Learn more]({learnMoreLink}).', + values: { + learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-netflow.html', + }, + }), + euiIconType: 'logoBeats', + artifacts: { + dashboards: [ + { + id: '34e26884-161a-4448-9556-43b5bf2f62a2', + linkLabel: i18n.translate('home.tutorials.netflowLogs.artifacts.dashboards.linkLabel', { + defaultMessage: 'Netflow Overview', + }), + isOverview: true, + }, + ], + exportedFields: { + documentationUrl: '{config.docs.beats.filebeat}/exported-fields-netflow.html', + }, + }, + completionTimeMinutes: 10, + onPrem: onPremInstructions(moduleName, platforms, context), + elasticCloud: cloudInstructions(moduleName, platforms), + onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), + }; +} diff --git a/src/plugins/home/server/tutorials/netscout_logs/index.ts b/src/plugins/home/server/tutorials/netscout_logs/index.ts new file mode 100644 index 0000000000000..b94e0df0bf795 --- /dev/null +++ b/src/plugins/home/server/tutorials/netscout_logs/index.ts @@ -0,0 +1,71 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { i18n } from '@kbn/i18n'; +import { TutorialsCategory } from '../../services/tutorials'; +import { + onPremInstructions, + cloudInstructions, + onPremCloudInstructions, +} from '../instructions/filebeat_instructions'; +import { + TutorialContext, + TutorialSchema, +} from '../../services/tutorials/lib/tutorials_registry_types'; + +export function netscoutLogsSpecProvider(context: TutorialContext): TutorialSchema { + const moduleName = 'netscout'; + const platforms = ['OSX', 'DEB', 'RPM', 'WINDOWS'] as const; + return { + id: 'netscoutLogs', + name: i18n.translate('home.tutorials.netscoutLogs.nameTitle', { + defaultMessage: 'Arbor Peakflow logs', + }), + moduleName, + category: TutorialsCategory.SECURITY_SOLUTION, + shortDescription: i18n.translate('home.tutorials.netscoutLogs.shortDescription', { + defaultMessage: 'Collect Netscout Arbor Peakflow SP logs over syslog or from a file.', + }), + longDescription: i18n.translate('home.tutorials.netscoutLogs.longDescription', { + defaultMessage: + 'This is a module for receiving Arbor Peakflow SP logs over Syslog or a file. \ +[Learn more]({learnMoreLink}).', + values: { + learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-netscout.html', + }, + }), + euiIconType: '/plugins/home/assets/logos/netscout.svg', + artifacts: { + dashboards: [], + application: { + path: '/app/security', + label: i18n.translate('home.tutorials.netscoutLogs.artifacts.dashboards.linkLabel', { + defaultMessage: 'Security App', + }), + }, + exportedFields: { + documentationUrl: '{config.docs.beats.filebeat}/exported-fields-netscout.html', + }, + }, + completionTimeMinutes: 10, + onPrem: onPremInstructions(moduleName, platforms, context), + elasticCloud: cloudInstructions(moduleName, platforms), + onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), + }; +} diff --git a/src/plugins/home/server/tutorials/o365_logs/index.ts b/src/plugins/home/server/tutorials/o365_logs/index.ts new file mode 100644 index 0000000000000..2ee3f3550a0d7 --- /dev/null +++ b/src/plugins/home/server/tutorials/o365_logs/index.ts @@ -0,0 +1,77 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { i18n } from '@kbn/i18n'; +import { TutorialsCategory } from '../../services/tutorials'; +import { + onPremInstructions, + cloudInstructions, + onPremCloudInstructions, +} from '../instructions/filebeat_instructions'; +import { + TutorialContext, + TutorialSchema, +} from '../../services/tutorials/lib/tutorials_registry_types'; + +export function o365LogsSpecProvider(context: TutorialContext): TutorialSchema { + const moduleName = 'o365'; + const platforms = ['OSX', 'DEB', 'RPM', 'WINDOWS'] as const; + return { + id: 'o365Logs', + name: i18n.translate('home.tutorials.o365Logs.nameTitle', { + defaultMessage: 'Office 365 logs', + }), + moduleName, + category: TutorialsCategory.SECURITY_SOLUTION, + shortDescription: i18n.translate('home.tutorials.o365Logs.shortDescription', { + defaultMessage: 'Collect Office 365 activity logs via the Office 365 API.', + }), + longDescription: i18n.translate('home.tutorials.o365Logs.longDescription', { + defaultMessage: + 'This is a module for Office 365 logs received via one of the Office 365 \ + API endpoints. It currently supports user, admin, system, and policy \ + actions and events from Office 365 and Azure AD activity logs exposed \ + by the Office 365 Management Activity API. \ + [Learn more]({learnMoreLink}).', + values: { + learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-o365.html', + }, + }), + euiIconType: '/plugins/home/assets/logos/o365.svg', + artifacts: { + dashboards: [ + { + id: '712e2c00-685d-11ea-8d6a-292ef5d68366', + linkLabel: i18n.translate('home.tutorials.o365Logs.artifacts.dashboards.linkLabel', { + defaultMessage: 'O365 Audit Dashboard', + }), + isOverview: true, + }, + ], + exportedFields: { + documentationUrl: '{config.docs.beats.filebeat}/exported-fields-o365.html', + }, + }, + completionTimeMinutes: 10, + previewImagePath: '/plugins/home/assets/o365_logs/screenshot.png', + onPrem: onPremInstructions(moduleName, platforms, context), + elasticCloud: cloudInstructions(moduleName, platforms), + onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), + }; +} diff --git a/src/plugins/home/server/tutorials/okta_logs/index.ts b/src/plugins/home/server/tutorials/okta_logs/index.ts new file mode 100644 index 0000000000000..6371d9848af2e --- /dev/null +++ b/src/plugins/home/server/tutorials/okta_logs/index.ts @@ -0,0 +1,75 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { i18n } from '@kbn/i18n'; +import { TutorialsCategory } from '../../services/tutorials'; +import { + onPremInstructions, + cloudInstructions, + onPremCloudInstructions, +} from '../instructions/filebeat_instructions'; +import { + TutorialContext, + TutorialSchema, +} from '../../services/tutorials/lib/tutorials_registry_types'; + +export function oktaLogsSpecProvider(context: TutorialContext): TutorialSchema { + const moduleName = 'okta'; + const platforms = ['OSX', 'DEB', 'RPM', 'WINDOWS'] as const; + return { + id: 'oktaLogs', + name: i18n.translate('home.tutorials.oktaLogs.nameTitle', { + defaultMessage: 'Okta logs', + }), + moduleName, + category: TutorialsCategory.SECURITY_SOLUTION, + shortDescription: i18n.translate('home.tutorials.oktaLogs.shortDescription', { + defaultMessage: 'Collect the Okta system log via the Okta API.', + }), + longDescription: i18n.translate('home.tutorials.oktaLogs.longDescription', { + defaultMessage: + 'The Okta module collects events from the [Okta API](https://developer.okta.com/docs/reference/). \ + Specifically this supports reading from the [Okta System Log API](https://developer.okta.com/docs/reference/api/system-log/). \ + [Learn more]({learnMoreLink}).', + values: { + learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-okta.html', + }, + }), + euiIconType: '/plugins/home/assets/logos/okta.svg', + artifacts: { + dashboards: [ + { + id: '749203a0-67b1-11ea-a76f-bf44814e437d', + linkLabel: i18n.translate('home.tutorials.oktaLogs.artifacts.dashboards.linkLabel', { + defaultMessage: 'Okta Overview', + }), + isOverview: true, + }, + ], + exportedFields: { + documentationUrl: '{config.docs.beats.filebeat}/exported-fields-okta.html', + }, + }, + completionTimeMinutes: 10, + previewImagePath: '/plugins/home/assets/okta_logs/screenshot.png', + onPrem: onPremInstructions(moduleName, platforms, context), + elasticCloud: cloudInstructions(moduleName, platforms), + onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), + }; +} diff --git a/src/plugins/home/server/tutorials/oracle_metrics/index.ts b/src/plugins/home/server/tutorials/oracle_metrics/index.ts index d2ddd19b930a2..4fd946c08e58a 100644 --- a/src/plugins/home/server/tutorials/oracle_metrics/index.ts +++ b/src/plugins/home/server/tutorials/oracle_metrics/index.ts @@ -51,6 +51,7 @@ export function oracleMetricsSpecProvider(context: TutorialContext): TutorialSch learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-' + moduleName + '.html', }, }), + euiIconType: '/plugins/home/assets/logos/oracle.svg', artifacts: { application: { label: i18n.translate('home.tutorials.oracleMetrics.artifacts.application.label', { diff --git a/src/plugins/home/server/tutorials/osquery_logs/index.ts b/src/plugins/home/server/tutorials/osquery_logs/index.ts index c4869a889a085..1d98b30b324ce 100644 --- a/src/plugins/home/server/tutorials/osquery_logs/index.ts +++ b/src/plugins/home/server/tutorials/osquery_logs/index.ts @@ -40,23 +40,27 @@ export function osqueryLogsSpecProvider(context: TutorialContext): TutorialSchem moduleName, category: TutorialsCategory.SECURITY_SOLUTION, shortDescription: i18n.translate('home.tutorials.osqueryLogs.shortDescription', { - defaultMessage: 'Collect the result logs created by osqueryd.', + defaultMessage: 'Collect osquery logs in JSON format.', }), longDescription: i18n.translate('home.tutorials.osqueryLogs.longDescription', { defaultMessage: - 'The `osquery` Filebeat module collects the JSON result logs collected by `osqueryd`. \ -[Learn more]({learnMoreLink}).', + 'The module collects and decodes the result logs written by \ + [osqueryd](https://osquery.readthedocs.io/en/latest/introduction/using-osqueryd/) in \ + the JSON format. To set up osqueryd follow the osquery installation instructions for \ + your operating system and configure the `filesystem` logging driver (the default). \ + Make sure UTC timestamps are enabled. \ + [Learn more]({learnMoreLink}).', values: { learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-osquery.html', }, }), - euiIconType: 'logoOsquery', + euiIconType: '/plugins/home/assets/logos/osquery.svg', artifacts: { dashboards: [ { id: '69f5ae20-eb02-11e7-8f04-51231daa5b05-ecs', linkLabel: i18n.translate('home.tutorials.osqueryLogs.artifacts.dashboards.linkLabel', { - defaultMessage: 'Osquery logs dashboard', + defaultMessage: 'Osquery Compliance Pack', }), isOverview: true, }, @@ -66,7 +70,6 @@ export function osqueryLogsSpecProvider(context: TutorialContext): TutorialSchem }, }, completionTimeMinutes: 10, - previewImagePath: '/plugins/home/assets/osquery_logs/screenshot.png', onPrem: onPremInstructions(moduleName, platforms, context), elasticCloud: cloudInstructions(moduleName, platforms), onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), diff --git a/src/plugins/home/server/tutorials/panw_logs/index.ts b/src/plugins/home/server/tutorials/panw_logs/index.ts new file mode 100644 index 0000000000000..5a0da7538b4c0 --- /dev/null +++ b/src/plugins/home/server/tutorials/panw_logs/index.ts @@ -0,0 +1,77 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { i18n } from '@kbn/i18n'; +import { TutorialsCategory } from '../../services/tutorials'; +import { + onPremInstructions, + cloudInstructions, + onPremCloudInstructions, +} from '../instructions/filebeat_instructions'; +import { + TutorialContext, + TutorialSchema, +} from '../../services/tutorials/lib/tutorials_registry_types'; + +export function panwLogsSpecProvider(context: TutorialContext): TutorialSchema { + const moduleName = 'panw'; + const platforms = ['OSX', 'DEB', 'RPM', 'WINDOWS'] as const; + return { + id: 'panwLogs', + name: i18n.translate('home.tutorials.panwLogs.nameTitle', { + defaultMessage: 'Palo Alto Networks PAN-OS logs', + }), + moduleName, + category: TutorialsCategory.SECURITY_SOLUTION, + shortDescription: i18n.translate('home.tutorials.panwLogs.shortDescription', { + defaultMessage: + 'Collect Palo Alto Networks PAN-OS threat and traffic logs over syslog or from a log file.', + }), + longDescription: i18n.translate('home.tutorials.panwLogs.longDescription', { + defaultMessage: + 'This is a module for Palo Alto Networks PAN-OS firewall monitoring \ + logs received over Syslog or read from a file. It currently supports \ + messages of Traffic and Threat types. \ +[Learn more]({learnMoreLink}).', + values: { + learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-panw.html', + }, + }), + euiIconType: '/plugins/home/assets/logos/paloalto.svg', + artifacts: { + dashboards: [ + { + id: 'e40ba240-7572-11e9-976e-65a8f47cc4c1', + linkLabel: i18n.translate('home.tutorials.panwLogs.artifacts.dashboards.linkLabel', { + defaultMessage: 'PANW Network Flows', + }), + isOverview: true, + }, + ], + exportedFields: { + documentationUrl: '{config.docs.beats.filebeat}/exported-fields-panw.html', + }, + }, + completionTimeMinutes: 10, + previewImagePath: '/plugins/home/assets/panw_logs/screenshot.png', + onPrem: onPremInstructions(moduleName, platforms, context), + elasticCloud: cloudInstructions(moduleName, platforms), + onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), + }; +} diff --git a/src/plugins/home/server/tutorials/rabbitmq_logs/index.ts b/src/plugins/home/server/tutorials/rabbitmq_logs/index.ts new file mode 100644 index 0000000000000..2676f8b52306c --- /dev/null +++ b/src/plugins/home/server/tutorials/rabbitmq_logs/index.ts @@ -0,0 +1,71 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { i18n } from '@kbn/i18n'; +import { TutorialsCategory } from '../../services/tutorials'; +import { + onPremInstructions, + cloudInstructions, + onPremCloudInstructions, +} from '../instructions/filebeat_instructions'; +import { + TutorialContext, + TutorialSchema, +} from '../../services/tutorials/lib/tutorials_registry_types'; + +export function rabbitmqLogsSpecProvider(context: TutorialContext): TutorialSchema { + const moduleName = 'rabbitmq'; + const platforms = ['OSX', 'DEB', 'RPM', 'WINDOWS'] as const; + return { + id: 'rabbitmqLogs', + name: i18n.translate('home.tutorials.rabbitmqLogs.nameTitle', { + defaultMessage: 'RabbitMQ logs', + }), + moduleName, + category: TutorialsCategory.LOGGING, + shortDescription: i18n.translate('home.tutorials.rabbitmqLogs.shortDescription', { + defaultMessage: 'Collect RabbitMQ logs.', + }), + longDescription: i18n.translate('home.tutorials.rabbitmqLogs.longDescription', { + defaultMessage: + 'This is the module for parsing [RabbitMQ log files](https://www.rabbitmq.com/logging.html) \ +[Learn more]({learnMoreLink}).', + values: { + learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-rabbitmq.html', + }, + }), + euiIconType: '/plugins/home/assets/logos/rabbitmq.svg', + artifacts: { + dashboards: [], + application: { + label: i18n.translate('home.tutorials.rabbitmqLogs.artifacts.application.label', { + defaultMessage: 'Discover', + }), + path: '/app/discover#/', + }, + exportedFields: { + documentationUrl: '{config.docs.beats.filebeat}/exported-fields-rabbitmq.html', + }, + }, + completionTimeMinutes: 10, + onPrem: onPremInstructions(moduleName, platforms, context), + elasticCloud: cloudInstructions(moduleName, platforms), + onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), + }; +} diff --git a/src/plugins/home/server/tutorials/radware_logs/index.ts b/src/plugins/home/server/tutorials/radware_logs/index.ts new file mode 100644 index 0000000000000..10f32c7b767ab --- /dev/null +++ b/src/plugins/home/server/tutorials/radware_logs/index.ts @@ -0,0 +1,71 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { i18n } from '@kbn/i18n'; +import { TutorialsCategory } from '../../services/tutorials'; +import { + onPremInstructions, + cloudInstructions, + onPremCloudInstructions, +} from '../instructions/filebeat_instructions'; +import { + TutorialContext, + TutorialSchema, +} from '../../services/tutorials/lib/tutorials_registry_types'; + +export function radwareLogsSpecProvider(context: TutorialContext): TutorialSchema { + const moduleName = 'radware'; + const platforms = ['OSX', 'DEB', 'RPM', 'WINDOWS'] as const; + return { + id: 'radwareLogs', + name: i18n.translate('home.tutorials.radwareLogs.nameTitle', { + defaultMessage: 'Radware DefensePro logs', + }), + moduleName, + category: TutorialsCategory.SECURITY_SOLUTION, + shortDescription: i18n.translate('home.tutorials.radwareLogs.shortDescription', { + defaultMessage: 'Collect Radware DefensePro logs over syslog or from a file.', + }), + longDescription: i18n.translate('home.tutorials.radwareLogs.longDescription', { + defaultMessage: + 'This is a module for receiving Radware DefensePro logs over Syslog or a file. \ +[Learn more]({learnMoreLink}).', + values: { + learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-radware.html', + }, + }), + euiIconType: '/plugins/home/assets/logos/radware.svg', + artifacts: { + dashboards: [], + application: { + path: '/app/security', + label: i18n.translate('home.tutorials.radwareLogs.artifacts.dashboards.linkLabel', { + defaultMessage: 'Security App', + }), + }, + exportedFields: { + documentationUrl: '{config.docs.beats.filebeat}/exported-fields-radware.html', + }, + }, + completionTimeMinutes: 10, + onPrem: onPremInstructions(moduleName, platforms, context), + elasticCloud: cloudInstructions(moduleName, platforms), + onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), + }; +} diff --git a/src/plugins/home/server/tutorials/register.ts b/src/plugins/home/server/tutorials/register.ts index c48423edb2a07..67e9f5a406803 100644 --- a/src/plugins/home/server/tutorials/register.ts +++ b/src/plugins/home/server/tutorials/register.ts @@ -16,82 +16,115 @@ * specific language governing permissions and limitations * under the License. */ -import { systemLogsSpecProvider } from './system_logs'; -import { systemMetricsSpecProvider } from './system_metrics'; +import { activemqLogsSpecProvider } from './activemq_logs'; +import { activemqMetricsSpecProvider } from './activemq_metrics'; +import { aerospikeMetricsSpecProvider } from './aerospike_metrics'; import { apacheLogsSpecProvider } from './apache_logs'; import { apacheMetricsSpecProvider } from './apache_metrics'; +import { auditbeatSpecProvider } from './auditbeat'; +import { auditdLogsSpecProvider } from './auditd_logs'; +import { awsLogsSpecProvider } from './aws_logs'; +import { awsMetricsSpecProvider } from './aws_metrics'; +import { azureLogsSpecProvider } from './azure_logs'; +import { azureMetricsSpecProvider } from './azure_metrics'; +import { barracudaLogsSpecProvider } from './barracuda_logs'; +import { bluecoatLogsSpecProvider } from './bluecoat_logs'; +import { cefLogsSpecProvider } from './cef_logs'; +import { cephMetricsSpecProvider } from './ceph_metrics'; +import { checkpointLogsSpecProvider } from './checkpoint_logs'; +import { ciscoLogsSpecProvider } from './cisco_logs'; +import { cloudwatchLogsSpecProvider } from './cloudwatch_logs'; +import { cockroachdbMetricsSpecProvider } from './cockroachdb_metrics'; +import { consulMetricsSpecProvider } from './consul_metrics'; +import { corednsLogsSpecProvider } from './coredns_logs'; +import { corednsMetricsSpecProvider } from './coredns_metrics'; +import { couchbaseMetricsSpecProvider } from './couchbase_metrics'; +import { couchdbMetricsSpecProvider } from './couchdb_metrics'; +import { crowdstrikeLogsSpecProvider } from './crowdstrike_logs'; +import { cylanceLogsSpecProvider } from './cylance_logs'; +import { dockerMetricsSpecProvider } from './docker_metrics'; +import { dropwizardMetricsSpecProvider } from './dropwizard_metrics'; import { elasticsearchLogsSpecProvider } from './elasticsearch_logs'; +import { elasticsearchMetricsSpecProvider } from './elasticsearch_metrics'; +import { envoyproxyLogsSpecProvider } from './envoyproxy_logs'; +import { envoyproxyMetricsSpecProvider } from './envoyproxy_metrics'; +import { etcdMetricsSpecProvider } from './etcd_metrics'; +import { f5LogsSpecProvider } from './f5_logs'; +import { fortinetLogsSpecProvider } from './fortinet_logs'; +import { golangMetricsSpecProvider } from './golang_metrics'; +import { googlecloudLogsSpecProvider } from './googlecloud_logs'; +import { googlecloudMetricsSpecProvider } from './googlecloud_metrics'; +import { gsuiteLogsSpecProvider } from './gsuite_logs'; +import { haproxyLogsSpecProvider } from './haproxy_logs'; +import { haproxyMetricsSpecProvider } from './haproxy_metrics'; +import { ibmmqLogsSpecProvider } from './ibmmq_logs'; +import { ibmmqMetricsSpecProvider } from './ibmmq_metrics'; +import { icingaLogsSpecProvider } from './icinga_logs'; import { iisLogsSpecProvider } from './iis_logs'; +import { iisMetricsSpecProvider } from './iis_metrics'; +import { impervaLogsSpecProvider } from './imperva_logs'; +import { infobloxLogsSpecProvider } from './infoblox_logs'; +import { iptablesLogsSpecProvider } from './iptables_logs'; +import { juniperLogsSpecProvider } from './juniper_logs'; import { kafkaLogsSpecProvider } from './kafka_logs'; +import { kafkaMetricsSpecProvider } from './kafka_metrics'; +import { kibanaLogsSpecProvider } from './kibana_logs'; +import { kibanaMetricsSpecProvider } from './kibana_metrics'; +import { kubernetesMetricsSpecProvider } from './kubernetes_metrics'; import { logstashLogsSpecProvider } from './logstash_logs'; -import { nginxLogsSpecProvider } from './nginx_logs'; -import { nginxMetricsSpecProvider } from './nginx_metrics'; +import { logstashMetricsSpecProvider } from './logstash_metrics'; +import { memcachedMetricsSpecProvider } from './memcached_metrics'; +import { microsoftLogsSpecProvider } from './microsoft_logs'; +import { mispLogsSpecProvider } from './misp_logs'; +import { mongodbLogsSpecProvider } from './mongodb_logs'; +import { mongodbMetricsSpecProvider } from './mongodb_metrics'; +import { mssqlLogsSpecProvider } from './mssql_logs'; +import { mssqlMetricsSpecProvider } from './mssql_metrics'; +import { muninMetricsSpecProvider } from './munin_metrics'; import { mysqlLogsSpecProvider } from './mysql_logs'; import { mysqlMetricsSpecProvider } from './mysql_metrics'; -import { mongodbMetricsSpecProvider } from './mongodb_metrics'; +import { natsLogsSpecProvider } from './nats_logs'; +import { natsMetricsSpecProvider } from './nats_metrics'; +import { netflowLogsSpecProvider } from './netflow_logs'; +import { netscoutLogsSpecProvider } from './netscout_logs'; +import { nginxLogsSpecProvider } from './nginx_logs'; +import { nginxMetricsSpecProvider } from './nginx_metrics'; +import { o365LogsSpecProvider } from './o365_logs'; +import { oktaLogsSpecProvider } from './okta_logs'; +import { openmetricsMetricsSpecProvider } from './openmetrics_metrics'; +import { oracleMetricsSpecProvider } from './oracle_metrics'; import { osqueryLogsSpecProvider } from './osquery_logs'; +import { panwLogsSpecProvider } from './panw_logs'; import { phpfpmMetricsSpecProvider } from './php_fpm_metrics'; -import { postgresqlMetricsSpecProvider } from './postgresql_metrics'; import { postgresqlLogsSpecProvider } from './postgresql_logs'; +import { postgresqlMetricsSpecProvider } from './postgresql_metrics'; +import { prometheusMetricsSpecProvider } from './prometheus_metrics'; +import { rabbitmqLogsSpecProvider } from './rabbitmq_logs'; import { rabbitmqMetricsSpecProvider } from './rabbitmq_metrics'; +import { radwareLogsSpecProvider } from './radware_logs'; import { redisLogsSpecProvider } from './redis_logs'; import { redisMetricsSpecProvider } from './redis_metrics'; +import { redisenterpriseMetricsSpecProvider } from './redisenterprise_metrics'; +import { santaLogsSpecProvider } from './santa_logs'; +import { sonicwallLogsSpecProvider } from './sonicwall_logs'; +import { sophosLogsSpecProvider } from './sophos_logs'; +import { squidLogsSpecProvider } from './squid_logs'; +import { stanMetricsSpecProvider } from './stan_metrics'; +import { statsdMetricsSpecProvider } from './statsd_metrics'; import { suricataLogsSpecProvider } from './suricata_logs'; -import { dockerMetricsSpecProvider } from './docker_metrics'; -import { kubernetesMetricsSpecProvider } from './kubernetes_metrics'; -import { uwsgiMetricsSpecProvider } from './uwsgi_metrics'; -import { netflowSpecProvider } from './netflow'; +import { systemLogsSpecProvider } from './system_logs'; +import { systemMetricsSpecProvider } from './system_metrics'; +import { tomcatLogsSpecProvider } from './tomcat_logs'; import { traefikLogsSpecProvider } from './traefik_logs'; -import { cephMetricsSpecProvider } from './ceph_metrics'; -import { aerospikeMetricsSpecProvider } from './aerospike_metrics'; -import { couchbaseMetricsSpecProvider } from './couchbase_metrics'; -import { dropwizardMetricsSpecProvider } from './dropwizard_metrics'; -import { elasticsearchMetricsSpecProvider } from './elasticsearch_metrics'; -import { etcdMetricsSpecProvider } from './etcd_metrics'; -import { haproxyMetricsSpecProvider } from './haproxy_metrics'; -import { kafkaMetricsSpecProvider } from './kafka_metrics'; -import { kibanaMetricsSpecProvider } from './kibana_metrics'; -import { memcachedMetricsSpecProvider } from './memcached_metrics'; -import { muninMetricsSpecProvider } from './munin_metrics'; +import { traefikMetricsSpecProvider } from './traefik_metrics'; +import { uptimeMonitorsSpecProvider } from './uptime_monitors'; +import { uwsgiMetricsSpecProvider } from './uwsgi_metrics'; import { vSphereMetricsSpecProvider } from './vsphere_metrics'; -import { windowsMetricsSpecProvider } from './windows_metrics'; import { windowsEventLogsSpecProvider } from './windows_event_logs'; -import { golangMetricsSpecProvider } from './golang_metrics'; -import { logstashMetricsSpecProvider } from './logstash_metrics'; -import { prometheusMetricsSpecProvider } from './prometheus_metrics'; -import { zookeeperMetricsSpecProvider } from './zookeeper_metrics'; -import { uptimeMonitorsSpecProvider } from './uptime_monitors'; -import { cloudwatchLogsSpecProvider } from './cloudwatch_logs'; -import { awsMetricsSpecProvider } from './aws_metrics'; -import { mssqlMetricsSpecProvider } from './mssql_metrics'; -import { natsMetricsSpecProvider } from './nats_metrics'; -import { natsLogsSpecProvider } from './nats_logs'; +import { windowsMetricsSpecProvider } from './windows_metrics'; import { zeekLogsSpecProvider } from './zeek_logs'; -import { corednsMetricsSpecProvider } from './coredns_metrics'; -import { corednsLogsSpecProvider } from './coredns_logs'; -import { auditbeatSpecProvider } from './auditbeat'; -import { iptablesLogsSpecProvider } from './iptables_logs'; -import { ciscoLogsSpecProvider } from './cisco_logs'; -import { envoyproxyLogsSpecProvider } from './envoyproxy_logs'; -import { couchdbMetricsSpecProvider } from './couchdb_metrics'; -import { consulMetricsSpecProvider } from './consul_metrics'; -import { cockroachdbMetricsSpecProvider } from './cockroachdb_metrics'; -import { traefikMetricsSpecProvider } from './traefik_metrics'; -import { awsLogsSpecProvider } from './aws_logs'; -import { activemqLogsSpecProvider } from './activemq_logs'; -import { activemqMetricsSpecProvider } from './activemq_metrics'; -import { azureMetricsSpecProvider } from './azure_metrics'; -import { ibmmqLogsSpecProvider } from './ibmmq_logs'; -import { stanMetricsSpecProvider } from './stan_metrics'; -import { envoyproxyMetricsSpecProvider } from './envoyproxy_metrics'; -import { ibmmqMetricsSpecProvider } from './ibmmq_metrics'; -import { statsdMetricsSpecProvider } from './statsd_metrics'; -import { redisenterpriseMetricsSpecProvider } from './redisenterprise_metrics'; -import { openmetricsMetricsSpecProvider } from './openmetrics_metrics'; -import { oracleMetricsSpecProvider } from './oracle_metrics'; -import { iisMetricsSpecProvider } from './iis_metrics'; -import { azureLogsSpecProvider } from './azure_logs'; -import { googlecloudMetricsSpecProvider } from './googlecloud_metrics'; +import { zookeeperMetricsSpecProvider } from './zookeeper_metrics'; +import { zscalerLogsSpecProvider } from './zscaler_logs'; export const builtInTutorials = [ systemLogsSpecProvider, @@ -118,7 +151,7 @@ export const builtInTutorials = [ dockerMetricsSpecProvider, kubernetesMetricsSpecProvider, uwsgiMetricsSpecProvider, - netflowSpecProvider, + netflowLogsSpecProvider, traefikLogsSpecProvider, cephMetricsSpecProvider, aerospikeMetricsSpecProvider, @@ -170,4 +203,37 @@ export const builtInTutorials = [ iisMetricsSpecProvider, azureLogsSpecProvider, googlecloudMetricsSpecProvider, + auditdLogsSpecProvider, + barracudaLogsSpecProvider, + bluecoatLogsSpecProvider, + cefLogsSpecProvider, + checkpointLogsSpecProvider, + crowdstrikeLogsSpecProvider, + cylanceLogsSpecProvider, + f5LogsSpecProvider, + fortinetLogsSpecProvider, + googlecloudLogsSpecProvider, + gsuiteLogsSpecProvider, + haproxyLogsSpecProvider, + icingaLogsSpecProvider, + impervaLogsSpecProvider, + infobloxLogsSpecProvider, + juniperLogsSpecProvider, + kibanaLogsSpecProvider, + microsoftLogsSpecProvider, + mispLogsSpecProvider, + mongodbLogsSpecProvider, + mssqlLogsSpecProvider, + netscoutLogsSpecProvider, + o365LogsSpecProvider, + oktaLogsSpecProvider, + panwLogsSpecProvider, + rabbitmqLogsSpecProvider, + radwareLogsSpecProvider, + santaLogsSpecProvider, + sonicwallLogsSpecProvider, + sophosLogsSpecProvider, + squidLogsSpecProvider, + tomcatLogsSpecProvider, + zscalerLogsSpecProvider, ]; diff --git a/src/plugins/home/server/tutorials/santa_logs/index.ts b/src/plugins/home/server/tutorials/santa_logs/index.ts new file mode 100644 index 0000000000000..3cdab67a08b57 --- /dev/null +++ b/src/plugins/home/server/tutorials/santa_logs/index.ts @@ -0,0 +1,75 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { i18n } from '@kbn/i18n'; +import { TutorialsCategory } from '../../services/tutorials'; +import { + onPremInstructions, + cloudInstructions, + onPremCloudInstructions, +} from '../instructions/filebeat_instructions'; +import { + TutorialContext, + TutorialSchema, +} from '../../services/tutorials/lib/tutorials_registry_types'; + +export function santaLogsSpecProvider(context: TutorialContext): TutorialSchema { + const moduleName = 'santa'; + const platforms = ['OSX'] as const; + return { + id: 'santaLogs', + name: i18n.translate('home.tutorials.santaLogs.nameTitle', { + defaultMessage: 'Google Santa logs', + }), + moduleName, + category: TutorialsCategory.SECURITY_SOLUTION, + shortDescription: i18n.translate('home.tutorials.santaLogs.shortDescription', { + defaultMessage: 'Collect Google Santa logs about process executions on MacOS.', + }), + longDescription: i18n.translate('home.tutorials.santaLogs.longDescription', { + defaultMessage: + 'The module collects and parses logs from [Google Santa](https://github.com/google/santa), \ + a security tool for macOS that monitors process executions and can blacklist/whitelist binaries. \ +[Learn more]({learnMoreLink}).', + values: { + learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-santa.html', + }, + }), + euiIconType: 'logoLogging', + artifacts: { + dashboards: [ + { + id: '161855f0-ff6a-11e8-93c5-d5ecd1b3e307-ecs', + linkLabel: i18n.translate('home.tutorials.santaLogs.artifacts.dashboards.linkLabel', { + defaultMessage: 'Santa Overview', + }), + isOverview: true, + }, + ], + exportedFields: { + documentationUrl: '{config.docs.beats.filebeat}/exported-fields-santa.html', + }, + }, + completionTimeMinutes: 10, + previewImagePath: '/plugins/home/assets/santa_logs/screenshot.png', + onPrem: onPremInstructions(moduleName, platforms, context), + elasticCloud: cloudInstructions(moduleName, platforms), + onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), + }; +} diff --git a/src/plugins/home/server/tutorials/sonicwall_logs/index.ts b/src/plugins/home/server/tutorials/sonicwall_logs/index.ts new file mode 100644 index 0000000000000..49cfa694f3888 --- /dev/null +++ b/src/plugins/home/server/tutorials/sonicwall_logs/index.ts @@ -0,0 +1,71 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { i18n } from '@kbn/i18n'; +import { TutorialsCategory } from '../../services/tutorials'; +import { + onPremInstructions, + cloudInstructions, + onPremCloudInstructions, +} from '../instructions/filebeat_instructions'; +import { + TutorialContext, + TutorialSchema, +} from '../../services/tutorials/lib/tutorials_registry_types'; + +export function sonicwallLogsSpecProvider(context: TutorialContext): TutorialSchema { + const moduleName = 'sonicwall'; + const platforms = ['OSX', 'DEB', 'RPM', 'WINDOWS'] as const; + return { + id: 'sonicwallLogs', + name: i18n.translate('home.tutorials.sonicwallLogs.nameTitle', { + defaultMessage: 'Sonicwall FW logs', + }), + moduleName, + category: TutorialsCategory.SECURITY_SOLUTION, + shortDescription: i18n.translate('home.tutorials.sonicwallLogs.shortDescription', { + defaultMessage: 'Collect Sonicwall-FW logs over syslog or from a file.', + }), + longDescription: i18n.translate('home.tutorials.sonicwallLogs.longDescription', { + defaultMessage: + 'This is a module for receiving Sonicwall-FW logs over Syslog or a file. \ +[Learn more]({learnMoreLink}).', + values: { + learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-sonicwall.html', + }, + }), + euiIconType: '/plugins/home/assets/logos/sonicwall.svg', + artifacts: { + dashboards: [], + application: { + path: '/app/security', + label: i18n.translate('home.tutorials.radwareLogs.artifacts.dashboards.linkLabel', { + defaultMessage: 'Security App', + }), + }, + exportedFields: { + documentationUrl: '{config.docs.beats.filebeat}/exported-fields-sonicwall.html', + }, + }, + completionTimeMinutes: 10, + onPrem: onPremInstructions(moduleName, platforms, context), + elasticCloud: cloudInstructions(moduleName, platforms), + onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), + }; +} diff --git a/src/plugins/home/server/tutorials/sophos_logs/index.ts b/src/plugins/home/server/tutorials/sophos_logs/index.ts new file mode 100644 index 0000000000000..0c732fe954d3b --- /dev/null +++ b/src/plugins/home/server/tutorials/sophos_logs/index.ts @@ -0,0 +1,71 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { i18n } from '@kbn/i18n'; +import { TutorialsCategory } from '../../services/tutorials'; +import { + onPremInstructions, + cloudInstructions, + onPremCloudInstructions, +} from '../instructions/filebeat_instructions'; +import { + TutorialContext, + TutorialSchema, +} from '../../services/tutorials/lib/tutorials_registry_types'; + +export function sophosLogsSpecProvider(context: TutorialContext): TutorialSchema { + const moduleName = 'sophos'; + const platforms = ['OSX', 'DEB', 'RPM', 'WINDOWS'] as const; + return { + id: 'sophosLogs', + name: i18n.translate('home.tutorials.sophosLogs.nameTitle', { + defaultMessage: 'Sophos logs', + }), + moduleName, + category: TutorialsCategory.SECURITY_SOLUTION, + shortDescription: i18n.translate('home.tutorials.sophosLogs.shortDescription', { + defaultMessage: 'Collect Sophos XG SFOS logs over syslog.', + }), + longDescription: i18n.translate('home.tutorials.sophosLogs.longDescription', { + defaultMessage: + 'This is a module for Sophos Products, currently it supports XG SFOS logs sent in the syslog format. \ +[Learn more]({learnMoreLink}).', + values: { + learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-sophos.html', + }, + }), + euiIconType: '/plugins/home/assets/logos/sophos.svg', + artifacts: { + dashboards: [], + application: { + path: '/app/security', + label: i18n.translate('home.tutorials.sophosLogs.artifacts.dashboards.linkLabel', { + defaultMessage: 'Security App', + }), + }, + exportedFields: { + documentationUrl: '{config.docs.beats.filebeat}/exported-fields-sophos.html', + }, + }, + completionTimeMinutes: 10, + onPrem: onPremInstructions(moduleName, platforms, context), + elasticCloud: cloudInstructions(moduleName, platforms), + onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), + }; +} diff --git a/src/plugins/home/server/tutorials/squid_logs/index.ts b/src/plugins/home/server/tutorials/squid_logs/index.ts new file mode 100644 index 0000000000000..c697f728b8e0e --- /dev/null +++ b/src/plugins/home/server/tutorials/squid_logs/index.ts @@ -0,0 +1,71 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { i18n } from '@kbn/i18n'; +import { TutorialsCategory } from '../../services/tutorials'; +import { + onPremInstructions, + cloudInstructions, + onPremCloudInstructions, +} from '../instructions/filebeat_instructions'; +import { + TutorialContext, + TutorialSchema, +} from '../../services/tutorials/lib/tutorials_registry_types'; + +export function squidLogsSpecProvider(context: TutorialContext): TutorialSchema { + const moduleName = 'squid'; + const platforms = ['OSX', 'DEB', 'RPM', 'WINDOWS'] as const; + return { + id: 'squidLogs', + name: i18n.translate('home.tutorials.squidLogs.nameTitle', { + defaultMessage: 'Squid logs', + }), + moduleName, + category: TutorialsCategory.SECURITY_SOLUTION, + shortDescription: i18n.translate('home.tutorials.squidLogs.shortDescription', { + defaultMessage: 'Collect Squid logs over syslog or from a file.', + }), + longDescription: i18n.translate('home.tutorials.squidLogs.longDescription', { + defaultMessage: + 'This is a module for receiving Squid logs over Syslog or a file. \ +[Learn more]({learnMoreLink}).', + values: { + learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-squid.html', + }, + }), + euiIconType: 'logoLogging', + artifacts: { + dashboards: [], + application: { + path: '/app/security', + label: i18n.translate('home.tutorials.squidLogs.artifacts.dashboards.linkLabel', { + defaultMessage: 'Security App', + }), + }, + exportedFields: { + documentationUrl: '{config.docs.beats.filebeat}/exported-fields-squid.html', + }, + }, + completionTimeMinutes: 10, + onPrem: onPremInstructions(moduleName, platforms, context), + elasticCloud: cloudInstructions(moduleName, platforms), + onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), + }; +} diff --git a/src/plugins/home/server/tutorials/suricata_logs/index.ts b/src/plugins/home/server/tutorials/suricata_logs/index.ts index eec81b9496647..85ea3062f8b6d 100644 --- a/src/plugins/home/server/tutorials/suricata_logs/index.ts +++ b/src/plugins/home/server/tutorials/suricata_logs/index.ts @@ -40,13 +40,13 @@ export function suricataLogsSpecProvider(context: TutorialContext): TutorialSche moduleName, category: TutorialsCategory.SECURITY_SOLUTION, shortDescription: i18n.translate('home.tutorials.suricataLogs.shortDescription', { - defaultMessage: 'Collect the result logs created by Suricata IDS/IPS/NSM.', + defaultMessage: 'Collect Suricata IDS/IPS/NSM logs.', }), longDescription: i18n.translate('home.tutorials.suricataLogs.longDescription', { defaultMessage: - 'The `suricata` Filebeat module collects the logs from the \ -[Suricata Eve JSON output](https://suricata.readthedocs.io/en/latest/output/eve/eve-json-format.html). \ -[Learn more]({learnMoreLink}).', + 'This is a module to the Suricata IDS/IPS/NSM log. It parses logs that are \ + in the [Suricata Eve JSON format](https://suricata.readthedocs.io/en/latest/output/eve/eve-json-format.html). \ + [Learn more]({learnMoreLink}).', values: { learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-suricata.html', }, @@ -55,9 +55,9 @@ export function suricataLogsSpecProvider(context: TutorialContext): TutorialSche artifacts: { dashboards: [ { - id: '69f5ae20-eb02-11e7-8f04-51231daa5b05', + id: '78289c40-86da-11e8-b59d-21efb914e65c-ecs', linkLabel: i18n.translate('home.tutorials.suricataLogs.artifacts.dashboards.linkLabel', { - defaultMessage: 'Suricata logs dashboard', + defaultMessage: 'Suricata Events Overview', }), isOverview: true, }, diff --git a/src/plugins/home/server/tutorials/system_logs/index.ts b/src/plugins/home/server/tutorials/system_logs/index.ts index f39df25461a5f..f94098399938f 100644 --- a/src/plugins/home/server/tutorials/system_logs/index.ts +++ b/src/plugins/home/server/tutorials/system_logs/index.ts @@ -31,33 +31,32 @@ import { export function systemLogsSpecProvider(context: TutorialContext): TutorialSchema { const moduleName = 'system'; - const platforms = ['OSX', 'DEB', 'RPM'] as const; + const platforms = ['OSX', 'DEB', 'RPM', 'WINDOWS'] as const; return { id: 'systemLogs', name: i18n.translate('home.tutorials.systemLogs.nameTitle', { defaultMessage: 'System logs', }), moduleName, - category: TutorialsCategory.LOGGING, + category: TutorialsCategory.SECURITY_SOLUTION, shortDescription: i18n.translate('home.tutorials.systemLogs.shortDescription', { - defaultMessage: 'Collect and parse logs written by the local Syslog server.', + defaultMessage: 'Collect system logs of common Unix/Linux based distributions.', }), longDescription: i18n.translate('home.tutorials.systemLogs.longDescription', { defaultMessage: - 'The `system` Filebeat module collects and parses logs created by the system logging service of common \ -Unix/Linux based distributions. This module is not available on Windows. \ + 'The module collects and parses logs created by the system logging service of common Unix/Linux based distributions. \ [Learn more]({learnMoreLink}).', values: { learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-system.html', }, }), - euiIconType: '/plugins/home/assets/logos/system.svg', + euiIconType: 'logoLogging', artifacts: { dashboards: [ { id: 'Filebeat-syslog-dashboard-ecs', linkLabel: i18n.translate('home.tutorials.systemLogs.artifacts.dashboards.linkLabel', { - defaultMessage: 'System logs dashboard', + defaultMessage: 'System Syslog Dashboard', }), isOverview: true, }, @@ -67,7 +66,6 @@ Unix/Linux based distributions. This module is not available on Windows. \ }, }, completionTimeMinutes: 10, - previewImagePath: '/plugins/home/assets/system_logs/screenshot.png', onPrem: onPremInstructions(moduleName, platforms, context), elasticCloud: cloudInstructions(moduleName, platforms), onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), diff --git a/src/plugins/home/server/tutorials/tomcat_logs/index.ts b/src/plugins/home/server/tutorials/tomcat_logs/index.ts new file mode 100644 index 0000000000000..4b3c9f7357719 --- /dev/null +++ b/src/plugins/home/server/tutorials/tomcat_logs/index.ts @@ -0,0 +1,71 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { i18n } from '@kbn/i18n'; +import { TutorialsCategory } from '../../services/tutorials'; +import { + onPremInstructions, + cloudInstructions, + onPremCloudInstructions, +} from '../instructions/filebeat_instructions'; +import { + TutorialContext, + TutorialSchema, +} from '../../services/tutorials/lib/tutorials_registry_types'; + +export function tomcatLogsSpecProvider(context: TutorialContext): TutorialSchema { + const moduleName = 'tomcat'; + const platforms = ['OSX', 'DEB', 'RPM', 'WINDOWS'] as const; + return { + id: 'tomcatLogs', + name: i18n.translate('home.tutorials.tomcatLogs.nameTitle', { + defaultMessage: 'Tomcat logs', + }), + moduleName, + category: TutorialsCategory.SECURITY_SOLUTION, + shortDescription: i18n.translate('home.tutorials.tomcatLogs.shortDescription', { + defaultMessage: 'Collect Apache Tomcat logs over syslog or from a file.', + }), + longDescription: i18n.translate('home.tutorials.tomcatLogs.longDescription', { + defaultMessage: + 'This is a module for receiving Apache Tomcat logs over Syslog or a file. \ +[Learn more]({learnMoreLink}).', + values: { + learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-tomcat.html', + }, + }), + euiIconType: '/plugins/home/assets/logos/tomcat.svg', + artifacts: { + dashboards: [], + application: { + path: '/app/security', + label: i18n.translate('home.tutorials.tomcatLogs.artifacts.dashboards.linkLabel', { + defaultMessage: 'Security App', + }), + }, + exportedFields: { + documentationUrl: '{config.docs.beats.filebeat}/exported-fields-tomcat.html', + }, + }, + completionTimeMinutes: 10, + onPrem: onPremInstructions(moduleName, platforms, context), + elasticCloud: cloudInstructions(moduleName, platforms), + onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), + }; +} diff --git a/src/plugins/home/server/tutorials/traefik_logs/index.ts b/src/plugins/home/server/tutorials/traefik_logs/index.ts index 0a84dcb081883..8bcc806ad59a0 100644 --- a/src/plugins/home/server/tutorials/traefik_logs/index.ts +++ b/src/plugins/home/server/tutorials/traefik_logs/index.ts @@ -38,13 +38,13 @@ export function traefikLogsSpecProvider(context: TutorialContext): TutorialSchem defaultMessage: 'Traefik logs', }), moduleName, - category: TutorialsCategory.LOGGING, + category: TutorialsCategory.SECURITY_SOLUTION, shortDescription: i18n.translate('home.tutorials.traefikLogs.shortDescription', { - defaultMessage: 'Collect and parse access logs created by the Traefik Proxy.', + defaultMessage: 'Collect Traefik access logs.', }), longDescription: i18n.translate('home.tutorials.traefikLogs.longDescription', { defaultMessage: - 'The `traefik` Filebeat module parses access logs created by Traefik. \ + 'The module parses access logs created by [Træfik](https://traefik.io/). \ [Learn more]({learnMoreLink}).', values: { learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-traefik.html', @@ -56,7 +56,7 @@ export function traefikLogsSpecProvider(context: TutorialContext): TutorialSchem { id: 'Filebeat-Traefik-Dashboard-ecs', linkLabel: i18n.translate('home.tutorials.traefikLogs.artifacts.dashboards.linkLabel', { - defaultMessage: 'Traefik logs dashboard', + defaultMessage: 'Traefik Access Logs', }), isOverview: true, }, @@ -66,7 +66,6 @@ export function traefikLogsSpecProvider(context: TutorialContext): TutorialSchem }, }, completionTimeMinutes: 10, - previewImagePath: '/plugins/home/assets/traefik_logs/screenshot.png', onPrem: onPremInstructions(moduleName, platforms, context), elasticCloud: cloudInstructions(moduleName, platforms), onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), diff --git a/src/plugins/home/server/tutorials/zeek_logs/index.ts b/src/plugins/home/server/tutorials/zeek_logs/index.ts index e39dcd3409490..dbc07d27b4f8a 100644 --- a/src/plugins/home/server/tutorials/zeek_logs/index.ts +++ b/src/plugins/home/server/tutorials/zeek_logs/index.ts @@ -31,7 +31,7 @@ import { export function zeekLogsSpecProvider(context: TutorialContext): TutorialSchema { const moduleName = 'zeek'; - const platforms = ['OSX', 'DEB', 'RPM'] as const; + const platforms = ['OSX', 'DEB', 'RPM', 'WINDOWS'] as const; return { id: 'zeekLogs', name: i18n.translate('home.tutorials.zeekLogs.nameTitle', { @@ -40,13 +40,13 @@ export function zeekLogsSpecProvider(context: TutorialContext): TutorialSchema { moduleName, category: TutorialsCategory.SECURITY_SOLUTION, shortDescription: i18n.translate('home.tutorials.zeekLogs.shortDescription', { - defaultMessage: 'Collect the logs created by Zeek/Bro.', + defaultMessage: 'Collect Zeek network security monitoring logs.', }), longDescription: i18n.translate('home.tutorials.zeekLogs.longDescription', { defaultMessage: - 'The `zeek` Filebeat module collects the logs from \ -[Zeek](https://www.zeek.org//documentation/index.html). \ -[Learn more]({learnMoreLink}).', + 'This is a module for Zeek, which used to be called Bro. It parses logs \ + that are in the [Zeek JSON format](https://www.zeek.org/manual/release/logs/index.html). \ + [Learn more]({learnMoreLink}).', values: { learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-zeek.html', }, @@ -57,7 +57,7 @@ export function zeekLogsSpecProvider(context: TutorialContext): TutorialSchema { { id: '7cbb5410-3700-11e9-aa6d-ff445a78330c', linkLabel: i18n.translate('home.tutorials.zeekLogs.artifacts.dashboards.linkLabel', { - defaultMessage: 'Zeek logs dashboard', + defaultMessage: 'Zeek Overview', }), isOverview: true, }, diff --git a/src/plugins/home/server/tutorials/zscaler_logs/index.ts b/src/plugins/home/server/tutorials/zscaler_logs/index.ts new file mode 100644 index 0000000000000..800702fe7da96 --- /dev/null +++ b/src/plugins/home/server/tutorials/zscaler_logs/index.ts @@ -0,0 +1,71 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { i18n } from '@kbn/i18n'; +import { TutorialsCategory } from '../../services/tutorials'; +import { + onPremInstructions, + cloudInstructions, + onPremCloudInstructions, +} from '../instructions/filebeat_instructions'; +import { + TutorialContext, + TutorialSchema, +} from '../../services/tutorials/lib/tutorials_registry_types'; + +export function zscalerLogsSpecProvider(context: TutorialContext): TutorialSchema { + const moduleName = 'zscaler'; + const platforms = ['OSX', 'DEB', 'RPM', 'WINDOWS'] as const; + return { + id: 'zscalerLogs', + name: i18n.translate('home.tutorials.zscalerLogs.nameTitle', { + defaultMessage: 'Zscaler Logs', + }), + moduleName, + category: TutorialsCategory.SECURITY_SOLUTION, + shortDescription: i18n.translate('home.tutorials.zscalerLogs.shortDescription', { + defaultMessage: 'This is a module for receiving Zscaler NSS logs over Syslog or a file.', + }), + longDescription: i18n.translate('home.tutorials.zscalerLogs.longDescription', { + defaultMessage: + 'This is a module for receiving Zscaler NSS logs over Syslog or a file. \ +[Learn more]({learnMoreLink}).', + values: { + learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-zscaler.html', + }, + }), + euiIconType: '/plugins/home/assets/logos/zscaler.svg', + artifacts: { + dashboards: [], + application: { + path: '/app/security', + label: i18n.translate('home.tutorials.zscalerLogs.artifacts.dashboards.linkLabel', { + defaultMessage: 'Security App', + }), + }, + exportedFields: { + documentationUrl: '{config.docs.beats.filebeat}/exported-fields-zscaler.html', + }, + }, + completionTimeMinutes: 10, + onPrem: onPremInstructions(moduleName, platforms, context), + elasticCloud: cloudInstructions(moduleName, platforms), + onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), + }; +} diff --git a/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/step_time_field/__snapshots__/step_time_field.test.tsx.snap b/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/step_time_field/__snapshots__/step_time_field.test.tsx.snap index 6cc92d20cfdcc..544e3ba983122 100644 --- a/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/step_time_field/__snapshots__/step_time_field.test.tsx.snap +++ b/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/step_time_field/__snapshots__/step_time_field.test.tsx.snap @@ -27,7 +27,7 @@ exports[`StepTimeField should render "Custom index pattern ID already exists" wh /> ({ TimeField: 'TimeField' })); jest.mock('./components/advanced_options', () => ({ AdvancedOptions: 'AdvancedOptions' })); jest.mock('./components/action_buttons', () => ({ ActionButtons: 'ActionButtons' })); jest.mock('./../../lib', () => ({ - extractTimeFields: require.requireActual('./../../lib').extractTimeFields, + extractTimeFields: jest.requireActual('./../../lib').extractTimeFields, ensureMinimumTime: async (fields: IFieldType) => Promise.resolve(fields), })); @@ -48,11 +48,8 @@ const fields = [ }, ]; mockContext.data.indexPatterns = { - make: () => ({ - fieldsFetcher: { - fetchForWildcard: jest.fn().mockReturnValue(Promise.resolve(fields)), - }, - }), + create: () => ({}), + getFieldsForWildcard: jest.fn().mockReturnValue(Promise.resolve(fields)), } as any; describe('StepTimeField', () => { diff --git a/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/step_time_field/step_time_field.tsx b/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/step_time_field/step_time_field.tsx index 5d33a08557fed..cacabb6d7623b 100644 --- a/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/step_time_field/step_time_field.tsx +++ b/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/step_time_field/step_time_field.tsx @@ -108,12 +108,12 @@ export class StepTimeField extends Component { }); test('invokes the provided services when creating an index pattern', async () => { - const create = jest.fn().mockImplementation(() => 'id'); + const newIndexPatternAndSave = jest.fn().mockImplementation(async () => { + return indexPattern; + }); const clear = jest.fn(); mockContext.data.indexPatterns.clearCache = clear; const indexPattern = ({ @@ -151,11 +153,10 @@ describe('CreateIndexPatternWizard', () => { title: 'my-fake-index-pattern', timeFieldName: 'timestamp', fields: [], - create, + _fetchFields: jest.fn(), } as unknown) as IndexPattern; - mockContext.data.indexPatterns.make = async () => { - return indexPattern; - }; + mockContext.data.indexPatterns.createAndSave = newIndexPatternAndSave; + mockContext.data.indexPatterns.setDefault = jest.fn(); const component = createComponentWithContext( CreateIndexPatternWizard, @@ -165,9 +166,8 @@ describe('CreateIndexPatternWizard', () => { component.setState({ indexPattern: 'foo' }); await (component.instance() as CreateIndexPatternWizard).createIndexPattern(undefined, 'id'); - expect(mockContext.uiSettings.get).toBeCalled(); - expect(create).toBeCalled(); - expect(clear).toBeCalledWith('id'); - expect(routeComponentPropsMock.history.push).toBeCalledWith(`/patterns/id`); + expect(newIndexPatternAndSave).toBeCalled(); + expect(clear).toBeCalledWith('1'); + expect(routeComponentPropsMock.history.push).toBeCalledWith(`/patterns/1`); }); }); diff --git a/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/create_index_pattern_wizard.tsx b/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/create_index_pattern_wizard.tsx index a789ebbfadbce..aa97c21d766b9 100644 --- a/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/create_index_pattern_wizard.tsx +++ b/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/create_index_pattern_wizard.tsx @@ -40,6 +40,7 @@ import { ensureMinimumTime, getIndices } from './lib'; import { IndexPatternCreationConfig } from '../..'; import { IndexPatternManagmentContextValue } from '../../types'; import { MatchedItem } from './types'; +import { DuplicateIndexPatternError, IndexPattern } from '../../../../data/public'; interface CreateIndexPatternWizardState { step: number; @@ -156,50 +157,50 @@ export class CreateIndexPatternWizard extends Component< }; createIndexPattern = async (timeFieldName: string | undefined, indexPatternId: string) => { + let emptyPattern: IndexPattern; const { history } = this.props; const { indexPattern } = this.state; - const emptyPattern = await this.context.services.data.indexPatterns.make(); - - Object.assign(emptyPattern, { - id: indexPatternId, - title: indexPattern, - timeFieldName, - ...this.state.indexPatternCreationType.getIndexPatternMappings(), - }); - - const createdId = await emptyPattern.create(); - if (!createdId) { - const confirmMessage = i18n.translate( - 'indexPatternManagement.indexPattern.titleExistsLabel', - { - values: { title: emptyPattern.title }, - defaultMessage: "An index pattern with the title '{title}' already exists.", - } - ); - - const isConfirmed = await this.context.services.overlays.openConfirm(confirmMessage, { - confirmButtonText: i18n.translate( - 'indexPatternManagement.indexPattern.goToPatternButtonLabel', + try { + emptyPattern = await this.context.services.data.indexPatterns.createAndSave({ + id: indexPatternId, + title: indexPattern, + timeFieldName, + ...this.state.indexPatternCreationType.getIndexPatternMappings(), + }); + } catch (err) { + if (err instanceof DuplicateIndexPatternError) { + const confirmMessage = i18n.translate( + 'indexPatternManagement.indexPattern.titleExistsLabel', { - defaultMessage: 'Go to existing pattern', + values: { title: emptyPattern!.title }, + defaultMessage: "An index pattern with the title '{title}' already exists.", } - ), - }); + ); + + const isConfirmed = await this.context.services.overlays.openConfirm(confirmMessage, { + confirmButtonText: i18n.translate( + 'indexPatternManagement.indexPattern.goToPatternButtonLabel', + { + defaultMessage: 'Go to existing pattern', + } + ), + }); - if (isConfirmed) { - return history.push(`/patterns/${indexPatternId}`); + if (isConfirmed) { + return history.push(`/patterns/${indexPatternId}`); + } else { + return; + } } else { - return; + throw err; } } - if (!this.context.services.uiSettings.get('defaultIndex')) { - await this.context.services.uiSettings.set('defaultIndex', createdId); - } + await this.context.services.data.indexPatterns.setDefault(emptyPattern.id as string); - this.context.services.data.indexPatterns.clearCache(createdId); - history.push(`/patterns/${createdId}`); + this.context.services.data.indexPatterns.clearCache(emptyPattern.id as string); + history.push(`/patterns/${emptyPattern.id}`); }; goToTimeFieldStep = (indexPattern: string, selectedTimeField?: string) => { diff --git a/src/plugins/index_pattern_management/public/components/edit_index_pattern/create_edit_field/create_edit_field.tsx b/src/plugins/index_pattern_management/public/components/edit_index_pattern/create_edit_field/create_edit_field.tsx index 13be9ca6c9c25..08edf42df60d8 100644 --- a/src/plugins/index_pattern_management/public/components/edit_index_pattern/create_edit_field/create_edit_field.tsx +++ b/src/plugins/index_pattern_management/public/components/edit_index_pattern/create_edit_field/create_edit_field.tsx @@ -96,7 +96,7 @@ export const CreateEditField = withRouter( indexPattern={indexPattern} spec={spec} services={{ - saveIndexPattern: data.indexPatterns.save.bind(data.indexPatterns), + saveIndexPattern: data.indexPatterns.updateSavedObject.bind(data.indexPatterns), redirectAway, }} /> diff --git a/src/plugins/index_pattern_management/public/components/edit_index_pattern/create_edit_field/create_edit_field_container.tsx b/src/plugins/index_pattern_management/public/components/edit_index_pattern/create_edit_field/create_edit_field_container.tsx index 39c0add40e9ad..076cda484d808 100644 --- a/src/plugins/index_pattern_management/public/components/edit_index_pattern/create_edit_field/create_edit_field_container.tsx +++ b/src/plugins/index_pattern_management/public/components/edit_index_pattern/create_edit_field/create_edit_field_container.tsx @@ -26,31 +26,31 @@ import { useKibana } from '../../../../../../plugins/kibana_react/public'; import { IndexPatternManagmentContext } from '../../../types'; import { CreateEditField } from './create_edit_field'; -export type CreateEditFieldContainerProps = RouteComponentProps<{ id: string; fieldName: string }>; +export type CreateEditFieldContainerProps = RouteComponentProps<{ id: string; fieldName?: string }>; const CreateEditFieldCont: React.FC = ({ ...props }) => { const { setBreadcrumbs, data } = useKibana().services; const [indexPattern, setIndexPattern] = useState(); + const fieldName = + props.match.params.fieldName && decodeURIComponent(props.match.params.fieldName); useEffect(() => { data.indexPatterns.get(props.match.params.id).then((ip: IndexPattern) => { setIndexPattern(ip); if (ip) { setBreadcrumbs( - props.match.params.fieldName - ? getEditFieldBreadcrumbs(ip, props.match.params.fieldName) - : getCreateFieldBreadcrumbs(ip) + fieldName ? getEditFieldBreadcrumbs(ip, fieldName) : getCreateFieldBreadcrumbs(ip) ); } }); - }, [props.match.params.id, props.match.params.fieldName, setBreadcrumbs, data.indexPatterns]); + }, [props.match.params.id, fieldName, setBreadcrumbs, data.indexPatterns]); if (indexPattern) { return ( ); } else { diff --git a/src/plugins/index_pattern_management/public/components/edit_index_pattern/edit_index_pattern.tsx b/src/plugins/index_pattern_management/public/components/edit_index_pattern/edit_index_pattern.tsx index d09836019b0bc..67a20c428040f 100644 --- a/src/plugins/index_pattern_management/public/components/edit_index_pattern/edit_index_pattern.tsx +++ b/src/plugins/index_pattern_management/public/components/edit_index_pattern/edit_index_pattern.tsx @@ -121,7 +121,8 @@ export const EditIndexPattern = withRouter( const refreshFields = () => { overlays.openConfirm(confirmMessage, confirmModalOptionsRefresh).then(async (isConfirmed) => { if (isConfirmed) { - await indexPattern.refreshFields(); + await data.indexPatterns.refreshFields(indexPattern); + await data.indexPatterns.updateSavedObject(indexPattern); setFields(indexPattern.getNonScriptedFields()); } }); @@ -236,7 +237,7 @@ export const EditIndexPattern = withRouter( ({ @@ -43,7 +43,7 @@ const helpers = { const indexPattern = ({ getNonScriptedFields: () => fields, -} as unknown) as IIndexPattern; +} as unknown) as IndexPattern; const mockFieldToIndexPatternField = (spec: Record) => { return new IndexPatternField( diff --git a/src/plugins/index_pattern_management/public/components/edit_index_pattern/indexed_fields_table/indexed_fields_table.tsx b/src/plugins/index_pattern_management/public/components/edit_index_pattern/indexed_fields_table/indexed_fields_table.tsx index 23977aac7fa7a..7be420e2af50d 100644 --- a/src/plugins/index_pattern_management/public/components/edit_index_pattern/indexed_fields_table/indexed_fields_table.tsx +++ b/src/plugins/index_pattern_management/public/components/edit_index_pattern/indexed_fields_table/indexed_fields_table.tsx @@ -19,23 +19,19 @@ import React, { Component } from 'react'; import { createSelector } from 'reselect'; -import { - IndexPatternField, - IIndexPattern, - IFieldType, -} from '../../../../../../plugins/data/public'; +import { IndexPatternField, IndexPattern, IFieldType } from '../../../../../../plugins/data/public'; import { Table } from './components/table'; import { getFieldFormat } from './lib'; import { IndexedFieldItem } from './types'; interface IndexedFieldsTableProps { fields: IndexPatternField[]; - indexPattern: IIndexPattern; + indexPattern: IndexPattern; fieldFilter?: string; indexedFieldTypeFilter?: string; helpers: { redirectToRoute: (obj: any) => void; - getFieldInfo: (indexPattern: IIndexPattern, field: IFieldType) => string[]; + getFieldInfo: (indexPattern: IndexPattern, field: IFieldType) => string[]; }; fieldWildcardMatcher: (filters: any[]) => (val: any) => boolean; } diff --git a/src/plugins/index_pattern_management/public/components/edit_index_pattern/scripted_fields_table/scripted_fields_table.tsx b/src/plugins/index_pattern_management/public/components/edit_index_pattern/scripted_fields_table/scripted_fields_table.tsx index 08cc90faf75fa..c7ea20c700086 100644 --- a/src/plugins/index_pattern_management/public/components/edit_index_pattern/scripted_fields_table/scripted_fields_table.tsx +++ b/src/plugins/index_pattern_management/public/components/edit_index_pattern/scripted_fields_table/scripted_fields_table.tsx @@ -39,7 +39,7 @@ interface ScriptedFieldsTableProps { }; onRemoveField?: () => void; painlessDocLink: string; - saveIndexPattern: DataPublicPluginStart['indexPatterns']['save']; + saveIndexPattern: DataPublicPluginStart['indexPatterns']['updateSavedObject']; } interface ScriptedFieldsTableState { diff --git a/src/plugins/index_pattern_management/public/components/edit_index_pattern/source_filters_table/components/table/table.test.tsx b/src/plugins/index_pattern_management/public/components/edit_index_pattern/source_filters_table/components/table/table.test.tsx index e43ee2e55eeca..2d3a61b42c3a4 100644 --- a/src/plugins/index_pattern_management/public/components/edit_index_pattern/source_filters_table/components/table/table.test.tsx +++ b/src/plugins/index_pattern_management/public/components/edit_index_pattern/source_filters_table/components/table/table.test.tsx @@ -22,13 +22,13 @@ import { shallow, ShallowWrapper } from 'enzyme'; import { Table, TableProps, TableState } from './table'; import { EuiTableFieldDataColumnType, keys } from '@elastic/eui'; -import { IIndexPattern } from 'src/plugins/data/public'; +import { IndexPattern } from 'src/plugins/data/public'; import { SourceFiltersTableFilter } from '../../types'; -const indexPattern = {} as IIndexPattern; +const indexPattern = {} as IndexPattern; const items: SourceFiltersTableFilter[] = [{ value: 'tim*', clientId: '' }]; -const getIndexPatternMock = (mockedFields: any = {}) => ({ ...mockedFields } as IIndexPattern); +const getIndexPatternMock = (mockedFields: any = {}) => ({ ...mockedFields } as IndexPattern); const getTableColumnRender = ( component: ShallowWrapper, diff --git a/src/plugins/index_pattern_management/public/components/edit_index_pattern/source_filters_table/components/table/table.tsx b/src/plugins/index_pattern_management/public/components/edit_index_pattern/source_filters_table/components/table/table.tsx index f73d756f28116..c5b09961f25fc 100644 --- a/src/plugins/index_pattern_management/public/components/edit_index_pattern/source_filters_table/components/table/table.tsx +++ b/src/plugins/index_pattern_management/public/components/edit_index_pattern/source_filters_table/components/table/table.tsx @@ -30,7 +30,7 @@ import { import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; -import { IIndexPattern } from 'src/plugins/data/public'; +import { IndexPattern } from 'src/plugins/data/public'; import { SourceFiltersTableFilter } from '../../types'; const filterHeader = i18n.translate( @@ -80,7 +80,7 @@ const cancelAria = i18n.translate( ); export interface TableProps { - indexPattern: IIndexPattern; + indexPattern: IndexPattern; items: SourceFiltersTableFilter[]; deleteFilter: Function; fieldWildcardMatcher: Function; diff --git a/src/plugins/index_pattern_management/public/components/edit_index_pattern/source_filters_table/source_filters_table.tsx b/src/plugins/index_pattern_management/public/components/edit_index_pattern/source_filters_table/source_filters_table.tsx index b00648f124716..cd311db513c09 100644 --- a/src/plugins/index_pattern_management/public/components/edit_index_pattern/source_filters_table/source_filters_table.tsx +++ b/src/plugins/index_pattern_management/public/components/edit_index_pattern/source_filters_table/source_filters_table.tsx @@ -30,7 +30,7 @@ export interface SourceFiltersTableProps { filterFilter: string; fieldWildcardMatcher: Function; onAddOrRemoveFilter?: Function; - saveIndexPattern: DataPublicPluginStart['indexPatterns']['save']; + saveIndexPattern: DataPublicPluginStart['indexPatterns']['updateSavedObject']; } export interface SourceFiltersTableState { diff --git a/src/plugins/index_pattern_management/public/components/edit_index_pattern/tabs/tabs.tsx b/src/plugins/index_pattern_management/public/components/edit_index_pattern/tabs/tabs.tsx index 101399ef02b73..5c29dfafd3c07 100644 --- a/src/plugins/index_pattern_management/public/components/edit_index_pattern/tabs/tabs.tsx +++ b/src/plugins/index_pattern_management/public/components/edit_index_pattern/tabs/tabs.tsx @@ -49,7 +49,7 @@ import { getTabs, getPath, convertToEuiSelectOption } from './utils'; interface TabsProps extends Pick { indexPattern: IndexPattern; fields: IndexPatternField[]; - saveIndexPattern: DataPublicPluginStart['indexPatterns']['save']; + saveIndexPattern: DataPublicPluginStart['indexPatterns']['updateSavedObject']; } const searchAriaLabel = i18n.translate( diff --git a/src/plugins/index_pattern_management/public/components/edit_index_pattern/tabs/utils.test.ts b/src/plugins/index_pattern_management/public/components/edit_index_pattern/tabs/utils.test.ts new file mode 100644 index 0000000000000..0e3ee27476fcc --- /dev/null +++ b/src/plugins/index_pattern_management/public/components/edit_index_pattern/tabs/utils.test.ts @@ -0,0 +1,30 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { getPath } from './utils'; +import { IndexPatternField, IndexPattern } from '../../../../../data/public'; + +test('getPath() should encode "fieldName"', () => { + expect( + getPath( + ({ name: 'Memory: Allocated Bytes/sec' } as unknown) as IndexPatternField, + ({ id: 'id' } as unknown) as IndexPattern + ) + ).toMatchInlineSnapshot(`"/patterns/id/field/Memory%3A%20Allocated%20Bytes%2Fsec"`); +}); diff --git a/src/plugins/index_pattern_management/public/components/edit_index_pattern/tabs/utils.ts b/src/plugins/index_pattern_management/public/components/edit_index_pattern/tabs/utils.ts index 91c5cc1afdb49..a94ed60b7aed5 100644 --- a/src/plugins/index_pattern_management/public/components/edit_index_pattern/tabs/utils.ts +++ b/src/plugins/index_pattern_management/public/components/edit_index_pattern/tabs/utils.ts @@ -117,7 +117,7 @@ export function getTabs( } export function getPath(field: IndexPatternField, indexPattern: IndexPattern) { - return `/patterns/${indexPattern?.id}/field/${field.name}`; + return `/patterns/${indexPattern?.id}/field/${encodeURIComponent(field.name)}`; } const allTypesDropDown = i18n.translate( diff --git a/src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/url/__snapshots__/label_template_flyout.test.tsx.snap b/src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/url/__snapshots__/label_template_flyout.test.tsx.snap index 69b192a81d097..38f630358d064 100644 --- a/src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/url/__snapshots__/label_template_flyout.test.tsx.snap +++ b/src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/url/__snapshots__/label_template_flyout.test.tsx.snap @@ -4,6 +4,7 @@ exports[`LabelTemplateFlyout should not render if not visible 1`] = `""`; exports[`LabelTemplateFlyout should render normally 1`] = ` diff --git a/src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/url/__snapshots__/url.test.tsx.snap b/src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/url/__snapshots__/url.test.tsx.snap index f862d0ebe8477..13be0353e1640 100644 --- a/src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/url/__snapshots__/url.test.tsx.snap +++ b/src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/url/__snapshots__/url.test.tsx.snap @@ -1,544 +1,431 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`UrlFormatEditor should render label template help 1`] = ` - - - - - } - labelType="label" +exports[`UrlFormatEditor should render normally 1`] = ` +
+
- - - + - + Type + + +
+
+
- - - } - isInvalid={false} - label={ - - } - labelType="label" - > - - - - -`; - -exports[`UrlFormatEditor should render normally 1`] = ` - - - - - } - labelType="label" +
+ +
+ + +
+
+
+
+
- - - + - + Open in a new tab + + +
+
+
- - - } - isInvalid={false} - label={ - - } - labelType="label" + + + + Off + + +
+
+
+
- - - - -`; - -exports[`UrlFormatEditor should render url template help 1`] = ` - - - - - } - labelType="label" - > - - - + - + URL template + + +
+
+
- - - } - isInvalid={false} - label={ - - } - labelType="label" - > - - - - -`; - -exports[`UrlFormatEditor should render width and height fields if image 1`] = ` - - - - - } - labelType="label" - > - - - + +
+
+
- - - } - isInvalid={false} - label={ - - } - labelType="label" + +
+

{ + // (undocumented) + id: string; +} + +// Warning: (ae-forgotten-export) The symbol "EmbeddableServerPlugin" needs to be exported by the entry point index.d.ts +// Warning: (ae-missing-release-tag) "plugin" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export const plugin: () => EmbeddableServerPlugin; + + +// (No @packageDocumentation comment for this package) + +``` diff --git a/src/plugins/es_ui_shared/__packages_do_not_import__/monaco/index.ts b/src/plugins/es_ui_shared/__packages_do_not_import__/monaco/index.ts deleted file mode 100644 index a9c6ea1e01d54..0000000000000 --- a/src/plugins/es_ui_shared/__packages_do_not_import__/monaco/index.ts +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -export { useXJsonMode } from './use_xjson_mode'; diff --git a/src/plugins/es_ui_shared/__packages_do_not_import__/monaco/use_xjson_mode.ts b/src/plugins/es_ui_shared/__packages_do_not_import__/monaco/use_xjson_mode.ts deleted file mode 100644 index b783045492f05..0000000000000 --- a/src/plugins/es_ui_shared/__packages_do_not_import__/monaco/use_xjson_mode.ts +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { XJsonLang } from '@kbn/monaco'; -import { useXJsonMode as useBaseXJsonMode } from '../xjson'; - -interface ReturnValue extends ReturnType { - XJsonLang: typeof XJsonLang; -} - -export const useXJsonMode = (json: Parameters[0]): ReturnValue => { - return { - ...useBaseXJsonMode(json), - XJsonLang, - }; -}; diff --git a/src/plugins/es_ui_shared/__packages_do_not_import__/xjson/index.ts b/src/plugins/es_ui_shared/__packages_do_not_import__/xjson/index.ts index a9c6ea1e01d54..adbdbe97c4a07 100644 --- a/src/plugins/es_ui_shared/__packages_do_not_import__/xjson/index.ts +++ b/src/plugins/es_ui_shared/__packages_do_not_import__/xjson/index.ts @@ -18,3 +18,5 @@ */ export { useXJsonMode } from './use_xjson_mode'; + +export { collapseLiteralStrings, expandLiteralStrings } from './json_xjson_translation_tools'; diff --git a/src/plugins/es_ui_shared/public/console_lang/lib/json_xjson_translation_tools/__tests__/json_xjson_translation_tools.test.ts b/src/plugins/es_ui_shared/__packages_do_not_import__/xjson/json_xjson_translation_tools/__tests__/json_xjson_translation_tools.test.ts similarity index 100% rename from src/plugins/es_ui_shared/public/console_lang/lib/json_xjson_translation_tools/__tests__/json_xjson_translation_tools.test.ts rename to src/plugins/es_ui_shared/__packages_do_not_import__/xjson/json_xjson_translation_tools/__tests__/json_xjson_translation_tools.test.ts diff --git a/src/plugins/es_ui_shared/public/console_lang/lib/json_xjson_translation_tools/__tests__/utils_string_collapsing.txt b/src/plugins/es_ui_shared/__packages_do_not_import__/xjson/json_xjson_translation_tools/__tests__/utils_string_collapsing.txt similarity index 100% rename from src/plugins/es_ui_shared/public/console_lang/lib/json_xjson_translation_tools/__tests__/utils_string_collapsing.txt rename to src/plugins/es_ui_shared/__packages_do_not_import__/xjson/json_xjson_translation_tools/__tests__/utils_string_collapsing.txt diff --git a/src/plugins/es_ui_shared/public/console_lang/lib/json_xjson_translation_tools/__tests__/utils_string_expanding.txt b/src/plugins/es_ui_shared/__packages_do_not_import__/xjson/json_xjson_translation_tools/__tests__/utils_string_expanding.txt similarity index 100% rename from src/plugins/es_ui_shared/public/console_lang/lib/json_xjson_translation_tools/__tests__/utils_string_expanding.txt rename to src/plugins/es_ui_shared/__packages_do_not_import__/xjson/json_xjson_translation_tools/__tests__/utils_string_expanding.txt diff --git a/src/plugins/es_ui_shared/public/console_lang/lib/json_xjson_translation_tools/index.ts b/src/plugins/es_ui_shared/__packages_do_not_import__/xjson/json_xjson_translation_tools/index.ts similarity index 100% rename from src/plugins/es_ui_shared/public/console_lang/lib/json_xjson_translation_tools/index.ts rename to src/plugins/es_ui_shared/__packages_do_not_import__/xjson/json_xjson_translation_tools/index.ts diff --git a/src/plugins/es_ui_shared/public/console_lang/lib/json_xjson_translation_tools/parser.ts b/src/plugins/es_ui_shared/__packages_do_not_import__/xjson/json_xjson_translation_tools/parser.ts similarity index 100% rename from src/plugins/es_ui_shared/public/console_lang/lib/json_xjson_translation_tools/parser.ts rename to src/plugins/es_ui_shared/__packages_do_not_import__/xjson/json_xjson_translation_tools/parser.ts diff --git a/src/plugins/es_ui_shared/__packages_do_not_import__/xjson/use_xjson_mode.ts b/src/plugins/es_ui_shared/__packages_do_not_import__/xjson/use_xjson_mode.ts index 7dcc7c9ed83bc..1d4c473ed14e4 100644 --- a/src/plugins/es_ui_shared/__packages_do_not_import__/xjson/use_xjson_mode.ts +++ b/src/plugins/es_ui_shared/__packages_do_not_import__/xjson/use_xjson_mode.ts @@ -18,7 +18,8 @@ */ import { useState, Dispatch } from 'react'; -import { collapseLiteralStrings, expandLiteralStrings } from '../../public'; + +import { collapseLiteralStrings, expandLiteralStrings } from './json_xjson_translation_tools'; interface ReturnValue { xJson: string; diff --git a/src/plugins/es_ui_shared/kibana.json b/src/plugins/es_ui_shared/kibana.json index eab7355d66f09..d442bfb93d5af 100644 --- a/src/plugins/es_ui_shared/kibana.json +++ b/src/plugins/es_ui_shared/kibana.json @@ -4,7 +4,6 @@ "ui": true, "server": true, "extraPublicDirs": [ - "static/ace_x_json/hooks", "static/validators/string", "static/forms/hook_form_lib", "static/forms/helpers", diff --git a/src/plugins/es_ui_shared/public/console_lang/index.ts b/src/plugins/es_ui_shared/public/console_lang/index.ts deleted file mode 100644 index 7d83191569622..0000000000000 --- a/src/plugins/es_ui_shared/public/console_lang/index.ts +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -// Lib is intentionally not included in this barrel export file to separate worker logic -// from being imported with pure functions - -export { - ElasticsearchSqlHighlightRules, - ScriptHighlightRules, - XJsonHighlightRules, - addXJsonToRules, - XJsonMode, - installXJsonMode, -} from './ace/modes'; - -export { expandLiteralStrings, collapseLiteralStrings } from './lib'; diff --git a/src/plugins/es_ui_shared/public/console_lang/lib/index.ts b/src/plugins/es_ui_shared/public/console_lang/lib/index.ts deleted file mode 100644 index bf7f0290d4158..0000000000000 --- a/src/plugins/es_ui_shared/public/console_lang/lib/index.ts +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -export { collapseLiteralStrings, expandLiteralStrings } from './json_xjson_translation_tools'; diff --git a/src/plugins/es_ui_shared/public/index.ts b/src/plugins/es_ui_shared/public/index.ts index 5a1c13658604a..94b084e7d3f20 100644 --- a/src/plugins/es_ui_shared/public/index.ts +++ b/src/plugins/es_ui_shared/public/index.ts @@ -22,9 +22,9 @@ * In the future, each top level folder should be exported like that to avoid naming collision */ import * as Forms from './forms'; -import * as Monaco from './monaco'; import * as ace from './ace'; import * as GlobalFlyout from './global_flyout'; +import * as XJson from './xjson'; export { JsonEditor, OnJsonEditorUpdateHandler, JsonEditorState } from './components/json_editor'; @@ -43,17 +43,6 @@ export { export { indices } from './indices'; -export { - installXJsonMode, - XJsonMode, - ElasticsearchSqlHighlightRules, - addXJsonToRules, - ScriptHighlightRules, - XJsonHighlightRules, - collapseLiteralStrings, - expandLiteralStrings, -} from './console_lang'; - export { AuthorizationContext, AuthorizationProvider, @@ -66,7 +55,7 @@ export { useAuthorizationContext, } from './authorization'; -export { Monaco, Forms, ace, GlobalFlyout }; +export { Forms, ace, GlobalFlyout, XJson }; export { extractQueryParams } from './url'; diff --git a/src/plugins/es_ui_shared/public/monaco/index.ts b/src/plugins/es_ui_shared/public/monaco/index.ts deleted file mode 100644 index 23ba93e913234..0000000000000 --- a/src/plugins/es_ui_shared/public/monaco/index.ts +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -export { useXJsonMode } from '../../__packages_do_not_import__/monaco'; diff --git a/src/plugins/es_ui_shared/public/xjson/index.ts b/src/plugins/es_ui_shared/public/xjson/index.ts new file mode 100644 index 0000000000000..d505cbe0c6348 --- /dev/null +++ b/src/plugins/es_ui_shared/public/xjson/index.ts @@ -0,0 +1,20 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export * from '../../__packages_do_not_import__/xjson'; diff --git a/src/plugins/es_ui_shared/static/ace_x_json/hooks/index.ts b/src/plugins/es_ui_shared/static/ace_x_json/hooks/index.ts deleted file mode 100644 index 1d2c33a9f0f47..0000000000000 --- a/src/plugins/es_ui_shared/static/ace_x_json/hooks/index.ts +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -export { useXJsonMode } from './use_x_json'; diff --git a/src/plugins/es_ui_shared/static/ace_x_json/hooks/use_x_json.ts b/src/plugins/es_ui_shared/static/ace_x_json/hooks/use_x_json.ts deleted file mode 100644 index 3a093ac6869d0..0000000000000 --- a/src/plugins/es_ui_shared/static/ace_x_json/hooks/use_x_json.ts +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -import { XJsonMode } from '../../../public'; -import { useXJsonMode as useBaseXJsonMode } from '../../../__packages_do_not_import__/xjson'; - -const xJsonMode = new XJsonMode(); - -interface ReturnValue extends ReturnType { - xJsonMode: typeof xJsonMode; -} - -export const useXJsonMode = (json: Parameters[0]): ReturnValue => { - return { - ...useBaseXJsonMode(json), - xJsonMode, - }; -}; diff --git a/src/plugins/es_ui_shared/static/forms/components/field.tsx b/src/plugins/es_ui_shared/static/forms/components/field.tsx index 78702e902ecf6..217a811168814 100644 --- a/src/plugins/es_ui_shared/static/forms/components/field.tsx +++ b/src/plugins/es_ui_shared/static/forms/components/field.tsx @@ -38,6 +38,7 @@ import { SelectField, SuperSelectField, ToggleField, + JsonEditorField, } from './fields'; const mapTypeToFieldComponent: { [key: string]: ComponentType } = { @@ -52,6 +53,7 @@ const mapTypeToFieldComponent: { [key: string]: ComponentType } = { [FIELD_TYPES.SELECT]: SelectField, [FIELD_TYPES.SUPER_SELECT]: SuperSelectField, [FIELD_TYPES.TOGGLE]: ToggleField, + [FIELD_TYPES.JSON]: JsonEditorField, }; export const Field = (props: Props) => { diff --git a/src/plugins/es_ui_shared/static/forms/components/fields/json_editor_field.tsx b/src/plugins/es_ui_shared/static/forms/components/fields/json_editor_field.tsx index fd57e098cf806..e2d80825f397e 100644 --- a/src/plugins/es_ui_shared/static/forms/components/fields/json_editor_field.tsx +++ b/src/plugins/es_ui_shared/static/forms/components/fields/json_editor_field.tsx @@ -23,7 +23,7 @@ import { JsonEditor, OnJsonEditorUpdateHandler } from '../../../../public'; import { FieldHook, getFieldValidityAndErrorMessage } from '../../hook_form_lib'; interface Props { - field: FieldHook; + field: FieldHook; euiCodeEditorProps?: { [key: string]: any }; [key: string]: any; } @@ -44,7 +44,7 @@ export const JsonEditorField = ({ field, ...rest }: Props) => { ['validations']; - children: (args: { - items: ArrayItem[]; - error: string | null; - addItem: () => void; - removeItem: (id: number) => void; - moveItem: (sourceIdx: number, destinationIdx: number) => void; - form: FormHook; - }) => JSX.Element; + validations?: FieldConfig['validations']; + children: (formFieldArray: FormArrayField) => JSX.Element; } export interface ArrayItem { @@ -45,6 +38,15 @@ export interface ArrayItem { isNew: boolean; } +export interface FormArrayField { + items: ArrayItem[]; + error: string | null; + addItem: () => void; + removeItem: (id: number) => void; + moveItem: (sourceIdx: number, destinationIdx: number) => void; + form: FormHook; +} + /** * Use UseArray to dynamically add fields to your form. * @@ -71,7 +73,7 @@ export const UseArray = ({ const uniqueId = useRef(0); const form = useFormContext(); - const { getFieldDefaultValue } = form; + const { __getFieldDefaultValue } = form; const getNewItemAtIndex = useCallback( (index: number): ArrayItem => ({ @@ -84,7 +86,7 @@ export const UseArray = ({ const fieldDefaultValue = useMemo(() => { const defaultValues = readDefaultValueOnForm - ? (getFieldDefaultValue(path) as any[]) + ? (__getFieldDefaultValue(path) as any[]) : undefined; const getInitialItemsFromValues = (values: any[]): ArrayItem[] => @@ -97,17 +99,23 @@ export const UseArray = ({ return defaultValues ? getInitialItemsFromValues(defaultValues) : new Array(initialNumberOfItems).fill('').map((_, i) => getNewItemAtIndex(i)); - }, [path, initialNumberOfItems, readDefaultValueOnForm, getFieldDefaultValue, getNewItemAtIndex]); + }, [ + path, + initialNumberOfItems, + readDefaultValueOnForm, + __getFieldDefaultValue, + getNewItemAtIndex, + ]); // Create a new hook field with the "hasValue" set to false so we don't use its value to build the final form data. // Apart from that the field behaves like a normal field and is hooked into the form validation lifecycle. - const fieldConfigBase: FieldConfig & InternalFieldConfig = { + const fieldConfigBase: FieldConfig & InternalFieldConfig = { defaultValue: fieldDefaultValue, - errorDisplayDelay: 0, + valueChangeDebounceTime: 0, isIncludedInOutput: false, }; - const fieldConfig: FieldConfig & InternalFieldConfig = validations + const fieldConfig: FieldConfig & InternalFieldConfig = validations ? { validations, ...fieldConfigBase } : fieldConfigBase; diff --git a/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/use_field.tsx b/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/use_field.tsx index 6b913f246abbb..a3a0984d4a736 100644 --- a/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/use_field.tsx +++ b/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/use_field.tsx @@ -19,23 +19,23 @@ import React, { FunctionComponent } from 'react'; -import { FieldHook, FieldConfig } from '../types'; +import { FieldHook, FieldConfig, FormData } from '../types'; import { useField } from '../hooks'; import { useFormContext } from '../form_context'; -export interface Props { +export interface Props { path: string; - config?: FieldConfig; + config?: FieldConfig; defaultValue?: T; - component?: FunctionComponent | 'input'; + component?: FunctionComponent; componentProps?: Record; readDefaultValueOnForm?: boolean; - onChange?: (value: T) => void; - children?: (field: FieldHook) => JSX.Element; + onChange?: (value: I) => void; + children?: (field: FieldHook) => JSX.Element; [key: string]: any; } -function UseFieldComp(props: Props) { +function UseFieldComp(props: Props) { const { path, config, @@ -48,18 +48,16 @@ function UseFieldComp(props: Props) { ...rest } = props; - const form = useFormContext(); + const form = useFormContext(); const ComponentToRender = component ?? 'input'; - // For backward compatibility we merge the "componentProps" prop into the "rest" - const propsToForward = - componentProps !== undefined ? { ...componentProps, ...rest } : { ...rest }; + const propsToForward = { ...componentProps, ...rest }; - const fieldConfig: FieldConfig & { initialValue?: T } = + const fieldConfig: FieldConfig & { initialValue?: T } = config !== undefined ? { ...config } : ({ ...form.__readFieldConfigFromSchema(path), - } as Partial>); + } as Partial>); if (defaultValue !== undefined) { // update the form "defaultValue" ref object so when/if we reset the form we can go back to this value @@ -70,21 +68,12 @@ function UseFieldComp(props: Props) { } else { if (readDefaultValueOnForm) { // Read the field initial value from the "defaultValue" object passed to the form - fieldConfig.initialValue = (form.getFieldDefaultValue(path) as T) ?? fieldConfig.defaultValue; + fieldConfig.initialValue = + (form.__getFieldDefaultValue(path) as T) ?? fieldConfig.defaultValue; } } - if (!fieldConfig.path) { - (fieldConfig.path as any) = path; - } else { - if (fieldConfig.path !== path) { - throw new Error( - `Field path mismatch. Got "${path}" but field config has "${fieldConfig.path}".` - ); - } - } - - const field = useField(form, path, fieldConfig, onChange); + const field = useField(form, path, fieldConfig, onChange); // Children prevails over anything else provided. if (children) { @@ -111,9 +100,13 @@ export const UseField = React.memo(UseFieldComp) as typeof UseFieldComp; * Get a component providing some common props for all instances. * @param partialProps Partial props to apply to all instances */ -export function getUseField(partialProps: Partial>) { - return function (props: Partial>) { - const componentProps = { ...partialProps, ...props } as Props; - return {...componentProps} />; +export function getUseField( + partialProps: Partial> +) { + return function ( + props: Partial> + ) { + const componentProps = { ...partialProps, ...props } as Props; + return {...componentProps} />; }; } diff --git a/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/use_multi_fields.tsx b/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/use_multi_fields.tsx index d69527e36249b..20f4608352d94 100644 --- a/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/use_multi_fields.tsx +++ b/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/use_multi_fields.tsx @@ -22,27 +22,27 @@ import React from 'react'; import { UseField, Props as UseFieldProps } from './use_field'; import { FieldHook } from '../types'; -type FieldsArray = Array<{ id: string } & Omit, 'children'>>; +type FieldsArray = Array<{ id: string } & Omit, 'children'>>; -interface Props { - fields: { [key: string]: Exclude, 'children'> }; - children: (fields: { [key: string]: FieldHook }) => JSX.Element; +interface Props { + fields: { [K in keyof T]: Exclude, 'children'> }; + children: (fields: { [K in keyof T]: FieldHook }) => JSX.Element; } -export const UseMultiFields = ({ fields, children }: Props) => { +export function UseMultiFields({ fields, children }: Props) { const fieldsArray = Object.entries(fields).reduce( - (acc, [fieldId, field]) => [...acc, { id: fieldId, ...field }], + (acc, [fieldId, field]) => [...acc, { id: fieldId, ...(field as FieldHook) }], [] as FieldsArray ); - const hookFields: { [key: string]: FieldHook } = {}; + const hookFields: { [K in keyof T]: FieldHook } = {} as any; const renderField = (index: number) => { const { id } = fieldsArray[index]; return ( - + {(field) => { - hookFields[id] = field; + hookFields[id as keyof T] = field; return index === fieldsArray.length - 1 ? children(hookFields) : renderField(index + 1); }} @@ -54,4 +54,4 @@ export const UseMultiFields = ({ fields, children }: Props) => { } return renderField(0); -}; +} diff --git a/src/plugins/es_ui_shared/static/forms/hook_form_lib/constants.ts b/src/plugins/es_ui_shared/static/forms/hook_form_lib/constants.ts index 4056947483107..3a2ffdc3af146 100644 --- a/src/plugins/es_ui_shared/static/forms/hook_form_lib/constants.ts +++ b/src/plugins/es_ui_shared/static/forms/hook_form_lib/constants.ts @@ -30,11 +30,15 @@ export const FIELD_TYPES = { SELECT: 'select', SUPER_SELECT: 'superSelect', MULTI_SELECT: 'multiSelect', + JSON: 'json', }; // Validation types export const VALIDATION_TYPES = { - FIELD: 'field', // Default validation error (on the field value) - ASYNC: 'async', // Returned from asynchronous validations - ARRAY_ITEM: 'arrayItem', // If the field value is an Array, this error would be returned if an _item_ of the array is invalid + /** Default validation error (on the field value) */ + FIELD: 'field', + /** Returned from asynchronous validations */ + ASYNC: 'async', + /** If the field value is an Array, this error type would be returned if an _item_ of the array is invalid */ + ARRAY_ITEM: 'arrayItem', }; diff --git a/src/plugins/es_ui_shared/static/forms/hook_form_lib/form_data_context.tsx b/src/plugins/es_ui_shared/static/forms/hook_form_lib/form_data_context.tsx index 0e6a75e9c5065..0670220ccd0c9 100644 --- a/src/plugins/es_ui_shared/static/forms/hook_form_lib/form_data_context.tsx +++ b/src/plugins/es_ui_shared/static/forms/hook_form_lib/form_data_context.tsx @@ -22,8 +22,8 @@ import React, { createContext, useContext, useMemo } from 'react'; import { FormData, FormHook } from './types'; import { Subject } from './lib'; -export interface Context { - getFormData$: () => Subject; +export interface Context { + getFormData$: () => Subject; getFormData: FormHook['getFormData']; } diff --git a/src/plugins/es_ui_shared/static/forms/hook_form_lib/hooks/use_field.ts b/src/plugins/es_ui_shared/static/forms/hook_form_lib/hooks/use_field.ts index bb4aae6eccae8..7b21b6638aeac 100644 --- a/src/plugins/es_ui_shared/static/forms/hook_form_lib/hooks/use_field.ts +++ b/src/plugins/es_ui_shared/static/forms/hook_form_lib/hooks/use_field.ts @@ -19,7 +19,14 @@ import { useMemo, useState, useEffect, useRef, useCallback } from 'react'; -import { FormHook, FieldHook, FieldConfig, FieldValidateResponse, ValidationError } from '../types'; +import { + FormHook, + FieldHook, + FieldConfig, + FieldValidateResponse, + ValidationError, + FormData, +} from '../types'; import { FIELD_TYPES, VALIDATION_TYPES } from '../constants'; export interface InternalFieldConfig { @@ -27,11 +34,11 @@ export interface InternalFieldConfig { isIncludedInOutput?: boolean; } -export const useField = ( - form: FormHook, +export const useField = ( + form: FormHook, path: string, - config: FieldConfig & InternalFieldConfig = {}, - valueChangeListener?: (value: T) => void + config: FieldConfig & InternalFieldConfig = {}, + valueChangeListener?: (value: I) => void ) => { const { type = FIELD_TYPES.TEXT, @@ -44,7 +51,7 @@ export const useField = ( validations, formatters, fieldsToValidateOnChange, - errorDisplayDelay = form.__options.errorDisplayDelay, + valueChangeDebounceTime = form.__options.valueChangeDebounceTime, serializer, deserializer, } = config; @@ -68,7 +75,7 @@ export const useField = ( [initialValue, deserializer] ); - const [value, setStateValue] = useState(deserializeValue); + const [value, setStateValue] = useState(deserializeValue); const [errors, setErrors] = useState([]); const [isPristine, setPristine] = useState(true); const [isValidating, setValidating] = useState(false); @@ -84,9 +91,9 @@ export const useField = ( // -- HELPERS // ---------------------------------- - const serializeValue: FieldHook['__serializeValue'] = useCallback( - (rawValue = value) => { - return serializer ? serializer(rawValue) : rawValue; + const serializeValue: FieldHook['__serializeValue'] = useCallback( + (internalValue: I = value) => { + return serializer ? serializer(internalValue) : ((internalValue as unknown) as T); }, [serializer, value] ); @@ -129,16 +136,8 @@ export const useField = ( const changeIteration = ++changeCounter.current; const startTime = Date.now(); - if (debounceTimeout.current) { - clearTimeout(debounceTimeout.current); - debounceTimeout.current = null; - } - setPristine(false); - - if (errorDisplayDelay > 0) { - setIsChangingValue(true); - } + setIsChangingValue(true); // Notify listener if (valueChangeListener) { @@ -161,22 +160,24 @@ export const useField = ( * and then, we verify how long we've already waited for as form.__validateFields() is asynchronous * and might already have taken more than the specified delay) */ - if (errorDisplayDelay > 0 && changeIteration === changeCounter.current) { - const delta = Date.now() - startTime; - if (delta < errorDisplayDelay) { - debounceTimeout.current = setTimeout(() => { - debounceTimeout.current = null; - setIsChangingValue(false); - }, errorDisplayDelay - delta); - } else { - setIsChangingValue(false); + if (changeIteration === changeCounter.current) { + if (valueChangeDebounceTime > 0) { + const delta = Date.now() - startTime; + if (delta < valueChangeDebounceTime) { + debounceTimeout.current = setTimeout(() => { + debounceTimeout.current = null; + setIsChangingValue(false); + }, valueChangeDebounceTime - delta); + return; + } } + setIsChangingValue(false); } }, [ path, value, valueChangeListener, - errorDisplayDelay, + valueChangeDebounceTime, fieldsToValidateOnChange, __updateFormDataAt, __validateFields, @@ -207,7 +208,7 @@ export const useField = ( validationTypeToValidate, }: { formData: any; - value: T; + value: I; validationTypeToValidate?: string; }): ValidationError[] | Promise => { if (!validations) { @@ -339,7 +340,7 @@ export const useField = ( * If a validationType is provided then only that validation will be executed, * skipping the other type of validation that might exist. */ - const validate: FieldHook['validate'] = useCallback( + const validate: FieldHook['validate'] = useCallback( (validationData = {}) => { const { formData = getFormData({ unflatten: false }), @@ -392,14 +393,14 @@ export const useField = ( * * @param newValue The new value to assign to the field */ - const setValue: FieldHook['setValue'] = useCallback( + const setValue: FieldHook['setValue'] = useCallback( (newValue) => { setStateValue((prev) => { - let formattedValue: T; + let formattedValue: I; if (typeof newValue === 'function') { - formattedValue = formatInputValue((newValue as Function)(prev)); + formattedValue = formatInputValue((newValue as Function)(prev)); } else { - formattedValue = formatInputValue(newValue); + formattedValue = formatInputValue(newValue); } return formattedValue; }); @@ -407,7 +408,7 @@ export const useField = ( [formatInputValue] ); - const _setErrors: FieldHook['setErrors'] = useCallback((_errors) => { + const _setErrors: FieldHook['setErrors'] = useCallback((_errors) => { setErrors( _errors.map((error) => ({ validationType: VALIDATION_TYPES.FIELD, @@ -422,13 +423,13 @@ export const useField = ( * * @param event Form input change event */ - const onChange: FieldHook['onChange'] = useCallback( + const onChange: FieldHook['onChange'] = useCallback( (event) => { const newValue = {}.hasOwnProperty.call(event!.target, 'checked') ? event.target.checked : event.target.value; - setValue((newValue as unknown) as T); + setValue((newValue as unknown) as I); }, [setValue] ); @@ -443,7 +444,7 @@ export const useField = ( * * @param validationType The validation type to return error messages from */ - const getErrorsMessages: FieldHook['getErrorsMessages'] = useCallback( + const getErrorsMessages: FieldHook['getErrorsMessages'] = useCallback( (args = {}) => { const { errorCode, validationType = VALIDATION_TYPES.FIELD } = args; const errorMessages = errors.reduce((messages, error) => { @@ -464,30 +465,64 @@ export const useField = ( [errors] ); - const reset: FieldHook['reset'] = useCallback( + /** + * Handler to update the state and make sure the component is still mounted. + * When resetting the form, some field might get unmounted (e.g. a toggle on "true" becomes "false" and now certain fields should not be in the DOM). + * In that scenario there is a race condition in the "reset" method below, because the useState() hook is not synchronous. + * + * A better approach would be to have the state in a reducer and being able to update all values in a single dispatch action. + */ + const updateStateIfMounted = useCallback( + ( + state: 'isPristine' | 'isValidating' | 'isChangingValue' | 'isValidated' | 'errors' | 'value', + nextValue: any + ) => { + if (isMounted.current === false) { + return; + } + + switch (state) { + case 'value': + return setValue(nextValue); + case 'errors': + return setErrors(nextValue); + case 'isChangingValue': + return setIsChangingValue(nextValue); + case 'isPristine': + return setPristine(nextValue); + case 'isValidated': + return setIsValidated(nextValue); + case 'isValidating': + return setValidating(nextValue); + } + }, + [setValue] + ); + + const reset: FieldHook['reset'] = useCallback( (resetOptions = { resetValue: true }) => { const { resetValue = true, defaultValue: updatedDefaultValue } = resetOptions; - setPristine(true); - setValidating(false); - setIsChangingValue(false); - setIsValidated(false); - setErrors([]); + updateStateIfMounted('isPristine', true); + updateStateIfMounted('isValidating', false); + updateStateIfMounted('isChangingValue', false); + updateStateIfMounted('isValidated', false); + updateStateIfMounted('errors', []); if (resetValue) { hasBeenReset.current = true; const newValue = deserializeValue(updatedDefaultValue ?? defaultValue); - setValue(newValue); + updateStateIfMounted('value', newValue); return newValue; } }, - [setValue, deserializeValue, defaultValue] + [updateStateIfMounted, deserializeValue, defaultValue] ); // Don't take into account non blocker validation. Some are just warning (like trying to add a wrong ComboBox item) const isValid = errors.filter((e) => e.__isBlocking__ !== false).length === 0; - const field = useMemo>(() => { + const field = useMemo>(() => { return { path, type, @@ -565,6 +600,7 @@ export const useField = ( return () => { if (debounceTimeout.current) { clearTimeout(debounceTimeout.current); + debounceTimeout.current = null; } }; }, [onValueChange]); diff --git a/src/plugins/es_ui_shared/static/forms/hook_form_lib/hooks/use_form.test.tsx b/src/plugins/es_ui_shared/static/forms/hook_form_lib/hooks/use_form.test.tsx index edcd84daf5d2f..b28c09d07fa98 100644 --- a/src/plugins/es_ui_shared/static/forms/hook_form_lib/hooks/use_form.test.tsx +++ b/src/plugins/es_ui_shared/static/forms/hook_form_lib/hooks/use_form.test.tsx @@ -196,7 +196,9 @@ describe('useForm() hook', () => { }); expect(isValid).toBe(false); - expect(data).toEqual({}); // Don't build the object (and call the serializers()) when invalid + // If the form is not valid, we don't build the final object to avoid + // calling the serializer(s) with invalid values. + expect(data).toEqual({}); }); }); diff --git a/src/plugins/es_ui_shared/static/forms/hook_form_lib/hooks/use_form.ts b/src/plugins/es_ui_shared/static/forms/hook_form_lib/hooks/use_form.ts index b390c17d3c2ff..be4535fec3669 100644 --- a/src/plugins/es_ui_shared/static/forms/hook_form_lib/hooks/use_form.ts +++ b/src/plugins/es_ui_shared/static/forms/hook_form_lib/hooks/use_form.ts @@ -24,19 +24,18 @@ import { set } from '@elastic/safer-lodash-set'; import { FormHook, FieldHook, FormData, FieldConfig, FieldsMap, FormConfig } from '../types'; import { mapFormFields, unflattenObject, Subject, Subscription } from '../lib'; -const DEFAULT_ERROR_DISPLAY_TIMEOUT = 500; const DEFAULT_OPTIONS = { - errorDisplayDelay: DEFAULT_ERROR_DISPLAY_TIMEOUT, + valueChangeDebounceTime: 500, stripEmptyFields: true, }; -interface UseFormReturn { - form: FormHook; +interface UseFormReturn { + form: FormHook; } -export function useForm( - formConfig?: FormConfig -): UseFormReturn { +export function useForm( + formConfig?: FormConfig +): UseFormReturn { const { onSubmit, schema, serializer, deserializer, options, id = 'default', defaultValue } = formConfig ?? {}; @@ -48,9 +47,9 @@ export function useForm( const filtered = Object.entries(_defaultValue as object) .filter(({ 1: value }) => value !== undefined) - .reduce((acc, [key, value]) => ({ ...acc, [key]: value }), {}); + .reduce((acc, [key, value]) => ({ ...acc, [key]: value }), {} as T); - return deserializer ? (deserializer(filtered) as any) : filtered; + return deserializer ? deserializer(filtered) : filtered; }, [deserializer] ); @@ -61,13 +60,13 @@ export function useForm( const defaultValueDeserialized = useRef(defaultValueMemoized); - const { errorDisplayDelay, stripEmptyFields: doStripEmptyFields } = options ?? {}; + const { valueChangeDebounceTime, stripEmptyFields: doStripEmptyFields } = options ?? {}; const formOptions = useMemo( () => ({ stripEmptyFields: doStripEmptyFields ?? DEFAULT_OPTIONS.stripEmptyFields, - errorDisplayDelay: errorDisplayDelay ?? DEFAULT_OPTIONS.errorDisplayDelay, + valueChangeDebounceTime: valueChangeDebounceTime ?? DEFAULT_OPTIONS.valueChangeDebounceTime, }), - [errorDisplayDelay, doStripEmptyFields] + [valueChangeDebounceTime, doStripEmptyFields] ); const [isSubmitted, setIsSubmitted] = useState(false); @@ -93,7 +92,7 @@ export function useForm( return formData$.current; }, []); - const fieldsToArray = useCallback(() => Object.values(fieldsRefs.current), []); + const fieldsToArray = useCallback<() => FieldHook[]>(() => Object.values(fieldsRefs.current), []); const getFieldsForOutput = useCallback( (fields: FieldsMap, opts: { stripEmptyFields: boolean }): FieldsMap => { @@ -144,7 +143,7 @@ export function useForm( }); const fieldsValue = mapFormFields(fieldsToOutput, (field) => field.__serializeValue()); return serializer - ? (serializer(unflattenObject(fieldsValue)) as T) + ? (serializer(unflattenObject(fieldsValue) as I) as T) : (unflattenObject(fieldsValue) as T); } @@ -175,6 +174,24 @@ export function useForm( const isFieldValid = (field: FieldHook) => field.isValid && !field.isValidating; + const waitForFieldsToFinishValidating = useCallback(async () => { + let areSomeFieldValidating = fieldsToArray().some((field) => field.isValidating); + if (!areSomeFieldValidating) { + return; + } + + return new Promise((resolve) => { + setTimeout(() => { + areSomeFieldValidating = fieldsToArray().some((field) => field.isValidating); + if (areSomeFieldValidating) { + // Recursively wait for all the fields to finish validating. + return waitForFieldsToFinishValidating().then(resolve); + } + resolve(); + }, 100); + }); + }, [fieldsToArray]); + const validateFields: FormHook['__validateFields'] = useCallback( async (fieldNames) => { const fieldsToValidate = fieldNames @@ -204,18 +221,25 @@ export function useForm( // To know the current form validity, we will then merge the "validationResult" _with_ the fieldsRefs object state, // the "validationResult" taking presedence over the fieldsRefs values. const formFieldsValidity = fieldsToArray().map((field) => { + const hasUpdatedValidity = validationResultByPath[field.path] !== undefined; const _isValid = validationResultByPath[field.path] ?? field.isValid; - const _isValidated = - validationResultByPath[field.path] !== undefined ? true : field.isValidated; - return [_isValid, _isValidated]; + const _isValidated = hasUpdatedValidity ? true : field.isValidated; + const _isValidating = hasUpdatedValidity ? false : field.isValidating; + return { + isValid: _isValid, + isValidated: _isValidated, + isValidating: _isValidating, + }; }); - const areAllFieldsValidated = formFieldsValidity.every(({ 1: isValidated }) => isValidated); + const areAllFieldsValidated = formFieldsValidity.every((field) => field.isValidated); + const areSomeFieldValidating = formFieldsValidity.some((field) => field.isValidating); // If *not* all the fiels have been validated, the validity of the form is unknown, thus still "undefined" - const isFormValid = areAllFieldsValidated - ? formFieldsValidity.every(([_isValid]) => _isValid) - : undefined; + const isFormValid = + areAllFieldsValidated && areSomeFieldValidating === false + ? formFieldsValidity.every((field) => field.isValid) + : undefined; setIsValid(isFormValid); @@ -225,6 +249,14 @@ export function useForm( ); const validateAllFields = useCallback(async (): Promise => { + // Maybe some field are being validated because of their async validation(s). + // We make sure those validations have finished executing before proceeding. + await waitForFieldsToFinishValidating(); + + if (!isMounted.current) { + return false; + } + const fieldsArray = fieldsToArray(); const fieldsToValidate = fieldsArray.filter((field) => !field.isValidated); @@ -238,7 +270,7 @@ export function useForm( setIsValid(isFormValid); return isFormValid!; - }, [fieldsToArray, validateFields]); + }, [fieldsToArray, validateFields, waitForFieldsToFinishValidating]); const addField: FormHook['__addField'] = useCallback( (field) => { @@ -303,7 +335,7 @@ export function useForm( const getFields: FormHook['getFields'] = useCallback(() => fieldsRefs.current, []); - const getFieldDefaultValue: FormHook['getFieldDefaultValue'] = useCallback( + const getFieldDefaultValue: FormHook['__getFieldDefaultValue'] = useCallback( (fieldName) => get(defaultValueDeserialized.current, fieldName), [] ); @@ -410,13 +442,13 @@ export function useForm( getFields, getFormData, getErrors, - getFieldDefaultValue, reset, __options: formOptions, __getFormData$: getFormData$, __updateFormDataAt: updateFormDataAt, __updateDefaultValueAt: updateDefaultValueAt, __readFieldConfigFromSchema: readFieldConfigFromSchema, + __getFieldDefaultValue: getFieldDefaultValue, __addField: addField, __removeField: removeField, __validateFields: validateFields, diff --git a/src/plugins/es_ui_shared/static/forms/hook_form_lib/hooks/use_form_data.ts b/src/plugins/es_ui_shared/static/forms/hook_form_lib/hooks/use_form_data.ts index fb4a0984438ad..6c6dee3624979 100644 --- a/src/plugins/es_ui_shared/static/forms/hook_form_lib/hooks/use_form_data.ts +++ b/src/plugins/es_ui_shared/static/forms/hook_form_lib/hooks/use_form_data.ts @@ -63,7 +63,11 @@ export const useFormData = (options: Options = {}): ? (watch as string[]) : ([watch] as string[]); - if (valuesToWatchArray.some((value) => previousRawData.current[value] !== raw[value])) { + if ( + valuesToWatchArray.some( + (value) => previousRawData.current[value] !== raw[value as keyof T] + ) + ) { previousRawData.current = raw; // Only update the state if one of the field we watch has changed. setFormData(raw); diff --git a/src/plugins/es_ui_shared/static/forms/hook_form_lib/types.ts b/src/plugins/es_ui_shared/static/forms/hook_form_lib/types.ts index 18b8f478f7c0e..ae731caff2881 100644 --- a/src/plugins/es_ui_shared/static/forms/hook_form_lib/types.ts +++ b/src/plugins/es_ui_shared/static/forms/hook_form_lib/types.ts @@ -24,21 +24,37 @@ import { Subject, Subscription } from './lib'; // Comes from https://github.com/microsoft/TypeScript/issues/15012#issuecomment-365453623 type Required = T extends FormData ? { [P in keyof T]-?: NonNullable } : T; -export interface FormHook { +export interface FormHook { + /** Flag that indicates if the form has been submitted at least once. It is set to `true` when we call `submit()`. */ readonly isSubmitted: boolean; + /** Flag that indicates if the form is being submitted. */ readonly isSubmitting: boolean; + /** Flag that indicates if the form is valid. If `undefined` then the form validation has not been checked yet. */ readonly isValid: boolean | undefined; + /** The form id. If none was provided, "default" will be returned. */ readonly id: string; + /** + * This handler submits the form and returns its data and validity. If the form is not valid, the data will be `null` + * as only valid data is passed through the `serializer(s)` before being returned. + */ submit: (e?: FormEvent | MouseEvent) => Promise<{ data: T; isValid: boolean }>; + /** Use this handler to get the validity of the form. */ validate: () => Promise; subscribe: (handler: OnUpdateHandler) => Subscription; + /** Sets a field value imperatively. */ setFieldValue: (fieldName: string, value: FieldValue) => void; + /** Sets a field errors imperatively. */ setFieldErrors: (fieldName: string, errors: ValidationError[]) => void; + /** Access any field on the form. */ getFields: () => FieldsMap; + /** + * Return the form data. It accepts an optional options object with an `unflatten` parameter (defaults to `true`). + * If you are only interested in the raw form data, pass `unflatten: false` to the handler + */ getFormData: (options?: { unflatten?: boolean }) => T; - getFieldDefaultValue: (fieldName: string) => unknown; - /* Returns a list of all errors in the form */ + /* Returns an array with of all errors in the form. */ getErrors: () => string[]; + /** Resets the form to its initial state. */ reset: (options?: { resetValues?: boolean; defaultValue?: Partial }) => void; readonly __options: Required; __getFormData$: () => Subject; @@ -50,23 +66,19 @@ export interface FormHook { __updateFormDataAt: (field: string, value: unknown) => T; __updateDefaultValueAt: (field: string, value: unknown) => void; __readFieldConfigFromSchema: (fieldName: string) => FieldConfig; + __getFieldDefaultValue: (fieldName: string) => unknown; } -export interface FormSchema { - [key: string]: FormSchemaEntry; -} - -type FormSchemaEntry = - | FieldConfig - | Array> - | { [key: string]: FieldConfig | Array> | FormSchemaEntry }; +export type FormSchema = { + [K in keyof T]?: FieldConfig | FormSchema; +}; -export interface FormConfig { +export interface FormConfig { onSubmit?: FormSubmitHandler; - schema?: FormSchema; + schema?: FormSchema; defaultValue?: Partial; - serializer?: SerializerFunc; - deserializer?: SerializerFunc; + serializer?: SerializerFunc; + deserializer?: SerializerFunc; options?: FormOptions; id?: string; } @@ -83,20 +95,20 @@ export interface OnFormUpdateArg { export type OnUpdateHandler = (arg: OnFormUpdateArg) => void; export interface FormOptions { - errorDisplayDelay?: number; + valueChangeDebounceTime?: number; /** * Remove empty string field ("") from form data */ stripEmptyFields?: boolean; } -export interface FieldHook { +export interface FieldHook { readonly path: string; readonly label?: string; readonly labelAppend?: string | ReactNode; readonly helpText?: string | ReactNode; readonly type: string; - readonly value: T; + readonly value: I; readonly errors: ValidationError[]; readonly isValid: boolean; readonly isPristine: boolean; @@ -108,34 +120,33 @@ export interface FieldHook { errorCode?: string; }) => string | null; onChange: (event: ChangeEvent<{ name?: string; value: string; checked?: boolean }>) => void; - setValue: (value: T | ((prevValue: T) => T)) => void; + setValue: (value: I | ((prevValue: I) => I)) => void; setErrors: (errors: ValidationError[]) => void; clearErrors: (type?: string | string[]) => void; validate: (validateData?: { formData?: any; - value?: T; + value?: I; validationType?: string; }) => FieldValidateResponse | Promise; reset: (options?: { resetValue?: boolean; defaultValue?: T }) => unknown | undefined; // Flag to indicate if the field value will be included in the form data outputted // when calling form.getFormData(); __isIncludedInOutput: boolean; - __serializeValue: (rawValue?: unknown) => unknown; + __serializeValue: (internalValue?: I) => T; } -export interface FieldConfig { - readonly path?: string; +export interface FieldConfig { readonly label?: string; readonly labelAppend?: string | ReactNode; readonly helpText?: string | ReactNode; - readonly type?: HTMLInputElement['type']; - readonly defaultValue?: ValueType; - readonly validations?: Array>; + readonly type?: string; + readonly defaultValue?: T; + readonly validations?: Array>; readonly formatters?: FormatterFunc[]; - readonly deserializer?: SerializerFunc; - readonly serializer?: SerializerFunc; + readonly deserializer?: SerializerFunc; + readonly serializer?: SerializerFunc; readonly fieldsToValidateOnChange?: string[]; - readonly errorDisplayDelay?: number; + readonly valueChangeDebounceTime?: number; } export interface FieldsMap { @@ -166,7 +177,7 @@ export interface ValidationFuncArg { errors: readonly ValidationError[]; } -export type ValidationFunc = ( +export type ValidationFunc = ( data: ValidationFuncArg ) => ValidationError | void | undefined | Promise | void | undefined>; @@ -187,8 +198,12 @@ type FormatterFunc = (value: any, formData: FormData) => unknown; // string | number | boolean | string[] ... type FieldValue = unknown; -export interface ValidationConfig { - validator: ValidationFunc; +export interface ValidationConfig< + FormType extends FormData = any, + Error extends string = string, + ValueType = unknown +> { + validator: ValidationFunc; type?: string; /** * By default all validation are blockers, which means that if they fail, the field is invalid. diff --git a/src/plugins/expressions/README.asciidoc b/src/plugins/expressions/README.asciidoc new file mode 100644 index 0000000000000..e07f6e2909ab8 --- /dev/null +++ b/src/plugins/expressions/README.asciidoc @@ -0,0 +1,55 @@ +[[kibana-expressions-plugin]] +== `expressions` plugin + +Expression pipeline is a chain of functions that *pipe* its output to the +input of the next function. Functions can be configured using arguments provided +by the user. The final output of the expression pipeline can be rendered using +one of the *renderers* registered in `expressions` plugin. + +All the arguments to expression functions need to be serializable, as well as input and output. +Expression functions should try to stay 'pure'. This makes functions easy to reuse and also +make it possible to serialize the whole chain as well as output at every step of execution. + +Expressions power visualizations in Dashboard and Lens, as well as, every +*element* in Canvas is backed by an expression. + +This plugin provides methods which will parse & execute an *expression pipeline* +string for you, as well as a series of registries for advanced users who might +want to incorporate their own functions, types, and renderers into the service +for use in their own application. + +=== Examples + +Below is an example of serialized expression for one Canvas element that fetches +data using `essql` function, pipes it further to `math` and `metric` functions, +and final `render` function renders the result. + +[source] +filters +| essql + query="SELECT COUNT(timestamp) as total_errors + FROM kibana_sample_data_logs + WHERE tags LIKE '%warning%' OR tags LIKE '%error%'" +| math "total_errors" +| metric "TOTAL ISSUES" + metricFont={font family="'Open Sans', Helvetica, Arial, sans-serif" size=48 align="left" color="#FFFFFF" weight="normal" underline=false italic=false} + labelFont={font family="'Open Sans', Helvetica, Arial, sans-serif" size=30 align="left" color="#FFFFFF" weight="lighter" underline=false italic=false} +| render +[/source] + +[role="screenshot"] +image::https://user-images.githubusercontent.com/9773803/74162514-3250a880-4c21-11ea-9e68-86f66862a183.png[] + +=== API documentation + +==== Server API +https://github.com/elastic/kibana/blob/master/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionsserversetup.md[Server Setup contract] +https://github.com/elastic/kibana/blob/master/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionsserverstart.md[Server Start contract] + +===== Browser API +https://github.com/elastic/kibana/blob/master/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsservicesetup.md[Browser Setup contract] +https://github.com/elastic/kibana/blob/master/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsstart.md[Browser Start contract] + + +==== Other documentation +https://www.elastic.co/guide/en/kibana/current/canvas-function-arguments.html[See Canvas documentation about expressions] diff --git a/src/plugins/expressions/README.md b/src/plugins/expressions/README.md deleted file mode 100644 index c1f032ace37c9..0000000000000 --- a/src/plugins/expressions/README.md +++ /dev/null @@ -1,35 +0,0 @@ -# `expressions` plugin - -This plugin provides methods which will parse & execute an *expression pipeline* -string for you, as well as a series of registries for advanced users who might -want to incorporate their own functions, types, and renderers into the service -for use in their own application. - -Expression pipeline is a chain of functions that *pipe* its output to the -input of the next function. Functions can be configured using arguments provided -by the user. The final output of the expression pipeline can be rendered using -one of the *renderers* registered in `expressions` plugin. - -Expressions power visualizations in Dashboard and Lens, as well as, every -*element* in Canvas is backed by an expression. - -Below is an example of one Canvas element that fetches data using `essql` function, -pipes it further to `math` and `metric` functions, and final `render` function -renders the result. - -``` -filters -| essql - query="SELECT COUNT(timestamp) as total_errors - FROM kibana_sample_data_logs - WHERE tags LIKE '%warning%' OR tags LIKE '%error%'" -| math "total_errors" -| metric "TOTAL ISSUES" - metricFont={font family="'Open Sans', Helvetica, Arial, sans-serif" size=48 align="left" color="#FFFFFF" weight="normal" underline=false italic=false} - labelFont={font family="'Open Sans', Helvetica, Arial, sans-serif" size=30 align="left" color="#FFFFFF" weight="lighter" underline=false italic=false} -| render -``` - -![image](https://user-images.githubusercontent.com/9773803/74162514-3250a880-4c21-11ea-9e68-86f66862a183.png) - -[See Canvas documentation about expressions](https://www.elastic.co/guide/en/kibana/current/canvas-function-arguments.html). diff --git a/src/plugins/expressions/common/ast/types.ts b/src/plugins/expressions/common/ast/types.ts index d5039d0adb318..09fb4fae3f201 100644 --- a/src/plugins/expressions/common/ast/types.ts +++ b/src/plugins/expressions/common/ast/types.ts @@ -18,7 +18,6 @@ */ import { ExpressionValue, ExpressionValueError } from '../expression_types'; -import { ExpressionFunction } from '../../common'; export type ExpressionAstNode = | ExpressionAstExpression @@ -48,9 +47,9 @@ export interface ExpressionAstFunctionDebug { success: boolean; /** - * Reference to the expression function this AST node represents. + * Id of expression function. */ - fn: ExpressionFunction; + fn: string; /** * Input that expression function received as its first argument. diff --git a/src/plugins/expressions/common/execution/execution.test.ts b/src/plugins/expressions/common/execution/execution.test.ts index 2b8aa4b5e68f0..ff331d7c5ddaf 100644 --- a/src/plugins/expressions/common/execution/execution.test.ts +++ b/src/plugins/expressions/common/execution/execution.test.ts @@ -491,7 +491,7 @@ describe('Execution', () => { await execution.result; for (const node of execution.state.get().ast.chain) { - expect(node.debug?.fn.name).toBe('add'); + expect(node.debug?.fn).toBe('add'); } }); @@ -667,7 +667,7 @@ describe('Execution', () => { expect(node2.debug).toMatchObject({ success: false, - fn: expect.any(Object), + fn: 'throws', input: expect.any(Object), args: expect.any(Object), error: expect.any(Object), diff --git a/src/plugins/expressions/common/execution/execution.ts b/src/plugins/expressions/common/execution/execution.ts index 3533500a2fbc5..d4c9b0a25d45b 100644 --- a/src/plugins/expressions/common/execution/execution.ts +++ b/src/plugins/expressions/common/execution/execution.ts @@ -235,7 +235,7 @@ export class Execution< const timeEnd: number = now(); (link as ExpressionAstFunction).debug = { success: true, - fn, + fn: fn.name, input, args: resolvedArgs, output, @@ -253,7 +253,7 @@ export class Execution< if (this.params.debug) { (link as ExpressionAstFunction).debug = { success: false, - fn, + fn: fn.name, input, args, error, diff --git a/src/plugins/expressions/common/execution/execution_contract.ts b/src/plugins/expressions/common/execution/execution_contract.ts index 8c784352b9fdf..20c5b2dd434b5 100644 --- a/src/plugins/expressions/common/execution/execution_contract.ts +++ b/src/plugins/expressions/common/execution/execution_contract.ts @@ -18,6 +18,8 @@ */ import { Execution } from './execution'; +import { ExpressionValueError } from '../expression_types/specs'; +import { ExpressionAstExpression } from '../ast'; /** * `ExecutionContract` is a wrapper around `Execution` class. It provides the @@ -53,7 +55,7 @@ export class ExecutionContract< * wraps that error into `ExpressionValueError` type and returns that. * This function never throws. */ - getData = async () => { + getData = async (): Promise => { try { return await this.execution.result; } catch (e) { @@ -80,7 +82,7 @@ export class ExecutionContract< /** * Get AST used to execute the expression. */ - getAst = () => this.execution.state.get().ast; + getAst = (): ExpressionAstExpression => this.execution.state.get().ast; /** * Get Inspector adapters provided to all functions of expression through diff --git a/src/plugins/expressions/common/expression_renderers/types.ts b/src/plugins/expressions/common/expression_renderers/types.ts index 7b3e812eafedd..0ea3d72e75609 100644 --- a/src/plugins/expressions/common/expression_renderers/types.ts +++ b/src/plugins/expressions/common/expression_renderers/types.ts @@ -17,6 +17,8 @@ * under the License. */ +import { PersistedState } from 'src/plugins/visualizations/public'; + export interface ExpressionRenderDefinition { /** * Technical name of the renderer, used as ID to identify renderer in @@ -28,7 +30,7 @@ export interface ExpressionRenderDefinition { /** * A user friendly name of the renderer as will be displayed to user in UI. */ - displayName: string; + displayName?: string; /** * Help text as will be displayed to user. A sentence or few about what this @@ -68,4 +70,5 @@ export interface IInterpreterRenderHandlers { reload: () => void; update: (params: any) => void; event: (event: any) => void; + uiState?: PersistedState; } diff --git a/src/plugins/expressions/common/expression_types/specs/error.ts b/src/plugins/expressions/common/expression_types/specs/error.ts index 35554954d0828..ebaedcbba0d23 100644 --- a/src/plugins/expressions/common/expression_types/specs/error.ts +++ b/src/plugins/expressions/common/expression_types/specs/error.ts @@ -28,8 +28,10 @@ export type ExpressionValueError = ExpressionValueBoxed< { error: { message: string; + type?: string; name?: string; stack?: string; + original?: Error; }; info?: unknown; } diff --git a/src/plugins/expressions/common/service/expressions_services.ts b/src/plugins/expressions/common/service/expressions_services.ts index f1053c7bb8411..b5c98fada07c4 100644 --- a/src/plugins/expressions/common/service/expressions_services.ts +++ b/src/plugins/expressions/common/service/expressions_services.ts @@ -18,9 +18,11 @@ */ import { Executor } from '../executor'; -import { ExpressionRendererRegistry } from '../expression_renderers'; +import { AnyExpressionRenderDefinition, ExpressionRendererRegistry } from '../expression_renderers'; import { ExpressionAstExpression } from '../ast'; import { ExecutionContract } from '../execution/execution_contract'; +import { AnyExpressionTypeDefinition } from '../expression_types'; +import { AnyExpressionFunctionDefinition } from '../expression_functions'; /** * The public contract that `ExpressionsService` provides to other plugins @@ -45,18 +47,88 @@ export type ExpressionsServiceSetup = Pick< * The public contract that `ExpressionsService` provides to other plugins * in Kibana Platform in *start* life-cycle. */ -export type ExpressionsServiceStart = Pick< - ExpressionsService, - | 'getFunction' - | 'getFunctions' - | 'getRenderer' - | 'getRenderers' - | 'getType' - | 'getTypes' - | 'run' - | 'execute' - | 'fork' ->; +export interface ExpressionsServiceStart { + /** + * Get a registered `ExpressionFunction` by its name, which was registered + * using the `registerFunction` method. The returned `ExpressionFunction` + * instance is an internal representation of the function in Expressions + * service - do not mutate that object. + */ + getFunction: (name: string) => ReturnType; + + /** + * Get a registered `ExpressionRenderer` by its name, which was registered + * using the `registerRenderer` method. The returned `ExpressionRenderer` + * instance is an internal representation of the renderer in Expressions + * service - do not mutate that object. + */ + getRenderer: (name: string) => ReturnType; + + /** + * Get a registered `ExpressionType` by its name, which was registered + * using the `registerType` method. The returned `ExpressionType` + * instance is an internal representation of the type in Expressions + * service - do not mutate that object. + */ + getType: (name: string) => ReturnType; + + /** + * Executes expression string or a parsed expression AST and immediately + * returns the result. + * + * Below example will execute `sleep 100 | clog` expression with `123` initial + * input to the first function. + * + * ```ts + * expressions.run('sleep 100 | clog', 123); + * ``` + * + * - `sleep 100` will delay execution by 100 milliseconds and pass the `123` input as + * its output. + * - `clog` will print to console `123` and pass it as its output. + * - The final result of the execution will be `123`. + * + * Optionally, you can pass an object as the third argument which will be used + * to extend the `ExecutionContext`—an object passed to each function + * as the third argument, that allows functions to perform side-effects. + * + * ```ts + * expressions.run('...', null, { elasticsearchClient }); + * ``` + */ + run: = Record>( + ast: string | ExpressionAstExpression, + input: Input, + context?: ExtraContext + ) => Promise; + + /** + * Starts expression execution and immediately returns `ExecutionContract` + * instance that tracks the progress of the execution and can be used to + * interact with the execution. + */ + execute: < + Input = unknown, + Output = unknown, + ExtraContext extends Record = Record + >( + ast: string | ExpressionAstExpression, + // This any is for legacy reasons. + input: Input, + context?: ExtraContext + ) => ExecutionContract; + + /** + * Create a new instance of `ExpressionsService`. The new instance inherits + * all state of the original `ExpressionsService`, including all expression + * types, expression functions and context. Also, all new types and functions + * registered in the original services AFTER the forking event will be + * available in the forked instance. However, all new types and functions + * registered in the forked instances will NOT be available to the original + * service. + */ + fork: () => ExpressionsService; +} export interface ExpressionServiceParams { executor?: Executor; @@ -127,58 +199,21 @@ export class ExpressionsService { * passed to all functions that can be used for side-effects. */ public readonly registerFunction = ( - ...args: Parameters - ): ReturnType => this.executor.registerFunction(...args); + functionDefinition: AnyExpressionFunctionDefinition | (() => AnyExpressionFunctionDefinition) + ): void => this.executor.registerFunction(functionDefinition); public readonly registerType = ( - ...args: Parameters - ): ReturnType => this.executor.registerType(...args); + typeDefinition: AnyExpressionTypeDefinition | (() => AnyExpressionTypeDefinition) + ): void => this.executor.registerType(typeDefinition); public readonly registerRenderer = ( - ...args: Parameters - ): ReturnType => this.renderers.register(...args); + definition: AnyExpressionRenderDefinition | (() => AnyExpressionRenderDefinition) + ): void => this.renderers.register(definition); - /** - * Executes expression string or a parsed expression AST and immediately - * returns the result. - * - * Below example will execute `sleep 100 | clog` expression with `123` initial - * input to the first function. - * - * ```ts - * expressions.run('sleep 100 | clog', 123); - * ``` - * - * - `sleep 100` will delay execution by 100 milliseconds and pass the `123` input as - * its output. - * - `clog` will print to console `123` and pass it as its output. - * - The final result of the execution will be `123`. - * - * Optionally, you can pass an object as the third argument which will be used - * to extend the `ExecutionContext`—an object passed to each function - * as the third argument, that allows functions to perform side-effects. - * - * ```ts - * expressions.run('...', null, { elasticsearchClient }); - * ``` - */ - public readonly run = < - Input, - Output, - ExtraContext extends Record = Record - >( - ast: string | ExpressionAstExpression, - input: Input, - context?: ExtraContext - ): Promise => this.executor.run(ast, input, context); + public readonly run: ExpressionsServiceStart['run'] = (ast, input, context) => + this.executor.run(ast, input, context); - /** - * Get a registered `ExpressionFunction` by its name, which was registered - * using the `registerFunction` method. The returned `ExpressionFunction` - * instance is an internal representation of the function in Expressions - * service - do not mutate that object. - */ - public readonly getFunction = (name: string): ReturnType => + public readonly getFunction: ExpressionsServiceStart['getFunction'] = (name) => this.executor.getFunction(name); /** @@ -188,13 +223,7 @@ export class ExpressionsService { public readonly getFunctions = (): ReturnType => this.executor.getFunctions(); - /** - * Get a registered `ExpressionRenderer` by its name, which was registered - * using the `registerRenderer` method. The returned `ExpressionRenderer` - * instance is an internal representation of the renderer in Expressions - * service - do not mutate that object. - */ - public readonly getRenderer = (name: string): ReturnType => + public readonly getRenderer: ExpressionsServiceStart['getRenderer'] = (name) => this.renderers.get(name); /** @@ -204,13 +233,7 @@ export class ExpressionsService { public readonly getRenderers = (): ReturnType => this.renderers.toJS(); - /** - * Get a registered `ExpressionType` by its name, which was registered - * using the `registerType` method. The returned `ExpressionType` - * instance is an internal representation of the type in Expressions - * service - do not mutate that object. - */ - public readonly getType = (name: string): ReturnType => + public readonly getType: ExpressionsServiceStart['getType'] = (name) => this.executor.getType(name); /** @@ -219,36 +242,13 @@ export class ExpressionsService { */ public readonly getTypes = (): ReturnType => this.executor.getTypes(); - /** - * Starts expression execution and immediately returns `ExecutionContract` - * instance that tracks the progress of the execution and can be used to - * interact with the execution. - */ - public readonly execute = < - Input = unknown, - Output = unknown, - ExtraContext extends Record = Record - >( - ast: string | ExpressionAstExpression, - // This any is for legacy reasons. - input: Input = { type: 'null' } as any, - context?: ExtraContext - ): ExecutionContract => { - const execution = this.executor.createExecution(ast, context); + public readonly execute: ExpressionsServiceStart['execute'] = ((ast, input, context) => { + const execution = this.executor.createExecution(ast, context); execution.start(input); return execution.contract; - }; + }) as ExpressionsServiceStart['execute']; - /** - * Create a new instance of `ExpressionsService`. The new instance inherits - * all state of the original `ExpressionsService`, including all expression - * types, expression functions and context. Also, all new types and functions - * registered in the original services AFTER the forking event will be - * available in the forked instance. However, all new types and functions - * registered in the forked instances will NOT be available to the original - * service. - */ - public readonly fork = (): ExpressionsService => { + public readonly fork = () => { const executor = this.executor.fork(); const renderers = this.renderers; const fork = new ExpressionsService({ executor, renderers }); diff --git a/src/plugins/expressions/common/util/create_error.ts b/src/plugins/expressions/common/util/create_error.ts index 876e7dfec799c..9bdab74efd6f9 100644 --- a/src/plugins/expressions/common/util/create_error.ts +++ b/src/plugins/expressions/common/util/create_error.ts @@ -21,7 +21,7 @@ import { ExpressionValueError } from '../../common'; type ErrorLike = Partial>; -export const createError = (err: string | ErrorLike): ExpressionValueError => ({ +export const createError = (err: string | Error | ErrorLike): ExpressionValueError => ({ type: 'error', error: { stack: @@ -32,5 +32,6 @@ export const createError = (err: string | ErrorLike): ExpressionValueError => ({ : undefined, message: typeof err === 'string' ? err : String(err.message), name: typeof err === 'object' ? err.name || 'Error' : 'Error', + original: err instanceof Error ? err : undefined, }, }); diff --git a/src/plugins/expressions/public/index.ts b/src/plugins/expressions/public/index.ts index 87406db89a2a8..039890c9233cf 100644 --- a/src/plugins/expressions/public/index.ts +++ b/src/plugins/expressions/public/index.ts @@ -122,4 +122,7 @@ export { TypeToString, UnmappedTypeStrings, ExpressionValueRender as Render, + ExpressionsService, + ExpressionsServiceSetup, + ExpressionsServiceStart, } from '../common'; diff --git a/src/plugins/expressions/public/mocks.tsx b/src/plugins/expressions/public/mocks.tsx index 3865b4d20620a..f6546a6b7ff35 100644 --- a/src/plugins/expressions/public/mocks.tsx +++ b/src/plugins/expressions/public/mocks.tsx @@ -49,11 +49,8 @@ const createStartContract = (): Start => { ExpressionRenderHandler: jest.fn(), fork: jest.fn(), getFunction: jest.fn(), - getFunctions: jest.fn(), getRenderer: jest.fn(), - getRenderers: jest.fn(), getType: jest.fn(), - getTypes: jest.fn(), loader: jest.fn(), ReactExpressionRenderer: jest.fn((props) => <>), render: jest.fn(), diff --git a/src/plugins/expressions/public/plugin.test.ts b/src/plugins/expressions/public/plugin.test.ts index 08f7135f033f1..d9dde1f6def68 100644 --- a/src/plugins/expressions/public/plugin.test.ts +++ b/src/plugins/expressions/public/plugin.test.ts @@ -67,7 +67,7 @@ describe('ExpressionsPublicPlugin', () => { const { doStart } = await expressionsPluginMock.createPlugin(); const start = await doStart(); - const handler = start.execute('clog'); + const handler = start.execute('clog', null); expect(handler.getAst()).toMatchInlineSnapshot(` Object { "chain": Array [ @@ -85,7 +85,7 @@ describe('ExpressionsPublicPlugin', () => { test('"kibana" function return value of type "kibana_context"', async () => { const { doStart } = await expressionsPluginMock.createPlugin(); const start = await doStart(); - const execution = start.execute('kibana'); + const execution = start.execute('kibana', null); const result = await execution.getData(); expect((result as any).type).toBe('kibana_context'); diff --git a/src/plugins/expressions/public/plugin.ts b/src/plugins/expressions/public/plugin.ts index 9768ece899dd4..4ad0e53cdd9c0 100644 --- a/src/plugins/expressions/public/plugin.ts +++ b/src/plugins/expressions/public/plugin.ts @@ -21,20 +21,26 @@ import { PluginInitializerContext, CoreSetup, CoreStart, Plugin } from 'src/core import { ExpressionsService, ExpressionsServiceSetup, - ExpressionsServiceStart, ExecutionContext, + ExpressionsServiceStart, } from '../common'; import { setRenderersRegistry, setNotifications, setExpressionsService } from './services'; import { ReactExpressionRenderer } from './react_expression_renderer'; -import { ExpressionLoader, loader } from './loader'; +import { ExpressionLoader, IExpressionLoader, loader } from './loader'; import { render, ExpressionRenderHandler } from './render'; +/** + * Expressions public setup contract, extends {@link ExpressionsServiceSetup} + */ export type ExpressionsSetup = ExpressionsServiceSetup; +/** + * Expressions public start contrect, extends {@link ExpressionServiceStart} + */ export interface ExpressionsStart extends ExpressionsServiceStart { ExpressionLoader: typeof ExpressionLoader; ExpressionRenderHandler: typeof ExpressionRenderHandler; - loader: typeof loader; + loader: IExpressionLoader; ReactExpressionRenderer: typeof ReactExpressionRenderer; render: typeof render; } diff --git a/src/plugins/expressions/public/public.api.md b/src/plugins/expressions/public/public.api.md new file mode 100644 index 0000000000000..763147df6d922 --- /dev/null +++ b/src/plugins/expressions/public/public.api.md @@ -0,0 +1,1167 @@ +## API Report File for "kibana" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts + +import { CoreSetup } from 'src/core/public'; +import { CoreStart } from 'src/core/public'; +import { Ensure } from '@kbn/utility-types'; +import { EnvironmentMode } from '@kbn/config'; +import { EventEmitter } from 'events'; +import { Observable } from 'rxjs'; +import { PackageInfo } from '@kbn/config'; +import { PersistedState } from 'src/plugins/visualizations/public'; +import { Plugin as Plugin_2 } from 'src/core/public'; +import { PluginInitializerContext as PluginInitializerContext_2 } from 'src/core/public'; +import React from 'react'; +import { UnwrapPromiseOrReturn } from '@kbn/utility-types'; + +// Warning: (ae-missing-release-tag) "AnyExpressionFunctionDefinition" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export type AnyExpressionFunctionDefinition = ExpressionFunctionDefinition, any>; + +// Warning: (ae-missing-release-tag) "AnyExpressionTypeDefinition" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type AnyExpressionTypeDefinition = ExpressionTypeDefinition; + +// Warning: (ae-forgotten-export) The symbol "SingleArgumentType" needs to be exported by the entry point index.d.ts +// Warning: (ae-forgotten-export) The symbol "MultipleArgumentType" needs to be exported by the entry point index.d.ts +// Warning: (ae-forgotten-export) The symbol "UnresolvedSingleArgumentType" needs to be exported by the entry point index.d.ts +// Warning: (ae-forgotten-export) The symbol "UnresolvedMultipleArgumentType" needs to be exported by the entry point index.d.ts +// Warning: (ae-missing-release-tag) "ArgumentType" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export type ArgumentType = SingleArgumentType | MultipleArgumentType | UnresolvedSingleArgumentType | UnresolvedMultipleArgumentType; + +// Warning: (ae-missing-release-tag) "buildExpression" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export function buildExpression(initialState?: ExpressionAstFunctionBuilder[] | ExpressionAstExpression | string): ExpressionAstExpressionBuilder; + +// Warning: (ae-forgotten-export) The symbol "InferFunctionDefinition" needs to be exported by the entry point index.d.ts +// Warning: (ae-forgotten-export) The symbol "FunctionArgs" needs to be exported by the entry point index.d.ts +// Warning: (ae-missing-release-tag) "buildExpressionFunction" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export function buildExpressionFunction(fnName: InferFunctionDefinition['name'], +initialArgs: { + [K in keyof FunctionArgs]: FunctionArgs[K] | ExpressionAstExpressionBuilder | ExpressionAstExpressionBuilder[]; +}): ExpressionAstFunctionBuilder; + +// Warning: (ae-missing-release-tag) "Datatable" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export interface Datatable { + // (undocumented) + columns: DatatableColumn[]; + // (undocumented) + rows: DatatableRow[]; + // Warning: (ae-forgotten-export) The symbol "name" needs to be exported by the entry point index.d.ts + // + // (undocumented) + type: typeof name; +} + +// Warning: (ae-missing-release-tag) "DatatableColumn" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export interface DatatableColumn { + // (undocumented) + id: string; + // Warning: (ae-forgotten-export) The symbol "DatatableColumnMeta" needs to be exported by the entry point index.d.ts + // + // (undocumented) + meta: DatatableColumnMeta; + // (undocumented) + name: string; +} + +// Warning: (ae-missing-release-tag) "DatatableColumnType" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export type DatatableColumnType = 'string' | 'number' | 'boolean' | 'date' | 'null'; + +// Warning: (ae-missing-release-tag) "DatatableRow" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export type DatatableRow = Record; + +// Warning: (ae-forgotten-export) The symbol "Adapters" needs to be exported by the entry point index.d.ts +// Warning: (ae-forgotten-export) The symbol "DefaultInspectorAdapters" needs to be exported by the entry point index.d.ts +// Warning: (ae-missing-release-tag) "Execution" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export class Execution = Record, Input = unknown, Output = unknown, InspectorAdapters extends Adapters = ExtraContext['inspectorAdapters'] extends object ? ExtraContext['inspectorAdapters'] : DefaultInspectorAdapters> { + constructor(params: ExecutionParams); + cancel(): void; + // (undocumented) + cast(value: any, toTypeNames?: string[]): any; + readonly context: ExecutionContext & ExtraContext; + readonly contract: ExecutionContract; + // (undocumented) + readonly expression: string; + input: Input; + // (undocumented) + get inspectorAdapters(): InspectorAdapters; + // Warning: (ae-forgotten-export) The symbol "ExpressionExecOptions" needs to be exported by the entry point index.d.ts + // + // (undocumented) + interpret(ast: ExpressionAstNode, input: T, options?: ExpressionExecOptions): Promise; + // (undocumented) + invokeChain(chainArr: ExpressionAstFunction[], input: unknown): Promise; + // (undocumented) + invokeFunction(fn: ExpressionFunction, input: unknown, args: Record): Promise; + // (undocumented) + readonly params: ExecutionParams; + // (undocumented) + resolveArgs(fnDef: ExpressionFunction, input: unknown, argAsts: any): Promise; + // (undocumented) + get result(): Promise; + start(input?: Input): void; + readonly state: ExecutionContainer; +} + +// Warning: (ae-forgotten-export) The symbol "StateContainer" needs to be exported by the entry point index.d.ts +// Warning: (ae-forgotten-export) The symbol "ExecutionPureTransitions" needs to be exported by the entry point index.d.ts +// Warning: (ae-missing-release-tag) "ExecutionContainer" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type ExecutionContainer = StateContainer, ExecutionPureTransitions>; + +// Warning: (ae-missing-release-tag) "ExecutionContext" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export interface ExecutionContext { + abortSignal: AbortSignal; + getInitialInput: () => Input; + // Warning: (ae-forgotten-export) The symbol "SavedObjectAttributes" needs to be exported by the entry point index.d.ts + // Warning: (ae-forgotten-export) The symbol "SavedObject" needs to be exported by the entry point index.d.ts + getSavedObject?: (type: string, id: string) => Promise>; + inspectorAdapters: InspectorAdapters; + // Warning: (ae-forgotten-export) The symbol "ExecutionContextSearch" needs to be exported by the entry point index.d.ts + search?: ExecutionContextSearch; + types: Record; + variables: Record; +} + +// Warning: (ae-missing-release-tag) "ExecutionContract" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export class ExecutionContract = Record, Input = unknown, Output = unknown, InspectorAdapters = unknown> { + constructor(execution: Execution); + cancel: () => void; + // (undocumented) + protected readonly execution: Execution; + getAst: () => ExpressionAstExpression; + getData: () => Promise; + getExpression: () => string; + inspect: () => InspectorAdapters; + // (undocumented) + get isPending(): boolean; +} + +// Warning: (ae-missing-release-tag) "ExecutionParams" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export interface ExecutionParams = Record> { + // (undocumented) + ast?: ExpressionAstExpression; + // (undocumented) + context?: ExtraContext; + debug?: boolean; + // (undocumented) + executor: Executor; + // (undocumented) + expression?: string; +} + +// Warning: (ae-missing-release-tag) "ExecutionState" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export interface ExecutionState extends ExecutorState { + // (undocumented) + ast: ExpressionAstExpression; + error?: Error; + result?: Output; + state: 'not-started' | 'pending' | 'result' | 'error'; +} + +// Warning: (ae-missing-release-tag) "Executor" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export class Executor = Record> { + constructor(state?: ExecutorState); + // (undocumented) + get context(): Record; + // (undocumented) + createExecution = Record, Input = unknown, Output = unknown>(ast: string | ExpressionAstExpression, context?: ExtraContext, { debug }?: ExpressionExecOptions): Execution; + // (undocumented) + static createWithDefaults = Record>(state?: ExecutorState): Executor; + // (undocumented) + extendContext(extraContext: Record): void; + // (undocumented) + fork(): Executor; + // @deprecated (undocumented) + readonly functions: FunctionsRegistry; + // (undocumented) + getFunction(name: string): ExpressionFunction | undefined; + // (undocumented) + getFunctions(): Record; + // (undocumented) + getType(name: string): ExpressionType | undefined; + // (undocumented) + getTypes(): Record; + // (undocumented) + registerFunction(functionDefinition: AnyExpressionFunctionDefinition | (() => AnyExpressionFunctionDefinition)): void; + // (undocumented) + registerType(typeDefinition: AnyExpressionTypeDefinition | (() => AnyExpressionTypeDefinition)): void; + run = Record>(ast: string | ExpressionAstExpression, input: Input, context?: ExtraContext): Promise; + // (undocumented) + readonly state: ExecutorContainer; + // @deprecated (undocumented) + readonly types: TypesRegistry; +} + +// Warning: (ae-forgotten-export) The symbol "ExecutorPureTransitions" needs to be exported by the entry point index.d.ts +// Warning: (ae-forgotten-export) The symbol "ExecutorPureSelectors" needs to be exported by the entry point index.d.ts +// Warning: (ae-missing-release-tag) "ExecutorContainer" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type ExecutorContainer = Record> = StateContainer, ExecutorPureTransitions, ExecutorPureSelectors>; + +// Warning: (ae-missing-release-tag) "ExecutorState" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export interface ExecutorState = Record> { + // (undocumented) + context: Context; + // (undocumented) + functions: Record; + // (undocumented) + types: Record; +} + +// Warning: (ae-missing-release-tag) "ExpressionAstArgument" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type ExpressionAstArgument = string | boolean | number | ExpressionAstExpression; + +// Warning: (ae-missing-release-tag) "ExpressionAstExpression" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export interface ExpressionAstExpression { + // (undocumented) + chain: ExpressionAstFunction[]; + // (undocumented) + type: 'expression'; +} + +// Warning: (ae-missing-release-tag) "ExpressionAstExpressionBuilder" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export interface ExpressionAstExpressionBuilder { + findFunction: (fnName: InferFunctionDefinition['name']) => Array> | []; + functions: ExpressionAstFunctionBuilder[]; + toAst: () => ExpressionAstExpression; + toString: () => string; + type: 'expression_builder'; +} + +// Warning: (ae-missing-release-tag) "ExpressionAstFunction" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export interface ExpressionAstFunction { + // (undocumented) + arguments: Record; + // Warning: (ae-forgotten-export) The symbol "ExpressionAstFunctionDebug" needs to be exported by the entry point index.d.ts + debug?: ExpressionAstFunctionDebug; + // (undocumented) + function: string; + // (undocumented) + type: 'function'; +} + +// Warning: (ae-missing-release-tag) "ExpressionAstFunctionBuilder" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export interface ExpressionAstFunctionBuilder { + // Warning: (ae-forgotten-export) The symbol "FunctionArgName" needs to be exported by the entry point index.d.ts + addArgument: >(name: A, value: FunctionArgs[A] | ExpressionAstExpressionBuilder) => this; + // Warning: (ae-forgotten-export) The symbol "FunctionBuilderArguments" needs to be exported by the entry point index.d.ts + arguments: FunctionBuilderArguments; + getArgument: >(name: A) => Array[A] | ExpressionAstExpressionBuilder> | undefined; + name: InferFunctionDefinition['name']; + // Warning: (ae-forgotten-export) The symbol "OptionalKeys" needs to be exported by the entry point index.d.ts + removeArgument: >>(name: A) => this; + replaceArgument: >(name: A, value: Array[A] | ExpressionAstExpressionBuilder>) => this; + toAst: () => ExpressionAstFunction; + toString: () => string; + type: 'expression_function_builder'; +} + +// Warning: (ae-missing-release-tag) "ExpressionAstNode" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type ExpressionAstNode = ExpressionAstExpression | ExpressionAstFunction | ExpressionAstArgument; + +// Warning: (ae-missing-release-tag) "ExpressionExecutor" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public @deprecated (undocumented) +export interface ExpressionExecutor { + // Warning: (ae-forgotten-export) The symbol "ExpressionInterpreter" needs to be exported by the entry point index.d.ts + // + // (undocumented) + interpreter: ExpressionInterpreter; +} + +// Warning: (ae-missing-release-tag) "ExpressionFunction" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export class ExpressionFunction { + constructor(functionDefinition: AnyExpressionFunctionDefinition); + // (undocumented) + accepts: (type: string) => boolean; + aliases: string[]; + args: Record; + fn: (input: ExpressionValue, params: Record, handlers: object) => ExpressionValue; + help: string; + inputTypes: string[] | undefined; + name: string; + type: string; +} + +// Warning: (ae-missing-release-tag) "ExpressionFunctionDefinition" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export interface ExpressionFunctionDefinition, Output, Context extends ExecutionContext = ExecutionContext> { + aliases?: string[]; + args: { + [key in keyof Arguments]: ArgumentType; + }; + // @deprecated (undocumented) + context?: { + types: AnyExpressionFunctionDefinition['inputTypes']; + }; + fn(input: Input, args: Arguments, context: Context): Output; + help: string; + inputTypes?: Array>; + name: Name; + type?: TypeToString>; +} + +// @public +export interface ExpressionFunctionDefinitions { + // Warning: (ae-forgotten-export) The symbol "ExpressionFunctionClog" needs to be exported by the entry point index.d.ts + // + // (undocumented) + clog: ExpressionFunctionClog; + // Warning: (ae-forgotten-export) The symbol "ExpressionFunctionFont" needs to be exported by the entry point index.d.ts + // + // (undocumented) + font: ExpressionFunctionFont; + // (undocumented) + kibana: ExpressionFunctionKibana; + // Warning: (ae-forgotten-export) The symbol "ExpressionFunctionKibanaContext" needs to be exported by the entry point index.d.ts + // + // (undocumented) + kibana_context: ExpressionFunctionKibanaContext; + // Warning: (ae-forgotten-export) The symbol "ExpressionFunctionTheme" needs to be exported by the entry point index.d.ts + // + // (undocumented) + theme: ExpressionFunctionTheme; + // Warning: (ae-forgotten-export) The symbol "ExpressionFunctionVar" needs to be exported by the entry point index.d.ts + // + // (undocumented) + var: ExpressionFunctionVar; + // Warning: (ae-forgotten-export) The symbol "ExpressionFunctionVarSet" needs to be exported by the entry point index.d.ts + // + // (undocumented) + var_set: ExpressionFunctionVarSet; +} + +// Warning: (ae-missing-release-tag) "ExpressionFunctionKibana" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type ExpressionFunctionKibana = ExpressionFunctionDefinition<'kibana', ExpressionValueSearchContext | null, object, ExpressionValueSearchContext>; + +// Warning: (ae-missing-release-tag) "ExpressionFunctionParameter" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export class ExpressionFunctionParameter { + constructor(name: string, arg: ArgumentType); + // (undocumented) + accepts(type: string): boolean; + // (undocumented) + aliases: string[]; + // (undocumented) + default: any; + // (undocumented) + help: string; + // (undocumented) + multi: boolean; + // (undocumented) + name: string; + // (undocumented) + options: any[]; + // (undocumented) + required: boolean; + // (undocumented) + resolve: boolean; + // (undocumented) + types: string[]; +} + +// Warning: (ae-missing-release-tag) "ExpressionImage" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export interface ExpressionImage { + // (undocumented) + dataurl: string; + // (undocumented) + mode: string; + // (undocumented) + type: 'image'; +} + +// Warning: (ae-missing-release-tag) "ExpressionRenderDefinition" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export interface ExpressionRenderDefinition { + displayName?: string; + help?: string; + name: string; + render: (domNode: HTMLElement, config: Config, handlers: IInterpreterRenderHandlers) => void | Promise; + reuseDomNode: boolean; + validate?: () => undefined | Error; +} + +// Warning: (ae-missing-release-tag) "ExpressionRenderer" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export class ExpressionRenderer { + constructor(config: ExpressionRenderDefinition); + // (undocumented) + readonly displayName: string; + // (undocumented) + readonly help: string; + // (undocumented) + readonly name: string; + // (undocumented) + readonly render: ExpressionRenderDefinition['render']; + // (undocumented) + readonly reuseDomNode: boolean; + // (undocumented) + readonly validate: () => void | Error; +} + +// Warning: (ae-missing-release-tag) "ExpressionRendererComponent" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type ExpressionRendererComponent = React.FC; + +// Warning: (ae-missing-release-tag) "ExpressionRendererEvent" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export interface ExpressionRendererEvent { + // (undocumented) + data: any; + // (undocumented) + name: string; +} + +// Warning: (ae-missing-release-tag) "ExpressionRendererRegistry" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export class ExpressionRendererRegistry implements IRegistry { + // (undocumented) + get(id: string): ExpressionRenderer | null; + // Warning: (ae-forgotten-export) The symbol "AnyExpressionRenderDefinition" needs to be exported by the entry point index.d.ts + // + // (undocumented) + register(definition: AnyExpressionRenderDefinition | (() => AnyExpressionRenderDefinition)): void; + // (undocumented) + toArray(): ExpressionRenderer[]; + // (undocumented) + toJS(): Record; +} + +// Warning: (ae-missing-release-tag) "ExpressionRenderError" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export interface ExpressionRenderError extends Error { + // (undocumented) + type?: string; +} + +// Warning: (ae-missing-release-tag) "ExpressionRenderHandler" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export class ExpressionRenderHandler { + // Warning: (ae-forgotten-export) The symbol "ExpressionRenderHandlerParams" needs to be exported by the entry point index.d.ts + constructor(element: HTMLElement, { onRenderError }?: Partial); + // (undocumented) + destroy: () => void; + // (undocumented) + events$: Observable; + // (undocumented) + getElement: () => HTMLElement; + // (undocumented) + handleRenderError: (error: ExpressionRenderError) => void; + // (undocumented) + render$: Observable; + // (undocumented) + render: (data: any, uiState?: any) => Promise; + // Warning: (ae-forgotten-export) The symbol "UpdateValue" needs to be exported by the entry point index.d.ts + // + // (undocumented) + update$: Observable; + } + +// Warning: (ae-missing-release-tag) "ExpressionsPublicPlugin" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +class ExpressionsPublicPlugin implements Plugin_2 { + constructor(initializerContext: PluginInitializerContext_2); + // (undocumented) + setup(core: CoreSetup): ExpressionsSetup; + // (undocumented) + start(core: CoreStart): ExpressionsStart; + // (undocumented) + stop(): void; +} + +export { ExpressionsPublicPlugin } + +export { ExpressionsPublicPlugin as Plugin } + +// Warning: (ae-missing-release-tag) "ExpressionsService" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export class ExpressionsService { + // Warning: (ae-forgotten-export) The symbol "ExpressionServiceParams" needs to be exported by the entry point index.d.ts + constructor({ executor, renderers, }?: ExpressionServiceParams); + // (undocumented) + readonly execute: ExpressionsServiceStart['execute']; + // (undocumented) + readonly executor: Executor; + // (undocumented) + readonly fork: () => ExpressionsService; + // (undocumented) + readonly getFunction: ExpressionsServiceStart['getFunction']; + readonly getFunctions: () => ReturnType; + // (undocumented) + readonly getRenderer: ExpressionsServiceStart['getRenderer']; + readonly getRenderers: () => ReturnType; + // (undocumented) + readonly getType: ExpressionsServiceStart['getType']; + readonly getTypes: () => ReturnType; + readonly registerFunction: (functionDefinition: AnyExpressionFunctionDefinition | (() => AnyExpressionFunctionDefinition)) => void; + // (undocumented) + readonly registerRenderer: (definition: AnyExpressionRenderDefinition | (() => AnyExpressionRenderDefinition)) => void; + // (undocumented) + readonly registerType: (typeDefinition: AnyExpressionTypeDefinition | (() => AnyExpressionTypeDefinition)) => void; + // (undocumented) + readonly renderers: ExpressionRendererRegistry; + // (undocumented) + readonly run: ExpressionsServiceStart['run']; + setup(): ExpressionsServiceSetup; + start(): ExpressionsServiceStart; + // (undocumented) + stop(): void; +} + +// Warning: (ae-missing-release-tag) "ExpressionsServiceSetup" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export type ExpressionsServiceSetup = Pick; + +// Warning: (ae-missing-release-tag) "ExpressionsServiceStart" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export interface ExpressionsServiceStart { + execute: = Record>(ast: string | ExpressionAstExpression, input: Input, context?: ExtraContext) => ExecutionContract; + fork: () => ExpressionsService; + getFunction: (name: string) => ReturnType; + getRenderer: (name: string) => ReturnType; + getType: (name: string) => ReturnType; + run: = Record>(ast: string | ExpressionAstExpression, input: Input, context?: ExtraContext) => Promise; +} + +// Warning: (ae-missing-release-tag) "ExpressionsSetup" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export type ExpressionsSetup = ExpressionsServiceSetup; + +// Warning: (ae-missing-release-tag) "ExpressionsStart" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// Warning: (ae-unresolved-link) The @link reference could not be resolved: The package "kibana" does not have an export "ExpressionServiceStart" +// +// @public +export interface ExpressionsStart extends ExpressionsServiceStart { + // Warning: (ae-forgotten-export) The symbol "ExpressionLoader" needs to be exported by the entry point index.d.ts + // + // (undocumented) + ExpressionLoader: typeof ExpressionLoader; + // (undocumented) + ExpressionRenderHandler: typeof ExpressionRenderHandler; + // Warning: (ae-forgotten-export) The symbol "IExpressionLoader" needs to be exported by the entry point index.d.ts + // + // (undocumented) + loader: IExpressionLoader; + // (undocumented) + ReactExpressionRenderer: typeof ReactExpressionRenderer; + // Warning: (ae-forgotten-export) The symbol "render" needs to be exported by the entry point index.d.ts + // + // (undocumented) + render: typeof render; +} + +// Warning: (ae-missing-release-tag) "ExpressionType" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export class ExpressionType { + constructor(definition: AnyExpressionTypeDefinition); + // (undocumented) + castsFrom: (value: ExpressionValue) => boolean; + // (undocumented) + castsTo: (value: ExpressionValue) => boolean; + // (undocumented) + create: unknown; + // (undocumented) + deserialize?: (serialized: any) => ExpressionValue; + // (undocumented) + from: (value: ExpressionValue, types: Record) => any; + // (undocumented) + getFromFn: (typeName: string) => undefined | ExpressionValueConverter; + // (undocumented) + getToFn: (typeName: string) => undefined | ExpressionValueConverter; + help: string; + // (undocumented) + name: string; + serialize?: (value: ExpressionValue) => any; + // (undocumented) + to: (value: ExpressionValue, toTypeName: string, types: Record) => any; + validate: (type: any) => void | Error; +} + +// Warning: (ae-missing-release-tag) "ExpressionTypeDefinition" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export interface ExpressionTypeDefinition { + // (undocumented) + deserialize?: (type: SerializedType) => Value; + // (undocumented) + from?: { + [type: string]: ExpressionValueConverter; + }; + // (undocumented) + help?: string; + // (undocumented) + name: Name; + // (undocumented) + serialize?: (type: Value) => SerializedType; + // (undocumented) + to?: { + [type: string]: ExpressionValueConverter; + }; + // (undocumented) + validate?: (type: any) => void | Error; +} + +// Warning: (ae-missing-release-tag) "ExpressionTypeStyle" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export interface ExpressionTypeStyle { + // (undocumented) + css: string; + // Warning: (ae-forgotten-export) The symbol "CSSStyle" needs to be exported by the entry point index.d.ts + // + // (undocumented) + spec: CSSStyle; + // (undocumented) + type: 'style'; +} + +// Warning: (ae-missing-release-tag) "ExpressionValue" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type ExpressionValue = ExpressionValueUnboxed | ExpressionValueBoxed; + +// Warning: (ae-missing-release-tag) "ExpressionValueBoxed" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type ExpressionValueBoxed = { + type: Type; +} & Value; + +// Warning: (ae-missing-release-tag) "ExpressionValueConverter" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type ExpressionValueConverter = (input: I, availableTypes: Record) => O; + +// Warning: (ae-missing-release-tag) "ExpressionValueError" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type ExpressionValueError = ExpressionValueBoxed<'error', { + error: { + message: string; + type?: string; + name?: string; + stack?: string; + original?: Error; + }; + info?: unknown; +}>; + +// Warning: (ae-missing-release-tag) "ExpressionValueFilter" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export type ExpressionValueFilter = ExpressionValueBoxed<'filter', { + filterType?: string; + value?: string; + column?: string; + and: ExpressionValueFilter[]; + to?: string; + from?: string; + query?: string | null; +}>; + +// Warning: (ae-missing-release-tag) "ExpressionValueNum" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type ExpressionValueNum = ExpressionValueBoxed<'num', { + value: number; +}>; + +// Warning: (ae-forgotten-export) The symbol "name" needs to be exported by the entry point index.d.ts +// Warning: (ae-missing-release-tag) "ExpressionValueRender" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +type ExpressionValueRender = ExpressionValueBoxed; + +export { ExpressionValueRender } + +export { ExpressionValueRender as Render } + +// Warning: (ae-missing-release-tag) "ExpressionValueSearchContext" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type ExpressionValueSearchContext = ExpressionValueBoxed<'kibana_context', ExecutionContextSearch>; + +// Warning: (ae-missing-release-tag) "ExpressionValueUnboxed" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type ExpressionValueUnboxed = any; + +// Warning: (ae-missing-release-tag) "Font" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export interface Font { + // (undocumented) + label: FontLabel; + // (undocumented) + value: FontValue; +} + +// Warning: (ae-forgotten-export) The symbol "fonts" needs to be exported by the entry point index.d.ts +// Warning: (ae-missing-release-tag) "FontLabel" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export type FontLabel = typeof fonts[number]['label']; + +// Warning: (ae-missing-release-tag) "FontStyle" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export enum FontStyle { + // (undocumented) + ITALIC = "italic", + // (undocumented) + NORMAL = "normal" +} + +// Warning: (ae-missing-release-tag) "FontValue" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export type FontValue = typeof fonts[number]['value']; + +// Warning: (ae-missing-release-tag) "FontWeight" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export enum FontWeight { + // (undocumented) + BOLD = "bold", + // (undocumented) + BOLDER = "bolder", + // (undocumented) + EIGHT = "800", + // (undocumented) + FIVE = "500", + // (undocumented) + FOUR = "400", + // (undocumented) + LIGHTER = "lighter", + // (undocumented) + NINE = "900", + // (undocumented) + NORMAL = "normal", + // (undocumented) + ONE = "100", + // (undocumented) + SEVEN = "700", + // (undocumented) + SIX = "600", + // (undocumented) + THREE = "300", + // (undocumented) + TWO = "200" +} + +// Warning: (ae-missing-release-tag) "format" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export function format(ast: T, type: T extends ExpressionAstExpression ? 'expression' : 'argument'): string; + +// Warning: (ae-missing-release-tag) "formatExpression" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export function formatExpression(ast: ExpressionAstExpression): string; + +// Warning: (ae-missing-release-tag) "FunctionsRegistry" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export class FunctionsRegistry implements IRegistry { + constructor(executor: Executor); + // (undocumented) + get(id: string): ExpressionFunction | null; + // (undocumented) + register(functionDefinition: AnyExpressionFunctionDefinition | (() => AnyExpressionFunctionDefinition)): void; + // (undocumented) + toArray(): ExpressionFunction[]; + // (undocumented) + toJS(): Record; +} + +// Warning: (ae-missing-release-tag) "IExpressionLoaderParams" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export interface IExpressionLoaderParams { + // (undocumented) + context?: ExpressionValue; + // (undocumented) + customFunctions?: []; + // (undocumented) + customRenderers?: []; + // (undocumented) + disableCaching?: boolean; + // (undocumented) + inspectorAdapters?: Adapters; + // Warning: (ae-forgotten-export) The symbol "RenderErrorHandlerFnType" needs to be exported by the entry point index.d.ts + // + // (undocumented) + onRenderError?: RenderErrorHandlerFnType; + // (undocumented) + searchContext?: ExecutionContextSearch; + // (undocumented) + uiState?: unknown; + // (undocumented) + variables?: Record; +} + +// Warning: (ae-missing-release-tag) "IInterpreterRenderHandlers" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export interface IInterpreterRenderHandlers { + done: () => void; + // (undocumented) + event: (event: any) => void; + // (undocumented) + onDestroy: (fn: () => void) => void; + // (undocumented) + reload: () => void; + // (undocumented) + uiState?: PersistedState; + // (undocumented) + update: (params: any) => void; +} + +// Warning: (ae-missing-release-tag) "InterpreterErrorType" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public @deprecated (undocumented) +export type InterpreterErrorType = ExpressionValueError; + +// Warning: (ae-missing-release-tag) "IRegistry" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export interface IRegistry { + // (undocumented) + get(id: string): T | null; + // (undocumented) + toArray(): T[]; + // (undocumented) + toJS(): Record; +} + +// Warning: (ae-missing-release-tag) "isExpressionAstBuilder" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export function isExpressionAstBuilder(val: any): val is ExpressionAstExpressionBuilder; + +// Warning: (ae-missing-release-tag) "KIBANA_CONTEXT_NAME" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type KIBANA_CONTEXT_NAME = 'kibana_context'; + +// Warning: (ae-missing-release-tag) "KibanaContext" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type KibanaContext = ExpressionValueSearchContext; + +// Warning: (ae-missing-release-tag) "KibanaDatatable" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export interface KibanaDatatable { + // (undocumented) + columns: KibanaDatatableColumn[]; + // (undocumented) + rows: KibanaDatatableRow[]; + // Warning: (ae-forgotten-export) The symbol "name" needs to be exported by the entry point index.d.ts + // + // (undocumented) + type: typeof name_3; +} + +// Warning: (ae-missing-release-tag) "KibanaDatatableColumn" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export interface KibanaDatatableColumn { + // (undocumented) + formatHint?: SerializedFieldFormat; + // (undocumented) + id: string; + // (undocumented) + meta?: KibanaDatatableColumnMeta; + // (undocumented) + name: string; +} + +// Warning: (ae-missing-release-tag) "KibanaDatatableColumnMeta" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export interface KibanaDatatableColumnMeta { + // (undocumented) + aggConfigParams?: Record; + // (undocumented) + indexPatternId?: string; + // (undocumented) + type: string; +} + +// Warning: (ae-missing-release-tag) "KibanaDatatableRow" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export interface KibanaDatatableRow { + // (undocumented) + [key: string]: unknown; +} + +// Warning: (ae-missing-release-tag) "KnownTypeToString" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export type KnownTypeToString = T extends string ? 'string' : T extends boolean ? 'boolean' : T extends number ? 'number' : T extends null ? 'null' : T extends { + type: string; +} ? T['type'] : never; + +// Warning: (ae-missing-release-tag) "Overflow" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export enum Overflow { + // (undocumented) + AUTO = "auto", + // (undocumented) + HIDDEN = "hidden", + // (undocumented) + SCROLL = "scroll", + // (undocumented) + VISIBLE = "visible" +} + +// Warning: (ae-missing-release-tag) "parse" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export function parse(expression: E, startRule: S): S extends 'expression' ? ExpressionAstExpression : ExpressionAstArgument; + +// Warning: (ae-missing-release-tag) "parseExpression" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export function parseExpression(expression: string): ExpressionAstExpression; + +// Warning: (ae-forgotten-export) The symbol "PluginInitializerContext" needs to be exported by the entry point index.d.ts +// Warning: (ae-missing-release-tag) "plugin" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export function plugin(initializerContext: PluginInitializerContext): ExpressionsPublicPlugin; + +// Warning: (ae-missing-release-tag) "PointSeries" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export type PointSeries = ExpressionValueBoxed<'pointseries', { + columns: PointSeriesColumns; + rows: PointSeriesRow[]; +}>; + +// Warning: (ae-missing-release-tag) "PointSeriesColumn" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export interface PointSeriesColumn { + // (undocumented) + expression: string; + // (undocumented) + role: 'measure' | 'dimension'; + // (undocumented) + type: 'number' | 'string'; +} + +// Warning: (ae-missing-release-tag) "PointSeriesColumnName" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export type PointSeriesColumnName = 'x' | 'y' | 'color' | 'size' | 'text'; + +// Warning: (ae-missing-release-tag) "PointSeriesColumns" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export type PointSeriesColumns = Record | {}; + +// Warning: (ae-missing-release-tag) "PointSeriesRow" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type PointSeriesRow = Record; + +// Warning: (ae-missing-release-tag) "Range" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export interface Range { + // (undocumented) + from: number; + // (undocumented) + to: number; + // Warning: (ae-forgotten-export) The symbol "name" needs to be exported by the entry point index.d.ts + // + // (undocumented) + type: typeof name_4; +} + +// Warning: (ae-missing-release-tag) "ReactExpressionRenderer" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export const ReactExpressionRenderer: ({ className, dataAttrs, padding, renderError, expression, onEvent, reload$, ...expressionLoaderOptions }: ReactExpressionRendererProps) => JSX.Element; + +// Warning: (ae-missing-release-tag) "ReactExpressionRendererProps" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export interface ReactExpressionRendererProps extends IExpressionLoaderParams { + // (undocumented) + className?: string; + // (undocumented) + dataAttrs?: string[]; + // (undocumented) + expression: string | ExpressionAstExpression; + // (undocumented) + onEvent?: (event: ExpressionRendererEvent) => void; + // (undocumented) + padding?: 'xs' | 's' | 'm' | 'l' | 'xl'; + reload$?: Observable; + // (undocumented) + renderError?: (error?: string | null) => React.ReactElement | React.ReactElement[]; +} + +// Warning: (ae-missing-release-tag) "ReactExpressionRendererType" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type ReactExpressionRendererType = React.ComponentType; + +// Warning: (ae-missing-release-tag) "SerializedDatatable" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export interface SerializedDatatable extends Datatable { + // (undocumented) + rows: string[][]; +} + +// Warning: (ae-missing-release-tag) "SerializedFieldFormat" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export interface SerializedFieldFormat> { + // (undocumented) + id?: string; + // (undocumented) + params?: TParams; +} + +// Warning: (ae-missing-release-tag) "Style" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type Style = ExpressionTypeStyle; + +// Warning: (ae-missing-release-tag) "TextAlignment" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export enum TextAlignment { + // (undocumented) + CENTER = "center", + // (undocumented) + JUSTIFY = "justify", + // (undocumented) + LEFT = "left", + // (undocumented) + RIGHT = "right" +} + +// Warning: (ae-missing-release-tag) "TextDecoration" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export enum TextDecoration { + // (undocumented) + NONE = "none", + // (undocumented) + UNDERLINE = "underline" +} + +// Warning: (ae-missing-release-tag) "TypesRegistry" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export class TypesRegistry implements IRegistry { + constructor(executor: Executor); + // (undocumented) + get(id: string): ExpressionType | null; + // (undocumented) + register(typeDefinition: AnyExpressionTypeDefinition | (() => AnyExpressionTypeDefinition)): void; + // (undocumented) + toArray(): ExpressionType[]; + // (undocumented) + toJS(): Record; +} + +// Warning: (ae-missing-release-tag) "TypeString" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export type TypeString = KnownTypeToString>; + +// Warning: (ae-missing-release-tag) "TypeToString" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export type TypeToString = KnownTypeToString | UnmappedTypeStrings; + +// Warning: (ae-missing-release-tag) "UnmappedTypeStrings" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export type UnmappedTypeStrings = 'date' | 'filter'; + + +// (No @packageDocumentation comment for this package) + +``` diff --git a/src/plugins/expressions/server/mocks.ts b/src/plugins/expressions/server/mocks.ts index 0512789d76ab0..0beb4750c0d10 100644 --- a/src/plugins/expressions/server/mocks.ts +++ b/src/plugins/expressions/server/mocks.ts @@ -46,11 +46,8 @@ const createStartContract = (): Start => { execute: jest.fn(), fork: jest.fn(), getFunction: jest.fn(), - getFunctions: jest.fn(), getRenderer: jest.fn(), - getRenderers: jest.fn(), getType: jest.fn(), - getTypes: jest.fn(), run: jest.fn(), }; diff --git a/src/plugins/expressions/server/server.api.md b/src/plugins/expressions/server/server.api.md new file mode 100644 index 0000000000000..8266789664d44 --- /dev/null +++ b/src/plugins/expressions/server/server.api.md @@ -0,0 +1,971 @@ +## API Report File for "kibana" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts + +import { CoreSetup } from 'src/core/server'; +import { CoreStart } from 'src/core/server'; +import { Ensure } from '@kbn/utility-types'; +import { EventEmitter } from 'events'; +import { Observable } from 'rxjs'; +import { PersistedState } from 'src/plugins/visualizations/public'; +import { Plugin as Plugin_2 } from 'src/core/server'; +import { PluginInitializerContext } from 'src/core/server'; +import { UnwrapPromiseOrReturn } from '@kbn/utility-types'; + +// Warning: (ae-missing-release-tag) "AnyExpressionFunctionDefinition" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export type AnyExpressionFunctionDefinition = ExpressionFunctionDefinition, any>; + +// Warning: (ae-missing-release-tag) "AnyExpressionTypeDefinition" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type AnyExpressionTypeDefinition = ExpressionTypeDefinition; + +// Warning: (ae-forgotten-export) The symbol "SingleArgumentType" needs to be exported by the entry point index.d.ts +// Warning: (ae-forgotten-export) The symbol "MultipleArgumentType" needs to be exported by the entry point index.d.ts +// Warning: (ae-forgotten-export) The symbol "UnresolvedSingleArgumentType" needs to be exported by the entry point index.d.ts +// Warning: (ae-forgotten-export) The symbol "UnresolvedMultipleArgumentType" needs to be exported by the entry point index.d.ts +// Warning: (ae-missing-release-tag) "ArgumentType" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export type ArgumentType = SingleArgumentType | MultipleArgumentType | UnresolvedSingleArgumentType | UnresolvedMultipleArgumentType; + +// Warning: (ae-missing-release-tag) "buildExpression" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export function buildExpression(initialState?: ExpressionAstFunctionBuilder[] | ExpressionAstExpression | string): ExpressionAstExpressionBuilder; + +// Warning: (ae-forgotten-export) The symbol "InferFunctionDefinition" needs to be exported by the entry point index.d.ts +// Warning: (ae-forgotten-export) The symbol "FunctionArgs" needs to be exported by the entry point index.d.ts +// Warning: (ae-missing-release-tag) "buildExpressionFunction" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export function buildExpressionFunction(fnName: InferFunctionDefinition['name'], +initialArgs: { + [K in keyof FunctionArgs]: FunctionArgs[K] | ExpressionAstExpressionBuilder | ExpressionAstExpressionBuilder[]; +}): ExpressionAstFunctionBuilder; + +// Warning: (ae-missing-release-tag) "Datatable" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export interface Datatable { + // (undocumented) + columns: DatatableColumn[]; + // (undocumented) + rows: DatatableRow[]; + // Warning: (ae-forgotten-export) The symbol "name" needs to be exported by the entry point index.d.ts + // + // (undocumented) + type: typeof name; +} + +// Warning: (ae-missing-release-tag) "DatatableColumn" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export interface DatatableColumn { + // (undocumented) + id: string; + // Warning: (ae-forgotten-export) The symbol "DatatableColumnMeta" needs to be exported by the entry point index.d.ts + // + // (undocumented) + meta: DatatableColumnMeta; + // (undocumented) + name: string; +} + +// Warning: (ae-missing-release-tag) "DatatableColumnType" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export type DatatableColumnType = 'string' | 'number' | 'boolean' | 'date' | 'null'; + +// Warning: (ae-missing-release-tag) "DatatableRow" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export type DatatableRow = Record; + +// Warning: (ae-forgotten-export) The symbol "Adapters" needs to be exported by the entry point index.d.ts +// Warning: (ae-forgotten-export) The symbol "DefaultInspectorAdapters" needs to be exported by the entry point index.d.ts +// Warning: (ae-missing-release-tag) "Execution" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export class Execution = Record, Input = unknown, Output = unknown, InspectorAdapters extends Adapters = ExtraContext['inspectorAdapters'] extends object ? ExtraContext['inspectorAdapters'] : DefaultInspectorAdapters> { + constructor(params: ExecutionParams); + cancel(): void; + // (undocumented) + cast(value: any, toTypeNames?: string[]): any; + readonly context: ExecutionContext & ExtraContext; + // Warning: (ae-forgotten-export) The symbol "ExecutionContract" needs to be exported by the entry point index.d.ts + readonly contract: ExecutionContract; + // (undocumented) + readonly expression: string; + input: Input; + // (undocumented) + get inspectorAdapters(): InspectorAdapters; + // Warning: (ae-forgotten-export) The symbol "ExpressionExecOptions" needs to be exported by the entry point index.d.ts + // + // (undocumented) + interpret(ast: ExpressionAstNode, input: T, options?: ExpressionExecOptions): Promise; + // (undocumented) + invokeChain(chainArr: ExpressionAstFunction[], input: unknown): Promise; + // (undocumented) + invokeFunction(fn: ExpressionFunction, input: unknown, args: Record): Promise; + // (undocumented) + readonly params: ExecutionParams; + // (undocumented) + resolveArgs(fnDef: ExpressionFunction, input: unknown, argAsts: any): Promise; + // (undocumented) + get result(): Promise; + start(input?: Input): void; + readonly state: ExecutionContainer; +} + +// Warning: (ae-forgotten-export) The symbol "StateContainer" needs to be exported by the entry point index.d.ts +// Warning: (ae-forgotten-export) The symbol "ExecutionPureTransitions" needs to be exported by the entry point index.d.ts +// Warning: (ae-missing-release-tag) "ExecutionContainer" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type ExecutionContainer = StateContainer, ExecutionPureTransitions>; + +// Warning: (ae-missing-release-tag) "ExecutionContext" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export interface ExecutionContext { + abortSignal: AbortSignal; + getInitialInput: () => Input; + // Warning: (ae-forgotten-export) The symbol "SavedObjectAttributes" needs to be exported by the entry point index.d.ts + // Warning: (ae-forgotten-export) The symbol "SavedObject" needs to be exported by the entry point index.d.ts + getSavedObject?: (type: string, id: string) => Promise>; + inspectorAdapters: InspectorAdapters; + // Warning: (ae-forgotten-export) The symbol "ExecutionContextSearch" needs to be exported by the entry point index.d.ts + search?: ExecutionContextSearch; + types: Record; + variables: Record; +} + +// Warning: (ae-missing-release-tag) "ExecutionParams" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export interface ExecutionParams = Record> { + // (undocumented) + ast?: ExpressionAstExpression; + // (undocumented) + context?: ExtraContext; + debug?: boolean; + // (undocumented) + executor: Executor; + // (undocumented) + expression?: string; +} + +// Warning: (ae-missing-release-tag) "ExecutionState" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export interface ExecutionState extends ExecutorState { + // (undocumented) + ast: ExpressionAstExpression; + error?: Error; + result?: Output; + state: 'not-started' | 'pending' | 'result' | 'error'; +} + +// Warning: (ae-missing-release-tag) "Executor" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export class Executor = Record> { + constructor(state?: ExecutorState); + // (undocumented) + get context(): Record; + // (undocumented) + createExecution = Record, Input = unknown, Output = unknown>(ast: string | ExpressionAstExpression, context?: ExtraContext, { debug }?: ExpressionExecOptions): Execution; + // (undocumented) + static createWithDefaults = Record>(state?: ExecutorState): Executor; + // (undocumented) + extendContext(extraContext: Record): void; + // (undocumented) + fork(): Executor; + // @deprecated (undocumented) + readonly functions: FunctionsRegistry; + // (undocumented) + getFunction(name: string): ExpressionFunction | undefined; + // (undocumented) + getFunctions(): Record; + // (undocumented) + getType(name: string): ExpressionType | undefined; + // (undocumented) + getTypes(): Record; + // (undocumented) + registerFunction(functionDefinition: AnyExpressionFunctionDefinition | (() => AnyExpressionFunctionDefinition)): void; + // (undocumented) + registerType(typeDefinition: AnyExpressionTypeDefinition | (() => AnyExpressionTypeDefinition)): void; + run = Record>(ast: string | ExpressionAstExpression, input: Input, context?: ExtraContext): Promise; + // (undocumented) + readonly state: ExecutorContainer; + // @deprecated (undocumented) + readonly types: TypesRegistry; +} + +// Warning: (ae-forgotten-export) The symbol "ExecutorPureTransitions" needs to be exported by the entry point index.d.ts +// Warning: (ae-forgotten-export) The symbol "ExecutorPureSelectors" needs to be exported by the entry point index.d.ts +// Warning: (ae-missing-release-tag) "ExecutorContainer" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type ExecutorContainer = Record> = StateContainer, ExecutorPureTransitions, ExecutorPureSelectors>; + +// Warning: (ae-missing-release-tag) "ExecutorState" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export interface ExecutorState = Record> { + // (undocumented) + context: Context; + // (undocumented) + functions: Record; + // (undocumented) + types: Record; +} + +// Warning: (ae-missing-release-tag) "ExpressionAstArgument" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type ExpressionAstArgument = string | boolean | number | ExpressionAstExpression; + +// Warning: (ae-missing-release-tag) "ExpressionAstExpression" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export interface ExpressionAstExpression { + // (undocumented) + chain: ExpressionAstFunction[]; + // (undocumented) + type: 'expression'; +} + +// Warning: (ae-missing-release-tag) "ExpressionAstExpressionBuilder" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export interface ExpressionAstExpressionBuilder { + findFunction: (fnName: InferFunctionDefinition['name']) => Array> | []; + functions: ExpressionAstFunctionBuilder[]; + toAst: () => ExpressionAstExpression; + toString: () => string; + type: 'expression_builder'; +} + +// Warning: (ae-missing-release-tag) "ExpressionAstFunction" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export interface ExpressionAstFunction { + // (undocumented) + arguments: Record; + // Warning: (ae-forgotten-export) The symbol "ExpressionAstFunctionDebug" needs to be exported by the entry point index.d.ts + debug?: ExpressionAstFunctionDebug; + // (undocumented) + function: string; + // (undocumented) + type: 'function'; +} + +// Warning: (ae-missing-release-tag) "ExpressionAstFunctionBuilder" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export interface ExpressionAstFunctionBuilder { + // Warning: (ae-forgotten-export) The symbol "FunctionArgName" needs to be exported by the entry point index.d.ts + addArgument: >(name: A, value: FunctionArgs[A] | ExpressionAstExpressionBuilder) => this; + // Warning: (ae-forgotten-export) The symbol "FunctionBuilderArguments" needs to be exported by the entry point index.d.ts + arguments: FunctionBuilderArguments; + getArgument: >(name: A) => Array[A] | ExpressionAstExpressionBuilder> | undefined; + name: InferFunctionDefinition['name']; + // Warning: (ae-forgotten-export) The symbol "OptionalKeys" needs to be exported by the entry point index.d.ts + removeArgument: >>(name: A) => this; + replaceArgument: >(name: A, value: Array[A] | ExpressionAstExpressionBuilder>) => this; + toAst: () => ExpressionAstFunction; + toString: () => string; + type: 'expression_function_builder'; +} + +// Warning: (ae-missing-release-tag) "ExpressionAstNode" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type ExpressionAstNode = ExpressionAstExpression | ExpressionAstFunction | ExpressionAstArgument; + +// Warning: (ae-missing-release-tag) "ExpressionFunction" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export class ExpressionFunction { + constructor(functionDefinition: AnyExpressionFunctionDefinition); + // (undocumented) + accepts: (type: string) => boolean; + aliases: string[]; + args: Record; + fn: (input: ExpressionValue, params: Record, handlers: object) => ExpressionValue; + help: string; + inputTypes: string[] | undefined; + name: string; + type: string; +} + +// Warning: (ae-missing-release-tag) "ExpressionFunctionDefinition" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export interface ExpressionFunctionDefinition, Output, Context extends ExecutionContext = ExecutionContext> { + aliases?: string[]; + args: { + [key in keyof Arguments]: ArgumentType; + }; + // @deprecated (undocumented) + context?: { + types: AnyExpressionFunctionDefinition['inputTypes']; + }; + fn(input: Input, args: Arguments, context: Context): Output; + help: string; + inputTypes?: Array>; + name: Name; + type?: TypeToString>; +} + +// @public +export interface ExpressionFunctionDefinitions { + // Warning: (ae-forgotten-export) The symbol "ExpressionFunctionClog" needs to be exported by the entry point index.d.ts + // + // (undocumented) + clog: ExpressionFunctionClog; + // Warning: (ae-forgotten-export) The symbol "ExpressionFunctionFont" needs to be exported by the entry point index.d.ts + // + // (undocumented) + font: ExpressionFunctionFont; + // (undocumented) + kibana: ExpressionFunctionKibana; + // Warning: (ae-forgotten-export) The symbol "ExpressionFunctionKibanaContext" needs to be exported by the entry point index.d.ts + // + // (undocumented) + kibana_context: ExpressionFunctionKibanaContext; + // Warning: (ae-forgotten-export) The symbol "ExpressionFunctionTheme" needs to be exported by the entry point index.d.ts + // + // (undocumented) + theme: ExpressionFunctionTheme; + // Warning: (ae-forgotten-export) The symbol "ExpressionFunctionVar" needs to be exported by the entry point index.d.ts + // + // (undocumented) + var: ExpressionFunctionVar; + // Warning: (ae-forgotten-export) The symbol "ExpressionFunctionVarSet" needs to be exported by the entry point index.d.ts + // + // (undocumented) + var_set: ExpressionFunctionVarSet; +} + +// Warning: (ae-missing-release-tag) "ExpressionFunctionKibana" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type ExpressionFunctionKibana = ExpressionFunctionDefinition<'kibana', ExpressionValueSearchContext | null, object, ExpressionValueSearchContext>; + +// Warning: (ae-missing-release-tag) "ExpressionFunctionParameter" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export class ExpressionFunctionParameter { + constructor(name: string, arg: ArgumentType); + // (undocumented) + accepts(type: string): boolean; + // (undocumented) + aliases: string[]; + // (undocumented) + default: any; + // (undocumented) + help: string; + // (undocumented) + multi: boolean; + // (undocumented) + name: string; + // (undocumented) + options: any[]; + // (undocumented) + required: boolean; + // (undocumented) + resolve: boolean; + // (undocumented) + types: string[]; +} + +// Warning: (ae-missing-release-tag) "ExpressionImage" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export interface ExpressionImage { + // (undocumented) + dataurl: string; + // (undocumented) + mode: string; + // (undocumented) + type: 'image'; +} + +// Warning: (ae-missing-release-tag) "ExpressionRenderDefinition" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export interface ExpressionRenderDefinition { + displayName?: string; + help?: string; + name: string; + render: (domNode: HTMLElement, config: Config, handlers: IInterpreterRenderHandlers) => void | Promise; + reuseDomNode: boolean; + validate?: () => undefined | Error; +} + +// Warning: (ae-missing-release-tag) "ExpressionRenderer" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export class ExpressionRenderer { + constructor(config: ExpressionRenderDefinition); + // (undocumented) + readonly displayName: string; + // (undocumented) + readonly help: string; + // (undocumented) + readonly name: string; + // (undocumented) + readonly render: ExpressionRenderDefinition['render']; + // (undocumented) + readonly reuseDomNode: boolean; + // (undocumented) + readonly validate: () => void | Error; +} + +// Warning: (ae-missing-release-tag) "ExpressionRendererRegistry" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export class ExpressionRendererRegistry implements IRegistry { + // (undocumented) + get(id: string): ExpressionRenderer | null; + // Warning: (ae-forgotten-export) The symbol "AnyExpressionRenderDefinition" needs to be exported by the entry point index.d.ts + // + // (undocumented) + register(definition: AnyExpressionRenderDefinition | (() => AnyExpressionRenderDefinition)): void; + // (undocumented) + toArray(): ExpressionRenderer[]; + // (undocumented) + toJS(): Record; +} + +// Warning: (ae-missing-release-tag) "ExpressionsServerPlugin" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +class ExpressionsServerPlugin implements Plugin_2 { + constructor(initializerContext: PluginInitializerContext); + // Warning: (ae-forgotten-export) The symbol "ExpressionsService" needs to be exported by the entry point index.d.ts + // + // (undocumented) + readonly expressions: ExpressionsService; + // (undocumented) + setup(core: CoreSetup): ExpressionsServerSetup; + // (undocumented) + start(core: CoreStart): ExpressionsServerStart; + // (undocumented) + stop(): void; +} + +export { ExpressionsServerPlugin } + +export { ExpressionsServerPlugin as Plugin } + +// Warning: (ae-forgotten-export) The symbol "ExpressionsServiceSetup" needs to be exported by the entry point index.d.ts +// Warning: (ae-missing-release-tag) "ExpressionsServerSetup" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type ExpressionsServerSetup = ExpressionsServiceSetup; + +// Warning: (ae-forgotten-export) The symbol "ExpressionsServiceStart" needs to be exported by the entry point index.d.ts +// Warning: (ae-missing-release-tag) "ExpressionsServerStart" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type ExpressionsServerStart = ExpressionsServiceStart; + +// Warning: (ae-missing-release-tag) "ExpressionType" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export class ExpressionType { + constructor(definition: AnyExpressionTypeDefinition); + // (undocumented) + castsFrom: (value: ExpressionValue) => boolean; + // (undocumented) + castsTo: (value: ExpressionValue) => boolean; + // (undocumented) + create: unknown; + // (undocumented) + deserialize?: (serialized: any) => ExpressionValue; + // (undocumented) + from: (value: ExpressionValue, types: Record) => any; + // (undocumented) + getFromFn: (typeName: string) => undefined | ExpressionValueConverter; + // (undocumented) + getToFn: (typeName: string) => undefined | ExpressionValueConverter; + help: string; + // (undocumented) + name: string; + serialize?: (value: ExpressionValue) => any; + // (undocumented) + to: (value: ExpressionValue, toTypeName: string, types: Record) => any; + validate: (type: any) => void | Error; +} + +// Warning: (ae-missing-release-tag) "ExpressionTypeDefinition" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export interface ExpressionTypeDefinition { + // (undocumented) + deserialize?: (type: SerializedType) => Value; + // (undocumented) + from?: { + [type: string]: ExpressionValueConverter; + }; + // (undocumented) + help?: string; + // (undocumented) + name: Name; + // (undocumented) + serialize?: (type: Value) => SerializedType; + // (undocumented) + to?: { + [type: string]: ExpressionValueConverter; + }; + // (undocumented) + validate?: (type: any) => void | Error; +} + +// Warning: (ae-missing-release-tag) "ExpressionTypeStyle" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export interface ExpressionTypeStyle { + // (undocumented) + css: string; + // Warning: (ae-forgotten-export) The symbol "CSSStyle" needs to be exported by the entry point index.d.ts + // + // (undocumented) + spec: CSSStyle; + // (undocumented) + type: 'style'; +} + +// Warning: (ae-missing-release-tag) "ExpressionValue" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type ExpressionValue = ExpressionValueUnboxed | ExpressionValueBoxed; + +// Warning: (ae-missing-release-tag) "ExpressionValueBoxed" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type ExpressionValueBoxed = { + type: Type; +} & Value; + +// Warning: (ae-missing-release-tag) "ExpressionValueConverter" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type ExpressionValueConverter = (input: I, availableTypes: Record) => O; + +// Warning: (ae-missing-release-tag) "ExpressionValueError" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type ExpressionValueError = ExpressionValueBoxed<'error', { + error: { + message: string; + type?: string; + name?: string; + stack?: string; + original?: Error; + }; + info?: unknown; +}>; + +// Warning: (ae-missing-release-tag) "ExpressionValueFilter" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export type ExpressionValueFilter = ExpressionValueBoxed<'filter', { + filterType?: string; + value?: string; + column?: string; + and: ExpressionValueFilter[]; + to?: string; + from?: string; + query?: string | null; +}>; + +// Warning: (ae-missing-release-tag) "ExpressionValueNum" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type ExpressionValueNum = ExpressionValueBoxed<'num', { + value: number; +}>; + +// Warning: (ae-forgotten-export) The symbol "name" needs to be exported by the entry point index.d.ts +// Warning: (ae-missing-release-tag) "ExpressionValueRender" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +type ExpressionValueRender = ExpressionValueBoxed; + +export { ExpressionValueRender } + +export { ExpressionValueRender as Render } + +// Warning: (ae-missing-release-tag) "ExpressionValueSearchContext" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type ExpressionValueSearchContext = ExpressionValueBoxed<'kibana_context', ExecutionContextSearch>; + +// Warning: (ae-missing-release-tag) "ExpressionValueUnboxed" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type ExpressionValueUnboxed = any; + +// Warning: (ae-missing-release-tag) "Font" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export interface Font { + // (undocumented) + label: FontLabel; + // (undocumented) + value: FontValue; +} + +// Warning: (ae-forgotten-export) The symbol "fonts" needs to be exported by the entry point index.d.ts +// Warning: (ae-missing-release-tag) "FontLabel" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export type FontLabel = typeof fonts[number]['label']; + +// Warning: (ae-missing-release-tag) "FontStyle" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export enum FontStyle { + // (undocumented) + ITALIC = "italic", + // (undocumented) + NORMAL = "normal" +} + +// Warning: (ae-missing-release-tag) "FontValue" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export type FontValue = typeof fonts[number]['value']; + +// Warning: (ae-missing-release-tag) "FontWeight" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export enum FontWeight { + // (undocumented) + BOLD = "bold", + // (undocumented) + BOLDER = "bolder", + // (undocumented) + EIGHT = "800", + // (undocumented) + FIVE = "500", + // (undocumented) + FOUR = "400", + // (undocumented) + LIGHTER = "lighter", + // (undocumented) + NINE = "900", + // (undocumented) + NORMAL = "normal", + // (undocumented) + ONE = "100", + // (undocumented) + SEVEN = "700", + // (undocumented) + SIX = "600", + // (undocumented) + THREE = "300", + // (undocumented) + TWO = "200" +} + +// Warning: (ae-missing-release-tag) "format" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export function format(ast: T, type: T extends ExpressionAstExpression ? 'expression' : 'argument'): string; + +// Warning: (ae-missing-release-tag) "formatExpression" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export function formatExpression(ast: ExpressionAstExpression): string; + +// Warning: (ae-missing-release-tag) "FunctionsRegistry" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export class FunctionsRegistry implements IRegistry { + constructor(executor: Executor); + // (undocumented) + get(id: string): ExpressionFunction | null; + // (undocumented) + register(functionDefinition: AnyExpressionFunctionDefinition | (() => AnyExpressionFunctionDefinition)): void; + // (undocumented) + toArray(): ExpressionFunction[]; + // (undocumented) + toJS(): Record; +} + +// Warning: (ae-missing-release-tag) "IInterpreterRenderHandlers" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export interface IInterpreterRenderHandlers { + done: () => void; + // (undocumented) + event: (event: any) => void; + // (undocumented) + onDestroy: (fn: () => void) => void; + // (undocumented) + reload: () => void; + // (undocumented) + uiState?: PersistedState; + // (undocumented) + update: (params: any) => void; +} + +// Warning: (ae-missing-release-tag) "InterpreterErrorType" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public @deprecated (undocumented) +export type InterpreterErrorType = ExpressionValueError; + +// Warning: (ae-missing-release-tag) "IRegistry" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export interface IRegistry { + // (undocumented) + get(id: string): T | null; + // (undocumented) + toArray(): T[]; + // (undocumented) + toJS(): Record; +} + +// Warning: (ae-missing-release-tag) "isExpressionAstBuilder" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export function isExpressionAstBuilder(val: any): val is ExpressionAstExpressionBuilder; + +// Warning: (ae-missing-release-tag) "KIBANA_CONTEXT_NAME" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type KIBANA_CONTEXT_NAME = 'kibana_context'; + +// Warning: (ae-missing-release-tag) "KibanaContext" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type KibanaContext = ExpressionValueSearchContext; + +// Warning: (ae-missing-release-tag) "KibanaDatatable" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export interface KibanaDatatable { + // (undocumented) + columns: KibanaDatatableColumn[]; + // (undocumented) + rows: KibanaDatatableRow[]; + // Warning: (ae-forgotten-export) The symbol "name" needs to be exported by the entry point index.d.ts + // + // (undocumented) + type: typeof name_3; +} + +// Warning: (ae-missing-release-tag) "KibanaDatatableColumn" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export interface KibanaDatatableColumn { + // (undocumented) + formatHint?: SerializedFieldFormat; + // (undocumented) + id: string; + // (undocumented) + meta?: KibanaDatatableColumnMeta; + // (undocumented) + name: string; +} + +// Warning: (ae-missing-release-tag) "KibanaDatatableColumnMeta" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export interface KibanaDatatableColumnMeta { + // (undocumented) + aggConfigParams?: Record; + // (undocumented) + indexPatternId?: string; + // (undocumented) + type: string; +} + +// Warning: (ae-missing-release-tag) "KibanaDatatableRow" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export interface KibanaDatatableRow { + // (undocumented) + [key: string]: unknown; +} + +// Warning: (ae-missing-release-tag) "KnownTypeToString" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export type KnownTypeToString = T extends string ? 'string' : T extends boolean ? 'boolean' : T extends number ? 'number' : T extends null ? 'null' : T extends { + type: string; +} ? T['type'] : never; + +// Warning: (ae-missing-release-tag) "Overflow" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export enum Overflow { + // (undocumented) + AUTO = "auto", + // (undocumented) + HIDDEN = "hidden", + // (undocumented) + SCROLL = "scroll", + // (undocumented) + VISIBLE = "visible" +} + +// Warning: (ae-missing-release-tag) "parse" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export function parse(expression: E, startRule: S): S extends 'expression' ? ExpressionAstExpression : ExpressionAstArgument; + +// Warning: (ae-missing-release-tag) "parseExpression" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export function parseExpression(expression: string): ExpressionAstExpression; + +// Warning: (ae-missing-release-tag) "plugin" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export function plugin(initializerContext: PluginInitializerContext): ExpressionsServerPlugin; + +// Warning: (ae-missing-release-tag) "PointSeries" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export type PointSeries = ExpressionValueBoxed<'pointseries', { + columns: PointSeriesColumns; + rows: PointSeriesRow[]; +}>; + +// Warning: (ae-missing-release-tag) "PointSeriesColumn" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export interface PointSeriesColumn { + // (undocumented) + expression: string; + // (undocumented) + role: 'measure' | 'dimension'; + // (undocumented) + type: 'number' | 'string'; +} + +// Warning: (ae-missing-release-tag) "PointSeriesColumnName" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export type PointSeriesColumnName = 'x' | 'y' | 'color' | 'size' | 'text'; + +// Warning: (ae-missing-release-tag) "PointSeriesColumns" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export type PointSeriesColumns = Record | {}; + +// Warning: (ae-missing-release-tag) "PointSeriesRow" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type PointSeriesRow = Record; + +// Warning: (ae-missing-release-tag) "Range" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export interface Range { + // (undocumented) + from: number; + // (undocumented) + to: number; + // Warning: (ae-forgotten-export) The symbol "name" needs to be exported by the entry point index.d.ts + // + // (undocumented) + type: typeof name_4; +} + +// Warning: (ae-missing-release-tag) "SerializedDatatable" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export interface SerializedDatatable extends Datatable { + // (undocumented) + rows: string[][]; +} + +// Warning: (ae-missing-release-tag) "SerializedFieldFormat" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export interface SerializedFieldFormat> { + // (undocumented) + id?: string; + // (undocumented) + params?: TParams; +} + +// Warning: (ae-missing-release-tag) "Style" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type Style = ExpressionTypeStyle; + +// Warning: (ae-missing-release-tag) "TextAlignment" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export enum TextAlignment { + // (undocumented) + CENTER = "center", + // (undocumented) + JUSTIFY = "justify", + // (undocumented) + LEFT = "left", + // (undocumented) + RIGHT = "right" +} + +// Warning: (ae-missing-release-tag) "TextDecoration" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export enum TextDecoration { + // (undocumented) + NONE = "none", + // (undocumented) + UNDERLINE = "underline" +} + +// Warning: (ae-missing-release-tag) "TypesRegistry" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export class TypesRegistry implements IRegistry { + constructor(executor: Executor); + // (undocumented) + get(id: string): ExpressionType | null; + // (undocumented) + register(typeDefinition: AnyExpressionTypeDefinition | (() => AnyExpressionTypeDefinition)): void; + // (undocumented) + toArray(): ExpressionType[]; + // (undocumented) + toJS(): Record; +} + +// Warning: (ae-missing-release-tag) "TypeString" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export type TypeString = KnownTypeToString>; + +// Warning: (ae-missing-release-tag) "TypeToString" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export type TypeToString = KnownTypeToString | UnmappedTypeStrings; + +// Warning: (ae-missing-release-tag) "UnmappedTypeStrings" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export type UnmappedTypeStrings = 'date' | 'filter'; + + +// (No @packageDocumentation comment for this package) + +``` diff --git a/src/plugins/home/public/application/components/__snapshots__/home.test.js.snap b/src/plugins/home/public/application/components/__snapshots__/home.test.js.snap index bf1e8c8f0b401..e9b0494105e12 100644 --- a/src/plugins/home/public/application/components/__snapshots__/home.test.js.snap +++ b/src/plugins/home/public/application/components/__snapshots__/home.test.js.snap @@ -2,57 +2,26 @@ exports[`home change home route should render a link to change the default route in advanced settings if advanced settings is enabled 1`] = `

+
+
- - - + - - } - labelType="label" - > - - - - } - labelType="label" + + Label template + + +
+
+
+
+ +
+
+
+ +
+
+
+
- - - - +
+ +
+
+
+
+
+
+
+
+
+
+ + + + + + + + + + + + + + + + + + + + + +
+
+
+ + Input + +
+
+
+ + Output + +
+
+
+ Input +
+
+ john +
+
+
+ Output +
+
+
+ converted url for john +
+
+
+
+ Input +
+
+ /some/pathname/asset.png +
+
+
+ Output +
+
+
+ converted url for /some/pathname/asset.png +
+
+
+
+ Input +
+
+ 1234 +
+
+
+ Output +
+
+
+ converted url for 1234 +
+
+
+
+
+
+
+
`; diff --git a/src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/url/__snapshots__/url_template_flyout.test.tsx.snap b/src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/url/__snapshots__/url_template_flyout.test.tsx.snap index 14e5012e9a554..83e815dd72661 100644 --- a/src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/url/__snapshots__/url_template_flyout.test.tsx.snap +++ b/src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/url/__snapshots__/url_template_flyout.test.tsx.snap @@ -4,6 +4,7 @@ exports[`UrlTemplateFlyout should not render if not visible 1`] = `""`; exports[`UrlTemplateFlyout should render normally 1`] = ` diff --git a/src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/url/label_template_flyout.tsx b/src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/url/label_template_flyout.tsx index d04ee58f26b0a..4dd3fb8f1b695 100644 --- a/src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/url/label_template_flyout.tsx +++ b/src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/url/label_template_flyout.tsx @@ -63,7 +63,7 @@ const items: LabelTemplateExampleItem[] = [ export const LabelTemplateFlyout = ({ isVisible = false, onClose = () => {} }) => { return isVisible ? ( - +

diff --git a/src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/url/url.test.tsx b/src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/url/url.test.tsx index a1a1655949432..eb5cac111928f 100644 --- a/src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/url/url.test.tsx +++ b/src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/url/url.test.tsx @@ -18,13 +18,22 @@ */ import React from 'react'; -import { shallow } from 'enzyme'; import { FieldFormat } from 'src/plugins/data/public'; - +import { IntlProvider } from 'react-intl'; import { UrlFormatEditor } from './url'; +import { coreMock } from '../../../../../../../../../core/public/mocks'; +import { createKibanaReactContext } from '../../../../../../../../kibana_react/public'; +import { render } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; + +jest.mock('@elastic/eui/lib/services/accessibility', () => { + return { + htmlIdGenerator: () => () => `generated-id`, + }; +}); const fieldType = 'string'; -const format = { +const format = ({ getConverterFor: jest .fn() .mockImplementation(() => (input: string) => `converted url for ${input}`), @@ -35,78 +44,115 @@ const format = { { kind: 'audio', text: 'Audio' }, ], }, -}; +} as unknown) as FieldFormat; const formatParams = { openLinkInCurrentTab: true, urlTemplate: '', labelTemplate: '', width: '', height: '', + type: 'a', }; + const onChange = jest.fn(); const onError = jest.fn(); +const renderWithContext = (Element: React.ReactElement) => + render( + + {Element} + + ); + +const MY_BASE_PATH = 'my-base-path'; +const KibanaReactContext = createKibanaReactContext( + coreMock.createStart({ basePath: 'my-base-path' }) +); + describe('UrlFormatEditor', () => { it('should have a formatId', () => { expect(UrlFormatEditor.formatId).toEqual('url'); }); it('should render normally', async () => { - const component = shallow( + const { container } = renderWithContext( ); - - expect(component).toMatchSnapshot(); + expect(container).toMatchSnapshot(); }); it('should render url template help', async () => { - const component = shallow( + const { getByText, getByTestId } = renderWithContext( ); - (component.instance() as UrlFormatEditor).showUrlTemplateHelp(); - component.update(); - expect(component).toMatchSnapshot(); + getByText('URL template help'); + userEvent.click(getByText('URL template help')); + expect(getByTestId('urlTemplateFlyoutTestSubj')).toBeVisible(); }); it('should render label template help', async () => { - const component = shallow( + const { getByText, getByTestId } = renderWithContext( ); - (component.instance() as UrlFormatEditor).showLabelTemplateHelp(); - component.update(); - expect(component).toMatchSnapshot(); + getByText('Label template help'); + userEvent.click(getByText('Label template help')); + expect(getByTestId('labelTemplateFlyoutTestSubj')).toBeVisible(); }); it('should render width and height fields if image', async () => { - const component = shallow( + const { getByLabelText } = renderWithContext( ); - expect(component).toMatchSnapshot(); + expect(getByLabelText('Width')).toBeInTheDocument(); + expect(getByLabelText('Height')).toBeInTheDocument(); + }); + + it('should append base path to preview images', async () => { + let sampleImageUrlTemplate = ''; + const { getByLabelText } = renderWithContext( + { + sampleImageUrlTemplate = urlTemplate; + }} + onError={onError} + /> + ); + + // TODO: sample image url emitted only during change event + // So can't just path `type: img` and check rendered value + userEvent.selectOptions(getByLabelText('Type'), 'img'); + expect(sampleImageUrlTemplate).toContain(MY_BASE_PATH); + expect(sampleImageUrlTemplate).toMatchInlineSnapshot( + `"my-base-path/plugins/indexPatternManagement/assets/icons/{{value}}.png"` + ); }); }); diff --git a/src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/url/url.tsx b/src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/url/url.tsx index 30acf09526f85..95b5fc3955280 100644 --- a/src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/url/url.tsx +++ b/src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/url/url.tsx @@ -36,6 +36,8 @@ import { FormatEditorSamples } from '../../samples'; import { LabelTemplateFlyout } from './label_template_flyout'; import { UrlTemplateFlyout } from './url_template_flyout'; +import type { IndexPatternManagmentContextValue } from '../../../../../../types'; +import { context as contextType } from '../../../../../../../../kibana_react/public'; interface OnChangeParam { type: string; @@ -66,14 +68,21 @@ export class UrlFormatEditor extends DefaultFormatEditor< UrlFormatEditorFormatParams, UrlFormatEditorFormatState > { + static contextType = contextType; static formatId = 'url'; - iconPattern: string; + // TODO: @kbn/optimizer can't compile this + // declare context: IndexPatternManagmentContextValue; + context: IndexPatternManagmentContextValue | undefined; + private get sampleIconPath() { + const sampleIconPath = `/plugins/indexPatternManagement/assets/icons/{{value}}.png`; + return this.context?.services.http + ? this.context.services.http.basePath.prepend(sampleIconPath) + : sampleIconPath; + } constructor(props: FormatEditorProps) { super(props); - this.iconPattern = `/plugins/indexPatternManagement/assets/icons/{{value}}.png`; - this.state = { ...this.state, sampleInputsByType: { @@ -104,9 +113,9 @@ export class UrlFormatEditor extends DefaultFormatEditor< params.width = width; params.height = height; if (!urlTemplate) { - params.urlTemplate = this.iconPattern; + params.urlTemplate = this.sampleIconPath; } - } else if (newType !== 'img' && urlTemplate === this.iconPattern) { + } else if (newType !== 'img' && urlTemplate === this.sampleIconPath) { params.urlTemplate = undefined; } this.onChange(params); diff --git a/src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/url/url_template_flyout.tsx b/src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/url/url_template_flyout.tsx index c1b144b0d9eac..b1c66874d69cf 100644 --- a/src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/url/url_template_flyout.tsx +++ b/src/plugins/index_pattern_management/public/components/field_editor/components/field_format_editor/editors/url/url_template_flyout.tsx @@ -26,7 +26,7 @@ import { FormattedMessage } from '@kbn/i18n/react'; export const UrlTemplateFlyout = ({ isVisible = false, onClose = () => {} }) => { return isVisible ? ( - +

diff --git a/src/plugins/index_pattern_management/public/components/field_editor/field_editor.tsx b/src/plugins/index_pattern_management/public/components/field_editor/field_editor.tsx index 2b484d1d837bf..4fae91e78f8f9 100644 --- a/src/plugins/index_pattern_management/public/components/field_editor/field_editor.tsx +++ b/src/plugins/index_pattern_management/public/components/field_editor/field_editor.tsx @@ -133,7 +133,7 @@ export interface FieldEdiorProps { spec: IndexPatternField['spec']; services: { redirectAway: () => void; - saveIndexPattern: DataPublicPluginStart['indexPatterns']['save']; + saveIndexPattern: DataPublicPluginStart['indexPatterns']['updateSavedObject']; }; } @@ -825,7 +825,7 @@ export class FieldEditor extends PureComponent { + .catch(() => { if (oldField) { indexPattern.fields.update(oldField); } else { diff --git a/src/plugins/index_pattern_management/public/management_app/mount_management_section.tsx b/src/plugins/index_pattern_management/public/management_app/mount_management_section.tsx index add45a07e0c5f..d3f97e7f8aeb7 100644 --- a/src/plugins/index_pattern_management/public/management_app/mount_management_section.tsx +++ b/src/plugins/index_pattern_management/public/management_app/mount_management_section.tsx @@ -102,6 +102,7 @@ export async function mountManagementSection( ); return () => { + chrome.docTitle.reset(); ReactDOM.unmountComponentAtNode(params.element); }; } diff --git a/src/plugins/input_control_vis/kibana.json b/src/plugins/input_control_vis/kibana.json index 6928eb19d02e1..c6d1157f5ff25 100644 --- a/src/plugins/input_control_vis/kibana.json +++ b/src/plugins/input_control_vis/kibana.json @@ -4,6 +4,6 @@ "kibanaVersion": "kibana", "server": true, "ui": true, - "requiredPlugins": ["data", "expressions", "visualizations"], + "requiredPlugins": ["data", "expressions", "visualizations", "visDefaultEditor"], "requiredBundles": ["kibanaReact"] } diff --git a/src/plugins/input_control_vis/public/components/editor/control_editor.tsx b/src/plugins/input_control_vis/public/components/editor/control_editor.tsx index 90e875fd43432..aa473095aaf3f 100644 --- a/src/plugins/input_control_vis/public/components/editor/control_editor.tsx +++ b/src/plugins/input_control_vis/public/components/editor/control_editor.tsx @@ -18,9 +18,8 @@ */ import React, { PureComponent, ChangeEvent } from 'react'; -import { InjectedIntlProps } from 'react-intl'; +import { injectI18n, FormattedMessage, InjectedIntlProps } from '@kbn/i18n/react'; -import { injectI18n, FormattedMessage } from '@kbn/i18n/react'; import { EuiAccordion, EuiButtonIcon, diff --git a/src/plugins/input_control_vis/public/components/editor/controls_tab.tsx b/src/plugins/input_control_vis/public/components/editor/controls_tab.tsx index 19046f7f62fba..a9f04a86f8d03 100644 --- a/src/plugins/input_control_vis/public/components/editor/controls_tab.tsx +++ b/src/plugins/input_control_vis/public/components/editor/controls_tab.tsx @@ -18,9 +18,8 @@ */ import React, { PureComponent } from 'react'; -import { InjectedIntlProps } from 'react-intl'; +import { injectI18n, FormattedMessage, InjectedIntlProps } from '@kbn/i18n/react'; -import { injectI18n, FormattedMessage } from '@kbn/i18n/react'; import { EuiButton, EuiFlexGroup, diff --git a/src/plugins/input_control_vis/public/components/editor/field_select.tsx b/src/plugins/input_control_vis/public/components/editor/field_select.tsx index 2885cbf24553f..24ebfc46ae25f 100644 --- a/src/plugins/input_control_vis/public/components/editor/field_select.tsx +++ b/src/plugins/input_control_vis/public/components/editor/field_select.tsx @@ -19,9 +19,8 @@ import _ from 'lodash'; import React, { Component } from 'react'; -import { InjectedIntlProps } from 'react-intl'; -import { injectI18n, FormattedMessage } from '@kbn/i18n/react'; +import { injectI18n, FormattedMessage, InjectedIntlProps } from '@kbn/i18n/react'; import { EuiFormRow, EuiComboBox, EuiComboBoxOptionOption } from '@elastic/eui'; import { IIndexPattern, IFieldType } from '../../../../data/public'; diff --git a/src/plugins/input_control_vis/public/components/editor/index_pattern_select_form_row.tsx b/src/plugins/input_control_vis/public/components/editor/index_pattern_select_form_row.tsx index 66fdbca64f053..f424b25526b16 100644 --- a/src/plugins/input_control_vis/public/components/editor/index_pattern_select_form_row.tsx +++ b/src/plugins/input_control_vis/public/components/editor/index_pattern_select_form_row.tsx @@ -18,16 +18,15 @@ */ import React, { ComponentType } from 'react'; -import { injectI18n } from '@kbn/i18n/react'; +import { injectI18n, InjectedIntlProps } from '@kbn/i18n/react'; import { EuiFormRow } from '@elastic/eui'; -import { InjectedIntlProps } from 'react-intl'; -import { IndexPatternSelect } from 'src/plugins/data/public'; +import { IndexPatternSelectProps } from 'src/plugins/data/public'; export type IndexPatternSelectFormRowUiProps = InjectedIntlProps & { onChange: (opt: any) => void; indexPatternId: string; controlIndex: number; - IndexPatternSelect: ComponentType; + IndexPatternSelect: ComponentType; }; function IndexPatternSelectFormRowUi(props: IndexPatternSelectFormRowUiProps) { @@ -50,8 +49,6 @@ function IndexPatternSelectFormRowUi(props: IndexPatternSelectFormRowUiProps) { indexPatternId={indexPatternId} onChange={onChange} data-test-subj={selectId} - // TODO: supply actual savedObjectsClient here - savedObjectsClient={{} as any} /> ); diff --git a/src/plugins/input_control_vis/public/components/editor/list_control_editor.tsx b/src/plugins/input_control_vis/public/components/editor/list_control_editor.tsx index cf105d16f0535..2ebf19f522e9e 100644 --- a/src/plugins/input_control_vis/public/components/editor/list_control_editor.tsx +++ b/src/plugins/input_control_vis/public/components/editor/list_control_editor.tsx @@ -25,14 +25,14 @@ import { EuiFormRow, EuiFieldNumber, EuiSwitch, EuiSelect } from '@elastic/eui'; import { IndexPatternSelectFormRow } from './index_pattern_select_form_row'; import { FieldSelect } from './field_select'; import { ControlParams, ControlParamsOptions } from '../../editor_utils'; -import { IIndexPattern, IFieldType, IndexPatternSelect } from '../../../../data/public'; +import { IIndexPattern, IFieldType, IndexPatternSelectProps } from '../../../../data/public'; import { InputControlVisDependencies } from '../../plugin'; interface ListControlEditorState { isLoadingFieldType: boolean; isStringField: boolean; prevFieldName: string; - IndexPatternSelect: ComponentType | null; + IndexPatternSelect: ComponentType | null; } interface ListControlEditorProps { diff --git a/src/plugins/input_control_vis/public/components/editor/range_control_editor.tsx b/src/plugins/input_control_vis/public/components/editor/range_control_editor.tsx index 92169705f0a10..7013e069f8e9d 100644 --- a/src/plugins/input_control_vis/public/components/editor/range_control_editor.tsx +++ b/src/plugins/input_control_vis/public/components/editor/range_control_editor.tsx @@ -24,7 +24,7 @@ import { FormattedMessage } from '@kbn/i18n/react'; import { IndexPatternSelectFormRow } from './index_pattern_select_form_row'; import { FieldSelect } from './field_select'; import { ControlParams, ControlParamsOptions } from '../../editor_utils'; -import { IIndexPattern, IFieldType, IndexPatternSelect } from '../../../../data/public'; +import { IIndexPattern, IFieldType, IndexPatternSelectProps } from '../../../../data/public'; import { InputControlVisDependencies } from '../../plugin'; interface RangeControlEditorProps { @@ -42,7 +42,7 @@ interface RangeControlEditorProps { } interface RangeControlEditorState { - IndexPatternSelect: ComponentType | null; + IndexPatternSelect: ComponentType | null; } function filterField(field: IFieldType) { diff --git a/src/plugins/input_control_vis/public/components/vis/list_control.tsx b/src/plugins/input_control_vis/public/components/vis/list_control.tsx index 8ca93a302be89..e34989427be21 100644 --- a/src/plugins/input_control_vis/public/components/vis/list_control.tsx +++ b/src/plugins/input_control_vis/public/components/vis/list_control.tsx @@ -19,9 +19,8 @@ import React, { PureComponent } from 'react'; import _ from 'lodash'; -import { injectI18n } from '@kbn/i18n/react'; -import { InjectedIntlProps } from 'react-intl'; +import { injectI18n, InjectedIntlProps } from '@kbn/i18n/react'; import { EuiFieldText, EuiComboBox } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { FormRow } from './form_row'; diff --git a/src/plugins/input_control_vis/public/control/control.ts b/src/plugins/input_control_vis/public/control/control.ts index da2dc7bab7cf7..303b340e5905b 100644 --- a/src/plugins/input_control_vis/public/control/control.ts +++ b/src/plugins/input_control_vis/public/control/control.ts @@ -83,7 +83,7 @@ export abstract class Control { format = (value: any) => { const indexPattern = this.filterManager.getIndexPattern(); const field = this.filterManager.getField(); - if (field) { + if (field && indexPattern) { return indexPattern.getFormatterForField(field).convert(value); } diff --git a/src/plugins/input_control_vis/public/control/filter_manager/filter_manager.test.ts b/src/plugins/input_control_vis/public/control/filter_manager/filter_manager.test.ts index e0eeddf93f67e..141f879f248a9 100644 --- a/src/plugins/input_control_vis/public/control/filter_manager/filter_manager.test.ts +++ b/src/plugins/input_control_vis/public/control/filter_manager/filter_manager.test.ts @@ -21,7 +21,11 @@ import expect from '@kbn/expect'; import { FilterManager } from './filter_manager'; import { coreMock } from '../../../../../core/public/mocks'; -import { Filter, IndexPattern, FilterManager as QueryFilterManager } from '../../../../data/public'; +import { + Filter, + FilterManager as QueryFilterManager, + IndexPatternsContract, +} from '../../../../data/public'; const setupMock = coreMock.createSetup(); @@ -39,7 +43,6 @@ describe('FilterManager', function () { const controlId = 'control1'; describe('findFilters', function () { - const indexPatternMock = {} as IndexPattern; let kbnFilters: Filter[]; const queryFilterMock = new QueryFilterManager(setupMock.uiSettings); queryFilterMock.getAppFilters = () => kbnFilters; @@ -48,7 +51,13 @@ describe('FilterManager', function () { let filterManager: FilterManagerTest; beforeEach(() => { kbnFilters = []; - filterManager = new FilterManagerTest(controlId, 'field1', indexPatternMock, queryFilterMock); + filterManager = new FilterManagerTest( + controlId, + 'field1', + '1', + {} as IndexPatternsContract, + queryFilterMock + ); }); test('should not find filters that are not controlled by any visualization', function () { diff --git a/src/plugins/input_control_vis/public/control/filter_manager/filter_manager.ts b/src/plugins/input_control_vis/public/control/filter_manager/filter_manager.ts index ece3f7a88ba37..de948ccda8663 100644 --- a/src/plugins/input_control_vis/public/control/filter_manager/filter_manager.ts +++ b/src/plugins/input_control_vis/public/control/filter_manager/filter_manager.ts @@ -19,14 +19,22 @@ import _ from 'lodash'; -import { FilterManager as QueryFilterManager, IndexPattern, Filter } from '../../../../data/public'; +import { + FilterManager as QueryFilterManager, + IndexPattern, + Filter, + IndexPatternsContract, +} from '../../../../data/public'; export abstract class FilterManager { + protected indexPattern: IndexPattern | undefined; + constructor( public controlId: string, public fieldName: string, - public indexPattern: IndexPattern, - public queryFilter: QueryFilterManager + private indexPatternId: string, + private indexPatternsService: IndexPatternsContract, + protected queryFilter: QueryFilterManager ) {} /** @@ -41,12 +49,22 @@ export abstract class FilterManager { abstract getValueFromFilterBar(): any; - getIndexPattern(): IndexPattern { + async init() { + try { + if (!this.indexPattern) { + this.indexPattern = await this.indexPatternsService.get(this.indexPatternId); + } + } catch (e) { + // invalid index pattern id + } + } + + getIndexPattern(): IndexPattern | undefined { return this.indexPattern; } getField() { - return this.indexPattern.fields.getByName(this.fieldName); + return this.indexPattern?.fields.getByName(this.fieldName); } findFilters(): Filter[] { @@ -54,7 +72,7 @@ export abstract class FilterManager { this.queryFilter.getAppFilters(), this.queryFilter.getGlobalFilters(), ]); - return kbnFilters.filter((kbnFilter) => { + return kbnFilters.filter((kbnFilter: Filter) => { return _.get(kbnFilter, 'meta.controlledBy') === this.controlId; }); } diff --git a/src/plugins/input_control_vis/public/control/filter_manager/phrase_filter_manager.test.ts b/src/plugins/input_control_vis/public/control/filter_manager/phrase_filter_manager.test.ts index ec1f9d42aa67b..066d87230f909 100644 --- a/src/plugins/input_control_vis/public/control/filter_manager/phrase_filter_manager.test.ts +++ b/src/plugins/input_control_vis/public/control/filter_manager/phrase_filter_manager.test.ts @@ -19,7 +19,12 @@ import expect from '@kbn/expect'; -import { Filter, IndexPattern, FilterManager as QueryFilterManager } from '../../../../data/public'; +import { + Filter, + IndexPattern, + FilterManager as QueryFilterManager, + IndexPatternsContract, +} from '../../../../data/public'; import { PhraseFilterManager } from './phrase_filter_manager'; describe('PhraseFilterManager', function () { @@ -42,15 +47,20 @@ describe('PhraseFilterManager', function () { }, }, } as IndexPattern; + const indexPatternsServiceMock = ({ + get: jest.fn().mockReturnValue(Promise.resolve(indexPatternMock)), + } as unknown) as jest.Mocked; const queryFilterMock: QueryFilterManager = {} as QueryFilterManager; let filterManager: PhraseFilterManager; - beforeEach(() => { + beforeEach(async () => { filterManager = new PhraseFilterManager( controlId, 'field1', - indexPatternMock, + '1', + indexPatternsServiceMock, queryFilterMock ); + await filterManager.init(); }); test('should create match phrase filter from single value', function () { @@ -89,10 +99,11 @@ describe('PhraseFilterManager', function () { constructor( id: string, fieldName: string, - indexPattern: IndexPattern, + indexPatternId: string, + indexPatternsService: IndexPatternsContract, queryFilter: QueryFilterManager ) { - super(id, fieldName, indexPattern, queryFilter); + super(id, fieldName, indexPatternId, indexPatternsService, queryFilter); this.mockFilters = []; } @@ -105,14 +116,15 @@ describe('PhraseFilterManager', function () { } } - const indexPatternMock: IndexPattern = {} as IndexPattern; + const indexPatternsServiceMock = {} as IndexPatternsContract; const queryFilterMock: QueryFilterManager = {} as QueryFilterManager; let filterManager: MockFindFiltersPhraseFilterManager; beforeEach(() => { filterManager = new MockFindFiltersPhraseFilterManager( controlId, 'field1', - indexPatternMock, + '1', + indexPatternsServiceMock, queryFilterMock ); }); diff --git a/src/plugins/input_control_vis/public/control/filter_manager/phrase_filter_manager.ts b/src/plugins/input_control_vis/public/control/filter_manager/phrase_filter_manager.ts index 03ed6c5520dec..f3a2b4085b923 100644 --- a/src/plugins/input_control_vis/public/control/filter_manager/phrase_filter_manager.ts +++ b/src/plugins/input_control_vis/public/control/filter_manager/phrase_filter_manager.ts @@ -23,7 +23,7 @@ import { FilterManager } from './filter_manager'; import { PhraseFilter, esFilters, - IndexPattern, + IndexPatternsContract, FilterManager as QueryFilterManager, } from '../../../../data/public'; @@ -31,24 +31,26 @@ export class PhraseFilterManager extends FilterManager { constructor( controlId: string, fieldName: string, - indexPattern: IndexPattern, + indexPatternId: string, + indexPatternsService: IndexPatternsContract, queryFilter: QueryFilterManager ) { - super(controlId, fieldName, indexPattern, queryFilter); + super(controlId, fieldName, indexPatternId, indexPatternsService, queryFilter); } createFilter(phrases: any): PhraseFilter { + const indexPattern = this.getIndexPattern()!; let newFilter: PhraseFilter; - const value = this.indexPattern.fields.getByName(this.fieldName); + const value = indexPattern.fields.getByName(this.fieldName); if (!value) { throw new Error(`Unable to find field with name: ${this.fieldName} on indexPattern`); } if (phrases.length === 1) { - newFilter = esFilters.buildPhraseFilter(value, phrases[0], this.indexPattern); + newFilter = esFilters.buildPhraseFilter(value, phrases[0], indexPattern); } else { - newFilter = esFilters.buildPhrasesFilter(value, phrases, this.indexPattern); + newFilter = esFilters.buildPhrasesFilter(value, phrases, indexPattern); } newFilter.meta.key = this.fieldName; diff --git a/src/plugins/input_control_vis/public/control/filter_manager/range_filter_manager.test.ts b/src/plugins/input_control_vis/public/control/filter_manager/range_filter_manager.test.ts index 8556312d10f4a..2a66567006049 100644 --- a/src/plugins/input_control_vis/public/control/filter_manager/range_filter_manager.test.ts +++ b/src/plugins/input_control_vis/public/control/filter_manager/range_filter_manager.test.ts @@ -25,6 +25,7 @@ import { RangeFilterMeta, IndexPattern, FilterManager as QueryFilterManager, + IndexPatternsContract, } from '../../../../data/public'; describe('RangeFilterManager', function () { @@ -46,15 +47,20 @@ describe('RangeFilterManager', function () { }, }, } as IndexPattern; + const indexPatternsServiceMock = ({ + get: jest.fn().mockReturnValue(Promise.resolve(indexPatternMock)), + } as unknown) as jest.Mocked; const queryFilterMock: QueryFilterManager = {} as QueryFilterManager; let filterManager: RangeFilterManager; - beforeEach(() => { + beforeEach(async () => { filterManager = new RangeFilterManager( controlId, 'field1', - indexPatternMock, + '1', + indexPatternsServiceMock, queryFilterMock ); + await filterManager.init(); }); test('should create range filter from slider value', function () { @@ -75,10 +81,11 @@ describe('RangeFilterManager', function () { constructor( id: string, fieldName: string, - indexPattern: IndexPattern, + indexPatternId: string, + indexPatternsService: IndexPatternsContract, queryFilter: QueryFilterManager ) { - super(id, fieldName, indexPattern, queryFilter); + super(id, fieldName, indexPatternId, indexPatternsService, queryFilter); this.mockFilters = []; } @@ -91,14 +98,15 @@ describe('RangeFilterManager', function () { } } - const indexPatternMock: IndexPattern = {} as IndexPattern; + const indexPatternsServiceMock = {} as IndexPatternsContract; const queryFilterMock: QueryFilterManager = {} as QueryFilterManager; let filterManager: MockFindFiltersRangeFilterManager; beforeEach(() => { filterManager = new MockFindFiltersRangeFilterManager( controlId, 'field1', - indexPatternMock, + '1', + indexPatternsServiceMock, queryFilterMock ); }); diff --git a/src/plugins/input_control_vis/public/control/filter_manager/range_filter_manager.ts b/src/plugins/input_control_vis/public/control/filter_manager/range_filter_manager.ts index 1a884cf267c41..39e4bfa19e5dc 100644 --- a/src/plugins/input_control_vis/public/control/filter_manager/range_filter_manager.ts +++ b/src/plugins/input_control_vis/public/control/filter_manager/range_filter_manager.ts @@ -61,11 +61,12 @@ export class RangeFilterManager extends FilterManager { * @return {object} range filter */ createFilter(value: SliderValue): RangeFilter { + const indexPattern = this.getIndexPattern()!; const newFilter = esFilters.buildRangeFilter( // TODO: Fix type to be required - this.indexPattern.fields.getByName(this.fieldName) as IFieldType, + indexPattern.fields.getByName(this.fieldName) as IFieldType, toRange(value), - this.indexPattern + indexPattern ); newFilter.meta.key = this.fieldName; newFilter.meta.controlledBy = this.controlId; diff --git a/src/plugins/input_control_vis/public/control/list_control_factory.ts b/src/plugins/input_control_vis/public/control/list_control_factory.ts index 325eb471d510b..74ee09117887e 100644 --- a/src/plugins/input_control_vis/public/control/list_control_factory.ts +++ b/src/plugins/input_control_vis/public/control/list_control_factory.ts @@ -142,6 +142,17 @@ export class ListControl extends Control { timeout: `${settings.autocompleteTimeout}ms`, terminate_after: Number(settings.autocompleteTerminateAfter), }; + + // dynamic options are only allowed on String fields but the setting defaults to true so it could + // be enabled for non-string fields (since UI input is hidden for non-string fields). + // If field is not string, then disable dynamic options. + const field = indexPattern?.fields + .getAll() + .find(({ name }) => name === this.controlParams.fieldName); + if (field && field.type !== 'string') { + this.options.dynamicOptions = false; + } + const aggs = termsAgg({ field: indexPattern.fields.getByName(fieldName), size: this.options.dynamicOptions ? null : _.get(this.options, 'size', 5), @@ -213,27 +224,20 @@ export async function listControlFactory( deps: InputControlVisDependencies ) { const [, { data: dataPluginStart }] = await deps.core.getStartServices(); - const indexPattern = await dataPluginStart.indexPatterns.get(controlParams.indexPattern); - - // dynamic options are only allowed on String fields but the setting defaults to true so it could - // be enabled for non-string fields (since UI input is hidden for non-string fields). - // If field is not string, then disable dynamic options. - const field = indexPattern.fields.getAll().find(({ name }) => name === controlParams.fieldName); - if (field && field.type !== 'string') { - controlParams.options.dynamicOptions = false; - } const listControl = new ListControl( controlParams, new PhraseFilterManager( controlParams.id, controlParams.fieldName, - indexPattern, + controlParams.indexPattern, + dataPluginStart.indexPatterns, deps.data.query.filterManager ), useTimeFilter, dataPluginStart.search.searchSource, deps ); + await listControl.filterManager.init(); return listControl; } diff --git a/src/plugins/input_control_vis/public/control/range_control_factory.ts b/src/plugins/input_control_vis/public/control/range_control_factory.ts index eac79ca5fcca8..9cb1a0e25a8db 100644 --- a/src/plugins/input_control_vis/public/control/range_control_factory.ts +++ b/src/plugins/input_control_vis/public/control/range_control_factory.ts @@ -134,18 +134,20 @@ export async function rangeControlFactory( deps: InputControlVisDependencies ): Promise { const [, { data: dataPluginStart }] = await deps.core.getStartServices(); - const indexPattern = await dataPluginStart.indexPatterns.get(controlParams.indexPattern); - return new RangeControl( + const rangeControl = new RangeControl( controlParams, new RangeFilterManager( controlParams.id, controlParams.fieldName, - indexPattern, + controlParams.indexPattern, + dataPluginStart.indexPatterns, deps.data.query.filterManager ), useTimeFilter, dataPluginStart.search.searchSource, deps ); + await rangeControl.filterManager.init(); + return rangeControl; } diff --git a/src/plugins/input_control_vis/public/input_control_vis_type.ts b/src/plugins/input_control_vis/public/input_control_vis_type.ts index 9f415f2100004..782df67f5c58a 100644 --- a/src/plugins/input_control_vis/public/input_control_vis_type.ts +++ b/src/plugins/input_control_vis/public/input_control_vis_type.ts @@ -19,12 +19,15 @@ import { i18n } from '@kbn/i18n'; +import { BaseVisTypeOptions } from 'src/plugins/visualizations/public'; import { createInputControlVisController } from './vis_controller'; import { getControlsTab } from './components/editor/controls_tab'; import { OptionsTab } from './components/editor/options_tab'; import { InputControlVisDependencies } from './plugin'; -export function createInputControlVisTypeDefinition(deps: InputControlVisDependencies) { +export function createInputControlVisTypeDefinition( + deps: InputControlVisDependencies +): BaseVisTypeOptions { const InputControlVisController = createInputControlVisController(deps); const ControlsTab = getControlsTab(deps); diff --git a/src/plugins/input_control_vis/public/vis_controller.tsx b/src/plugins/input_control_vis/public/vis_controller.tsx index faea98b792291..6f35e17866120 100644 --- a/src/plugins/input_control_vis/public/vis_controller.tsx +++ b/src/plugins/input_control_vis/public/vis_controller.tsx @@ -31,12 +31,12 @@ import { RangeControl } from './control/range_control_factory'; import { ListControl } from './control/list_control_factory'; import { InputControlVisDependencies } from './plugin'; import { FilterManager, Filter } from '../../data/public'; -import { VisParams, Vis } from '../../visualizations/public'; +import { VisParams, ExprVis } from '../../visualizations/public'; export const createInputControlVisController = (deps: InputControlVisDependencies) => { return class InputControlVisController { private I18nContext?: I18nStart['Context']; - private isLoaded = false; + private _isLoaded = false; controls: Array; queryBarUpdateHandler: () => void; @@ -45,7 +45,7 @@ export const createInputControlVisController = (deps: InputControlVisDependencie timeFilterSubscription: Subscription; visParams?: VisParams; - constructor(public el: Element, public vis: Vis) { + constructor(public el: Element, public vis: ExprVis) { this.controls = []; this.queryBarUpdateHandler = this.updateControlsFromKbn.bind(this); @@ -58,7 +58,7 @@ export const createInputControlVisController = (deps: InputControlVisDependencie .getTimeUpdate$() .subscribe(() => { if (this.visParams?.useTimeFilter) { - this.isLoaded = false; + this._isLoaded = false; } }); } @@ -68,11 +68,11 @@ export const createInputControlVisController = (deps: InputControlVisDependencie const [{ i18n }] = await deps.core.getStartServices(); this.I18nContext = i18n.Context; } - if (!this.isLoaded || !isEqual(visParams, this.visParams)) { + if (!this._isLoaded || !isEqual(visParams, this.visParams)) { this.visParams = visParams; this.controls = []; this.controls = await this.initControls(); - this.isLoaded = true; + this._isLoaded = true; } this.drawVis(); } diff --git a/src/plugins/kibana_overview/README.md b/src/plugins/kibana_overview/README.md new file mode 100644 index 0000000000000..ad0cbfdf7013b --- /dev/null +++ b/src/plugins/kibana_overview/README.md @@ -0,0 +1,9 @@ +# kibana-overview + +> An overview page highlighting Kibana apps + +--- + +## Development + +See the [kibana contributing guide](https://github.com/elastic/kibana/blob/master/CONTRIBUTING.md) for instructions setting up your development environment. diff --git a/src/plugins/kibana_overview/common/index.ts b/src/plugins/kibana_overview/common/index.ts new file mode 100644 index 0000000000000..3bdfbee1081ad --- /dev/null +++ b/src/plugins/kibana_overview/common/index.ts @@ -0,0 +1,23 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export const PLUGIN_ID = 'kibanaOverview'; +export const PLUGIN_NAME = 'Overview'; +export const PLUGIN_PATH = `/app/kibana_overview`; +export const PLUGIN_ICON = 'logoKibana'; diff --git a/src/plugins/kibana_overview/kibana.json b/src/plugins/kibana_overview/kibana.json new file mode 100644 index 0000000000000..9ddcaabdaed6b --- /dev/null +++ b/src/plugins/kibana_overview/kibana.json @@ -0,0 +1,9 @@ +{ + "id": "kibanaOverview", + "version": "kibana", + "server": false, + "ui": true, + "requiredPlugins": ["navigation", "data", "home"], + "optionalPlugins": ["newsfeed"], + "requiredBundles": ["kibanaReact", "newsfeed"] +} diff --git a/src/plugins/kibana_overview/public/application.tsx b/src/plugins/kibana_overview/public/application.tsx new file mode 100644 index 0000000000000..1bf3fe07c36a8 --- /dev/null +++ b/src/plugins/kibana_overview/public/application.tsx @@ -0,0 +1,62 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React from 'react'; +import ReactDOM from 'react-dom'; +import { I18nProvider } from '@kbn/i18n/react'; +import { KibanaContextProvider } from '../../../../src/plugins/kibana_react/public'; +import { NewsfeedApiEndpoint } from '../../../../src/plugins/newsfeed/public'; +import { AppMountParameters, CoreStart } from '../../../../src/core/public'; +import { AppPluginStartDependencies } from './types'; +import { KibanaOverviewApp } from './components/app'; + +export const renderApp = ( + core: CoreStart, + deps: AppPluginStartDependencies, + { appBasePath, element }: AppMountParameters +) => { + const { notifications, http } = core; + const { newsfeed, home, navigation } = deps; + const newsfeed$ = newsfeed?.createNewsFeed$(NewsfeedApiEndpoint.KIBANA_ANALYTICS); + const navLinks = core.chrome.navLinks.getAll(); + const solutions = home.featureCatalogue + .getSolutions() + .filter(({ id }) => id !== 'kibana') + .filter(({ id }) => navLinks.find(({ category, hidden }) => !hidden && category?.id === id)); + const features = home.featureCatalogue.get(); + + ReactDOM.render( + + + + + , + element + ); + + return () => ReactDOM.unmountComponentAtNode(element); +}; diff --git a/src/plugins/kibana_overview/public/assets/kibana_canvas_dark.svg b/src/plugins/kibana_overview/public/assets/kibana_canvas_dark.svg new file mode 100644 index 0000000000000..c86a3a89924c8 --- /dev/null +++ b/src/plugins/kibana_overview/public/assets/kibana_canvas_dark.svg @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/plugins/kibana_overview/public/assets/kibana_canvas_light.svg b/src/plugins/kibana_overview/public/assets/kibana_canvas_light.svg new file mode 100644 index 0000000000000..d51560cb915c9 --- /dev/null +++ b/src/plugins/kibana_overview/public/assets/kibana_canvas_light.svg @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/plugins/kibana_overview/public/assets/kibana_dashboard_dark.svg b/src/plugins/kibana_overview/public/assets/kibana_dashboard_dark.svg new file mode 100644 index 0000000000000..834dd98d60e4c --- /dev/null +++ b/src/plugins/kibana_overview/public/assets/kibana_dashboard_dark.svg @@ -0,0 +1,116 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/plugins/kibana_overview/public/assets/kibana_dashboard_light.svg b/src/plugins/kibana_overview/public/assets/kibana_dashboard_light.svg new file mode 100644 index 0000000000000..958d25362c439 --- /dev/null +++ b/src/plugins/kibana_overview/public/assets/kibana_dashboard_light.svg @@ -0,0 +1,116 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/plugins/kibana_overview/public/assets/kibana_discover_dark.svg b/src/plugins/kibana_overview/public/assets/kibana_discover_dark.svg new file mode 100644 index 0000000000000..cf3116ae7f36a --- /dev/null +++ b/src/plugins/kibana_overview/public/assets/kibana_discover_dark.svg @@ -0,0 +1,145 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/plugins/kibana_overview/public/assets/kibana_discover_light.svg b/src/plugins/kibana_overview/public/assets/kibana_discover_light.svg new file mode 100644 index 0000000000000..6e039d03bef89 --- /dev/null +++ b/src/plugins/kibana_overview/public/assets/kibana_discover_light.svg @@ -0,0 +1,145 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/plugins/kibana_overview/public/assets/kibana_graph_dark.svg b/src/plugins/kibana_overview/public/assets/kibana_graph_dark.svg new file mode 100644 index 0000000000000..ea43adf3390d0 --- /dev/null +++ b/src/plugins/kibana_overview/public/assets/kibana_graph_dark.svg @@ -0,0 +1,68 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/plugins/kibana_overview/public/assets/kibana_graph_light.svg b/src/plugins/kibana_overview/public/assets/kibana_graph_light.svg new file mode 100644 index 0000000000000..c4505209a20bd --- /dev/null +++ b/src/plugins/kibana_overview/public/assets/kibana_graph_light.svg @@ -0,0 +1,68 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/plugins/kibana_overview/public/assets/kibana_maps_dark.svg b/src/plugins/kibana_overview/public/assets/kibana_maps_dark.svg new file mode 100644 index 0000000000000..a6c53012a5e90 --- /dev/null +++ b/src/plugins/kibana_overview/public/assets/kibana_maps_dark.svg @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/plugins/kibana_overview/public/assets/kibana_maps_light.svg b/src/plugins/kibana_overview/public/assets/kibana_maps_light.svg new file mode 100644 index 0000000000000..06a3ee5177eb9 --- /dev/null +++ b/src/plugins/kibana_overview/public/assets/kibana_maps_light.svg @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/plugins/kibana_overview/public/assets/kibana_ml_dark.svg b/src/plugins/kibana_overview/public/assets/kibana_ml_dark.svg new file mode 100644 index 0000000000000..574760e523f51 --- /dev/null +++ b/src/plugins/kibana_overview/public/assets/kibana_ml_dark.svg @@ -0,0 +1,141 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/plugins/kibana_overview/public/assets/kibana_ml_light.svg b/src/plugins/kibana_overview/public/assets/kibana_ml_light.svg new file mode 100644 index 0000000000000..2375d78ce61f3 --- /dev/null +++ b/src/plugins/kibana_overview/public/assets/kibana_ml_light.svg @@ -0,0 +1,141 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/plugins/kibana_overview/public/assets/kibana_montage_dark.svg b/src/plugins/kibana_overview/public/assets/kibana_montage_dark.svg new file mode 100644 index 0000000000000..7a476e4b19ae1 --- /dev/null +++ b/src/plugins/kibana_overview/public/assets/kibana_montage_dark.svg @@ -0,0 +1,178 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/plugins/kibana_overview/public/assets/kibana_montage_light.svg b/src/plugins/kibana_overview/public/assets/kibana_montage_light.svg new file mode 100644 index 0000000000000..83f48a0d31a0c --- /dev/null +++ b/src/plugins/kibana_overview/public/assets/kibana_montage_light.svg @@ -0,0 +1,218 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/plugins/kibana_overview/public/assets/solutions_enterprise_search_dark_2x.png b/src/plugins/kibana_overview/public/assets/solutions_enterprise_search_dark_2x.png new file mode 100644 index 0000000000000..86ac827f06a77 Binary files /dev/null and b/src/plugins/kibana_overview/public/assets/solutions_enterprise_search_dark_2x.png differ diff --git a/src/plugins/kibana_overview/public/assets/solutions_enterprise_search_light_2x.png b/src/plugins/kibana_overview/public/assets/solutions_enterprise_search_light_2x.png new file mode 100644 index 0000000000000..527a09aad05ec Binary files /dev/null and b/src/plugins/kibana_overview/public/assets/solutions_enterprise_search_light_2x.png differ diff --git a/src/plugins/kibana_overview/public/assets/solutions_observability_dark_2x.png b/src/plugins/kibana_overview/public/assets/solutions_observability_dark_2x.png new file mode 100644 index 0000000000000..c9dd85ee07f35 Binary files /dev/null and b/src/plugins/kibana_overview/public/assets/solutions_observability_dark_2x.png differ diff --git a/src/plugins/kibana_overview/public/assets/solutions_observability_light_2x.png b/src/plugins/kibana_overview/public/assets/solutions_observability_light_2x.png new file mode 100644 index 0000000000000..85120b906c967 Binary files /dev/null and b/src/plugins/kibana_overview/public/assets/solutions_observability_light_2x.png differ diff --git a/src/plugins/kibana_overview/public/assets/solutions_security_solution_dark_2x.png b/src/plugins/kibana_overview/public/assets/solutions_security_solution_dark_2x.png new file mode 100644 index 0000000000000..24f902bff090b Binary files /dev/null and b/src/plugins/kibana_overview/public/assets/solutions_security_solution_dark_2x.png differ diff --git a/src/plugins/kibana_overview/public/assets/solutions_security_solution_light_2x.png b/src/plugins/kibana_overview/public/assets/solutions_security_solution_light_2x.png new file mode 100644 index 0000000000000..2b35af848f912 Binary files /dev/null and b/src/plugins/kibana_overview/public/assets/solutions_security_solution_light_2x.png differ diff --git a/src/plugins/kibana_overview/public/components/_index.scss b/src/plugins/kibana_overview/public/components/_index.scss new file mode 100644 index 0000000000000..b8857d171728f --- /dev/null +++ b/src/plugins/kibana_overview/public/components/_index.scss @@ -0,0 +1 @@ +@import 'overview'; diff --git a/src/plugins/kibana_overview/public/components/_overview.scss b/src/plugins/kibana_overview/public/components/_overview.scss new file mode 100644 index 0000000000000..74a58122d4851 --- /dev/null +++ b/src/plugins/kibana_overview/public/components/_overview.scss @@ -0,0 +1,120 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +.kbnOverviewWrapper { + background-color: $euiColorEmptyShade; + display: flex; + flex-direction: column; + min-height: calc(100vh - #{$euiHeaderHeightCompensation}); +} + +.kbnOverviewContent { + margin: 0 auto; + max-width: 1200px; + padding: $euiSizeXL $euiSize; + width: 100%; + + // Ensure card heights are stretched equally when wrapped with this element + .kbnRedirectCrossAppLinks { + align-items: flex-start; + display: flex; + flex: 1; + flex-direction: column; + } +} + +.kbnOverviewApps__item { + .kbnOverviewApps__group--primary & { + @include euiBreakpoint('m', 'l', 'xl') { + max-width: calc(50% - #{$euiSizeM * 2}); + } + } + + .kbnOverviewApps__group--secondary & { + @include euiBreakpoint('m', 'l', 'xl') { + max-width: calc(25% - #{$euiSizeM * 2}); + } + } +} + +.kbnOverviewNews__content article { + & + article { + margin-top: $euiSizeL; + } + + &, + header { + & > * + * { + margin-top: $euiSizeXS; + } + } + + h3 { + font-weight: inherit; + } +} + +.kbnOverviewMore__item { + @include euiBreakpoint('m', 'l', 'xl') { + max-width: calc(33.333333333333333% - #{$euiSizeM * 2}); + } +} + +.kbnOverviewSolution__icon { + background-color: $euiColorEmptyShade !important; + box-shadow: none !important; + height: $euiSizeL * 2; + padding: $euiSizeM; + width: $euiSizeL * 2; +} + +.kbnOverviewSupplements--noNews .kbnOverviewMore { + h2 { + @include euiBreakpoint('m', 'l', 'xl') { + text-align: center; + } + } + + .kbnOverviewMore__content { + @include euiBreakpoint('m', 'l', 'xl') { + justify-content: center; + } + } +} + +.kbnOverviewData--expanded { + flex-direction: column; + + &, + & > * { + margin-bottom: 0 !important; + margin-top: 0 !important; + } +} + +// Accounting for no `flush="both"` prop on EuiButtonEmpty +.kbnOverviewDataAdd__actionButton { + margin-right: 0; +} + +.kbnOverviewDataManage__item:not(:only-child) { + @include euiBreakpoint('m', 'l', 'xl') { + flex: 0 0 calc(50% - #{$euiSizeM * 2}); + } +} diff --git a/src/plugins/kibana_overview/public/components/add_data/__snapshots__/add_data.test.tsx.snap b/src/plugins/kibana_overview/public/components/add_data/__snapshots__/add_data.test.tsx.snap new file mode 100644 index 0000000000000..42623abd79ac0 --- /dev/null +++ b/src/plugins/kibana_overview/public/components/add_data/__snapshots__/add_data.test.tsx.snap @@ -0,0 +1,102 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`AddData render 1`] = ` +
+ + + +

+ +

+
+
+ +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + + +
+`; diff --git a/src/plugins/kibana_overview/public/components/add_data/add_data.test.tsx b/src/plugins/kibana_overview/public/components/add_data/add_data.test.tsx new file mode 100644 index 0000000000000..f5cdbd9e27e28 --- /dev/null +++ b/src/plugins/kibana_overview/public/components/add_data/add_data.test.tsx @@ -0,0 +1,67 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React from 'react'; +import { AddData } from './add_data'; +import { shallowWithIntl } from 'test_utils/enzyme_helpers'; +import { FeatureCatalogueCategory } from 'src/plugins/home/public'; + +const mockFeatures = [ + { + category: FeatureCatalogueCategory.DATA, + description: 'Ingest data from popular apps and services.', + showOnHomePage: true, + icon: 'indexOpen', + id: 'home_tutorial_directory', + order: 500, + path: '/app/home#/tutorial_directory', + title: 'Ingest data', + }, + { + category: FeatureCatalogueCategory.ADMIN, + description: 'Add and manage your fleet of Elastic Agents and integrations.', + showOnHomePage: true, + icon: 'indexManagementApp', + id: 'ingestManager', + order: 510, + path: '/app/ingestManager', + title: 'Add Elastic Agent', + }, + { + category: FeatureCatalogueCategory.DATA, + description: 'Import your own CSV, NDJSON, or log file', + showOnHomePage: true, + icon: 'document', + id: 'ml_file_data_visualizer', + order: 520, + path: '/app/ml#/filedatavisualizer', + title: 'Upload a file', + }, +]; + +const addBasePathMock = jest.fn((path: string) => (path ? path : 'path')); + +describe('AddData', () => { + test('render', () => { + const component = shallowWithIntl( + + ); + expect(component).toMatchSnapshot(); + }); +}); diff --git a/src/plugins/kibana_overview/public/components/add_data/add_data.tsx b/src/plugins/kibana_overview/public/components/add_data/add_data.tsx new file mode 100644 index 0000000000000..e29c2a08395cf --- /dev/null +++ b/src/plugins/kibana_overview/public/components/add_data/add_data.tsx @@ -0,0 +1,108 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React, { FC } from 'react'; +import PropTypes from 'prop-types'; +import { EuiButtonEmpty, EuiFlexGroup, EuiFlexItem, EuiSpacer, EuiTitle } from '@elastic/eui'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { CoreStart } from 'kibana/public'; +import { RedirectAppLinks, useKibana } from '../../../../../../src/plugins/kibana_react/public'; +import { FeatureCatalogueEntry } from '../../../../../../src/plugins/home/public'; +// @ts-expect-error untyped component +import { Synopsis } from '../synopsis'; + +interface Props { + addBasePath: (path: string) => string; + features: FeatureCatalogueEntry[]; +} + +export const AddData: FC = ({ addBasePath, features }) => { + const { + services: { application }, + } = useKibana(); + + return ( +
+ + + +

+ +

+
+
+ + +
+ + + +
+
+
+ + + + + {features.map((feature) => ( + + + + + + ))} + +
+ ); +}; + +AddData.propTypes = { + addBasePath: PropTypes.func.isRequired, + features: PropTypes.arrayOf( + PropTypes.shape({ + id: PropTypes.string.isRequired, + title: PropTypes.string.isRequired, + description: PropTypes.string.isRequired, + icon: PropTypes.string.isRequired, + path: PropTypes.string.isRequired, + showOnHomePage: PropTypes.bool.isRequired, + category: PropTypes.string.isRequired, + order: PropTypes.number, + }) + ), +}; diff --git a/src/plugins/kibana_overview/public/components/add_data/index.ts b/src/plugins/kibana_overview/public/components/add_data/index.ts new file mode 100644 index 0000000000000..a7d465d177636 --- /dev/null +++ b/src/plugins/kibana_overview/public/components/add_data/index.ts @@ -0,0 +1,20 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export * from './add_data'; diff --git a/src/plugins/kibana_overview/public/components/app.tsx b/src/plugins/kibana_overview/public/components/app.tsx new file mode 100644 index 0000000000000..bf9211f49a18e --- /dev/null +++ b/src/plugins/kibana_overview/public/components/app.tsx @@ -0,0 +1,69 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React, { useEffect, useState } from 'react'; +import { Observable } from 'rxjs'; +import { I18nProvider } from '@kbn/i18n/react'; +import { HashRouter as Router, Switch, Route } from 'react-router-dom'; +import { CoreStart } from 'src/core/public'; +import { NavigationPublicPluginStart } from 'src/plugins/navigation/public'; +import { FetchResult } from 'src/plugins/newsfeed/public'; +import { FeatureCatalogueEntry, FeatureCatalogueSolution } from 'src/plugins/home/public'; +import { Overview } from './overview'; + +interface KibanaOverviewAppDeps { + basename: string; + notifications: CoreStart['notifications']; + http: CoreStart['http']; + navigation: NavigationPublicPluginStart; + newsfeed$?: Observable; + solutions: FeatureCatalogueSolution[]; + features: FeatureCatalogueEntry[]; +} + +export const KibanaOverviewApp = ({ + basename, + newsfeed$, + solutions, + features, +}: KibanaOverviewAppDeps) => { + const [newsFetchResult, setNewsFetchResult] = useState(null); + + useEffect(() => { + if (newsfeed$) { + const subscription = newsfeed$.subscribe((res: FetchResult | void | null) => { + setNewsFetchResult(res); + }); + + return () => subscription.unsubscribe(); + } + }, [newsfeed$]); + + return ( + + + + + + + + + + ); +}; diff --git a/src/plugins/kibana_overview/public/components/getting_started/__snapshots__/getting_started.test.tsx.snap b/src/plugins/kibana_overview/public/components/getting_started/__snapshots__/getting_started.test.tsx.snap new file mode 100644 index 0000000000000..374715a277ebc --- /dev/null +++ b/src/plugins/kibana_overview/public/components/getting_started/__snapshots__/getting_started.test.tsx.snap @@ -0,0 +1,391 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`GettingStarted dark mode on 1`] = ` +
+ + +
+ +

+ +

+
+ + +

+ +

+
+ + + + + } + layout="horizontal" + paddingSize="none" + title="Dashboard" + titleElement="h3" + titleSize="xs" + /> + + + + } + layout="horizontal" + paddingSize="none" + title="Discover" + titleElement="h3" + titleSize="xs" + /> + + + + } + layout="horizontal" + paddingSize="none" + title="Canvas" + titleElement="h3" + titleSize="xs" + /> + + + + } + layout="horizontal" + paddingSize="none" + title="Maps" + titleElement="h3" + titleSize="xs" + /> + + + + } + layout="horizontal" + paddingSize="none" + title="Machine Learning" + titleElement="h3" + titleSize="xs" + /> + + + + } + layout="horizontal" + paddingSize="none" + title="Graph" + titleElement="h3" + titleSize="xs" + /> + + + + + + + + +
+
+ + + +
+
+`; + +exports[`GettingStarted render 1`] = ` +
+ + +
+ +

+ +

+
+ + +

+ +

+
+ + + + + } + layout="horizontal" + paddingSize="none" + title="Dashboard" + titleElement="h3" + titleSize="xs" + /> + + + + } + layout="horizontal" + paddingSize="none" + title="Discover" + titleElement="h3" + titleSize="xs" + /> + + + + } + layout="horizontal" + paddingSize="none" + title="Canvas" + titleElement="h3" + titleSize="xs" + /> + + + + } + layout="horizontal" + paddingSize="none" + title="Maps" + titleElement="h3" + titleSize="xs" + /> + + + + } + layout="horizontal" + paddingSize="none" + title="Machine Learning" + titleElement="h3" + titleSize="xs" + /> + + + + } + layout="horizontal" + paddingSize="none" + title="Graph" + titleElement="h3" + titleSize="xs" + /> + + + + + + + + +
+
+ + + +
+
+`; diff --git a/src/plugins/kibana_overview/public/components/getting_started/getting_started.test.tsx b/src/plugins/kibana_overview/public/components/getting_started/getting_started.test.tsx new file mode 100644 index 0000000000000..7d40c4174f39b --- /dev/null +++ b/src/plugins/kibana_overview/public/components/getting_started/getting_started.test.tsx @@ -0,0 +1,118 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React from 'react'; +import { GettingStarted } from './getting_started'; +import { shallowWithIntl } from 'test_utils/enzyme_helpers'; +import { FeatureCatalogueCategory } from 'src/plugins/home/public'; + +const addBasePathMock = jest.fn((path: string) => (path ? path : 'path')); + +const mockApps = [ + { + category: FeatureCatalogueCategory.DATA, + description: 'Display and share a collection of visualizations and saved searches.', + icon: 'dashboardApp', + id: 'dashboard', + order: 100, + path: 'path-to-dashboard', + showOnHomePage: false, + solutionId: 'kibana', + subtitle: 'Analyze data in dashboards.', + title: 'Dashboard', + }, + { + category: FeatureCatalogueCategory.DATA, + description: 'Interactively explore your data by querying and filtering raw documents.', + icon: 'discoverApp', + id: 'discover', + order: 200, + path: 'path-to-discover', + + showOnHomePage: false, + solutionId: 'kibana', + subtitle: 'Search and find insights.', + title: 'Discover', + }, + { + category: FeatureCatalogueCategory.DATA, + description: 'Showcase your data in a pixel-perfect way.', + icon: 'canvasApp', + id: 'canvas', + order: 300, + path: 'path-to-canvas', + + showOnHomePage: false, + solutionId: 'kibana', + subtitle: 'Design pixel-perfect reports.', + title: 'Canvas', + }, + { + category: FeatureCatalogueCategory.DATA, + description: 'Explore geospatial data from Elasticsearch and the Elastic Maps Service.', + icon: 'gisApp', + id: 'maps', + order: 400, + path: 'path-to-maps', + showOnHomePage: false, + solutionId: 'kibana', + subtitle: 'Plot geographic data.', + title: 'Maps', + }, + { + category: FeatureCatalogueCategory.DATA, + description: + 'Automatically model the normal behavior of your time series data to detect anomalies.', + icon: 'machineLearningApp', + id: 'ml', + order: 500, + path: 'path-to-ml', + showOnHomePage: false, + solutionId: 'kibana', + subtitle: 'Model, predict, and detect.', + title: 'Machine Learning', + }, + { + category: FeatureCatalogueCategory.DATA, + description: 'Surface and analyze relevant relationships in your Elasticsearch data.', + icon: 'graphApp', + id: 'graph', + order: 600, + path: 'path-to-graph', + showOnHomePage: false, + solutionId: 'kibana', + subtitle: 'Reveal patterns and relationships.', + title: 'Graph', + }, +]; + +describe('GettingStarted', () => { + test('render', () => { + const component = shallowWithIntl( + + ); + expect(component).toMatchSnapshot(); + }); + test('dark mode on', () => { + const component = shallowWithIntl( + + ); + expect(component).toMatchSnapshot(); + }); +}); diff --git a/src/plugins/kibana_overview/public/components/getting_started/getting_started.tsx b/src/plugins/kibana_overview/public/components/getting_started/getting_started.tsx new file mode 100644 index 0000000000000..9f2d714f43a53 --- /dev/null +++ b/src/plugins/kibana_overview/public/components/getting_started/getting_started.tsx @@ -0,0 +1,126 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React, { FC } from 'react'; +import { + EuiButton, + EuiCard, + EuiFlexGrid, + EuiFlexGroup, + EuiFlexItem, + EuiIcon, + EuiImage, + EuiSpacer, + EuiText, + EuiTitle, +} from '@elastic/eui'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { CoreStart } from 'kibana/public'; +import { RedirectAppLinks, useKibana } from '../../../../../../src/plugins/kibana_react/public'; +import { FeatureCatalogueEntry } from '../../../../../../src/plugins/home/public'; +import { PLUGIN_ID } from '../../../common'; + +interface Props { + addBasePath: (path: string) => string; + isDarkTheme: boolean; + apps: FeatureCatalogueEntry[]; +} + +export const GettingStarted: FC = ({ addBasePath, isDarkTheme, apps }) => { + const { + services: { application }, + } = useKibana(); + const gettingStartedGraphicURL = `/plugins/${PLUGIN_ID}/assets/kibana_montage_${ + isDarkTheme ? 'dark' : 'light' + }.svg`; + + return ( +
+ + +
+ +

+ +

+
+ + + + +

+ +

+
+ + + + + {apps.map(({ subtitle = '', icon, title }) => ( + + } + layout="horizontal" + paddingSize="none" + title={title} + titleElement="h3" + titleSize="xs" + /> + + ))} + + + + + + + + + +
+
+ + + + +
+
+ ); +}; diff --git a/src/plugins/kibana_overview/public/components/getting_started/index.ts b/src/plugins/kibana_overview/public/components/getting_started/index.ts new file mode 100644 index 0000000000000..6a0df12de2d2d --- /dev/null +++ b/src/plugins/kibana_overview/public/components/getting_started/index.ts @@ -0,0 +1,20 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export * from './getting_started'; diff --git a/src/plugins/kibana_overview/public/components/manage_data/__snapshots__/manage_data.test.tsx.snap b/src/plugins/kibana_overview/public/components/manage_data/__snapshots__/manage_data.test.tsx.snap new file mode 100644 index 0000000000000..4be9e4df6b736 --- /dev/null +++ b/src/plugins/kibana_overview/public/components/manage_data/__snapshots__/manage_data.test.tsx.snap @@ -0,0 +1,103 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`ManageData render 1`] = ` + + +`; + +exports[`ManageData render empty without any features 1`] = ``; diff --git a/src/plugins/kibana_overview/public/components/manage_data/index.tsx b/src/plugins/kibana_overview/public/components/manage_data/index.tsx new file mode 100644 index 0000000000000..2845e3bd12023 --- /dev/null +++ b/src/plugins/kibana_overview/public/components/manage_data/index.tsx @@ -0,0 +1,20 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export * from './manage_data'; diff --git a/src/plugins/kibana_overview/public/components/manage_data/manage_data.test.tsx b/src/plugins/kibana_overview/public/components/manage_data/manage_data.test.tsx new file mode 100644 index 0000000000000..3ce2364c96083 --- /dev/null +++ b/src/plugins/kibana_overview/public/components/manage_data/manage_data.test.tsx @@ -0,0 +1,83 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React from 'react'; +import { ManageData } from './manage_data'; +import { shallowWithIntl } from 'test_utils/enzyme_helpers'; +import { FeatureCatalogueCategory } from 'src/plugins/home/public'; + +const mockFeatures = [ + { + category: FeatureCatalogueCategory.ADMIN, + description: 'Control who has access and what tasks they can perform.', + icon: 'securityApp', + id: 'security', + order: 600, + path: 'path-to-security-roles', + title: 'Protect your data', + showOnHomePage: true, + }, + { + category: FeatureCatalogueCategory.ADMIN, + description: 'Track the real-time health and performance of your deployment.', + icon: 'monitoringApp', + id: 'monitoring', + order: 610, + path: 'path-to-monitoring', + title: 'Monitor the stack', + showOnHomePage: true, + }, + { + category: FeatureCatalogueCategory.ADMIN, + description: + 'Save snapshots to a backup repository, and restore to recover index and cluster state.', + icon: 'storage', + id: 'snapshot_restore', + order: 630, + path: 'path-to-snapshot-restore', + title: 'Store & recover backups', + showOnHomePage: true, + }, + { + category: FeatureCatalogueCategory.ADMIN, + description: 'Define lifecycle policies to automatically perform operations as an index ages.', + icon: 'indexSettings', + id: 'index_lifecycle_management', + order: 640, + path: 'path-to-index-lifecycle-management', + title: 'Manage index lifecycles', + showOnHomePage: true, + }, +]; + +const addBasePathMock = jest.fn((path: string) => (path ? path : 'path')); + +describe('ManageData', () => { + test('render', () => { + const component = shallowWithIntl( + + ); + expect(component).toMatchSnapshot(); + }); + + test('render empty without any features', () => { + const component = shallowWithIntl(); + expect(component).toMatchSnapshot(); + }); +}); diff --git a/src/plugins/kibana_overview/public/components/manage_data/manage_data.tsx b/src/plugins/kibana_overview/public/components/manage_data/manage_data.tsx new file mode 100644 index 0000000000000..f7a40b9370efd --- /dev/null +++ b/src/plugins/kibana_overview/public/components/manage_data/manage_data.tsx @@ -0,0 +1,95 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React, { FC } from 'react'; +import PropTypes from 'prop-types'; +import { EuiFlexGroup, EuiFlexItem, EuiHorizontalRule, EuiSpacer, EuiTitle } from '@elastic/eui'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { CoreStart } from 'kibana/public'; +import { RedirectAppLinks, useKibana } from '../../../../../../src/plugins/kibana_react/public'; +import { FeatureCatalogueEntry } from '../../../../../../src/plugins/home/public'; +// @ts-expect-error untyped component +import { Synopsis } from '../synopsis'; + +interface Props { + addBasePath: (path: string) => string; + features: FeatureCatalogueEntry[]; +} + +export const ManageData: FC = ({ addBasePath, features }) => { + const { + services: { application }, + } = useKibana(); + return ( + <> + {features.length > 1 ?

); diff --git a/src/plugins/kibana_react/public/index.ts b/src/plugins/kibana_react/public/index.ts index 9a9486da892e4..2b555e2334691 100644 --- a/src/plugins/kibana_react/public/index.ts +++ b/src/plugins/kibana_react/public/index.ts @@ -20,6 +20,7 @@ export * from './code_editor'; export * from './exit_full_screen_button'; export * from './context'; +export * from './overview_page'; export * from './overlays'; export * from './ui_settings'; export * from './field_icon'; diff --git a/src/plugins/kibana_react/public/markdown/index.tsx b/src/plugins/kibana_react/public/markdown/index.tsx index cacf223cf33ed..4d6fd0b742ee4 100644 --- a/src/plugins/kibana_react/public/markdown/index.tsx +++ b/src/plugins/kibana_react/public/markdown/index.tsx @@ -17,5 +17,27 @@ * under the License. */ -export { MarkdownSimple } from './markdown_simple'; -export { Markdown } from './markdown'; +import React from 'react'; +import { EuiLoadingContent, EuiDelayRender } from '@elastic/eui'; +import type { MarkdownSimpleProps } from './markdown_simple'; +import type { MarkdownProps } from './markdown'; + +const Fallback = () => ( + + + +); + +const LazyMarkdownSimple = React.lazy(() => import('./markdown_simple')); +export const MarkdownSimple = (props: MarkdownSimpleProps) => ( + }> + + +); + +const LazyMarkdown = React.lazy(() => import('./markdown')); +export const Markdown = (props: MarkdownProps) => ( + }> + + +); diff --git a/src/plugins/kibana_react/public/markdown/markdown.tsx b/src/plugins/kibana_react/public/markdown/markdown.tsx index 15d1c4931e60b..8bb61bc71862e 100644 --- a/src/plugins/kibana_react/public/markdown/markdown.tsx +++ b/src/plugins/kibana_react/public/markdown/markdown.tsx @@ -84,7 +84,7 @@ export const markdownFactory = memoize( } ); -interface MarkdownProps extends React.HTMLAttributes { +export interface MarkdownProps extends React.HTMLAttributes { className?: string; markdown?: string; openLinksInNewTab?: boolean; @@ -112,3 +112,7 @@ export class Markdown extends PureComponent { ); } } + +// Needed for React.lazy +// eslint-disable-next-line import/no-default-export +export default Markdown; diff --git a/src/plugins/kibana_react/public/markdown/markdown_simple.tsx b/src/plugins/kibana_react/public/markdown/markdown_simple.tsx index a5465fd1c6fc9..71ae4e031abca 100644 --- a/src/plugins/kibana_react/public/markdown/markdown_simple.tsx +++ b/src/plugins/kibana_react/public/markdown/markdown_simple.tsx @@ -24,7 +24,7 @@ const markdownRenderers = { root: Fragment, }; -interface MarkdownSimpleProps { +export interface MarkdownSimpleProps { children: string; } @@ -32,3 +32,7 @@ interface MarkdownSimpleProps { export const MarkdownSimple = ({ children }: MarkdownSimpleProps) => ( {children} ); + +// Needed for React.lazy +// eslint-disable-next-line import/no-default-export +export default MarkdownSimple; diff --git a/src/plugins/kibana_react/public/overview_page/index.ts b/src/plugins/kibana_react/public/overview_page/index.ts new file mode 100644 index 0000000000000..f1e08928de6e4 --- /dev/null +++ b/src/plugins/kibana_react/public/overview_page/index.ts @@ -0,0 +1,21 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export * from './overview_page_footer'; +export * from './overview_page_header'; diff --git a/src/plugins/kibana_react/public/overview_page/overview_page_footer/__snapshots__/overview_page_footer.test.tsx.snap b/src/plugins/kibana_react/public/overview_page/overview_page_footer/__snapshots__/overview_page_footer.test.tsx.snap new file mode 100644 index 0000000000000..491b81c554511 --- /dev/null +++ b/src/plugins/kibana_react/public/overview_page/overview_page_footer/__snapshots__/overview_page_footer.test.tsx.snap @@ -0,0 +1,49 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`OverviewPageFooter render 1`] = ` +
+ + +
+ + +
+ + + + + +
+
+ +
+`; diff --git a/src/plugins/kibana_react/public/overview_page/overview_page_footer/index.ts b/src/plugins/kibana_react/public/overview_page/overview_page_footer/index.ts new file mode 100644 index 0000000000000..4c74c95a592e8 --- /dev/null +++ b/src/plugins/kibana_react/public/overview_page/overview_page_footer/index.ts @@ -0,0 +1,20 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export * from './overview_page_footer'; diff --git a/src/plugins/kibana_react/public/overview_page/overview_page_footer/overview_page_footer.test.tsx b/src/plugins/kibana_react/public/overview_page/overview_page_footer/overview_page_footer.test.tsx new file mode 100644 index 0000000000000..ac28211d5032a --- /dev/null +++ b/src/plugins/kibana_react/public/overview_page/overview_page_footer/overview_page_footer.test.tsx @@ -0,0 +1,52 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React from 'react'; +import { OverviewPageFooter } from './overview_page_footer'; +import { shallowWithIntl } from 'test_utils/enzyme_helpers'; + +jest.mock('../../app_links', () => ({ + RedirectAppLinks: jest.fn((element: JSX.Element) => element), +})); + +jest.mock('../../context', () => ({ + useKibana: jest.fn().mockReturnValue({ + services: { + application: { capabilities: { advancedSettings: { show: true } } }, + notifications: { toast: { addSuccess: jest.fn() } }, + }, + }), +})); + +jest.mock('../../ui_settings', () => ({ + useUiSetting$: jest.fn().mockReturnValue(['path-to-default-route', jest.fn()]), +})); + +afterEach(() => jest.clearAllMocks()); + +const addBasePathMock = jest.fn((path: string) => (path ? path : 'path')); + +describe('OverviewPageFooter', () => { + test('render', () => { + const component = shallowWithIntl( + + ); + expect(component).toMatchSnapshot(); + }); +}); diff --git a/src/plugins/kibana_react/public/overview_page/overview_page_footer/overview_page_footer.tsx b/src/plugins/kibana_react/public/overview_page/overview_page_footer/overview_page_footer.tsx new file mode 100644 index 0000000000000..4a8a5276e0e7d --- /dev/null +++ b/src/plugins/kibana_react/public/overview_page/overview_page_footer/overview_page_footer.tsx @@ -0,0 +1,114 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React, { FC } from 'react'; +import { EuiFlexGroup, EuiFlexItem, EuiButtonEmpty } from '@elastic/eui'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { i18n } from '@kbn/i18n'; +import { CoreStart } from 'kibana/public'; +import { RedirectAppLinks } from '../../app_links'; +import { useKibana } from '../../context'; +import { useUiSetting$ } from '../../ui_settings'; + +interface Props { + addBasePath: (path: string) => string; + /** The path to set as the new default route in advanced settings */ + path: string; +} + +export const OverviewPageFooter: FC = ({ addBasePath, path }) => { + const [defaultRoute, setDefaultRoute] = useUiSetting$('defaultRoute'); + const { + services: { + application, + notifications: { toasts }, + }, + } = useKibana(); + + const { show, save } = application.capabilities.advancedSettings; + const isAdvancedSettingsEnabled = show && save; + + const defaultRoutebutton = + defaultRoute === path ? ( + + + + + + ) : ( + { + setDefaultRoute(path); + toasts.addSuccess({ + title: i18n.translate('kibana-react.pageFooter.changeDefaultRouteSuccessToast', { + defaultMessage: 'Landing page updated', + }), + }); + }} + size="xs" + > + + + ); + + return ( +
+ + +
{isAdvancedSettingsEnabled ? defaultRoutebutton : null}
+
+ + +
+ + + + + +
+
+
+
+ ); +}; diff --git a/src/plugins/kibana_react/public/overview_page/overview_page_header/__snapshots__/overview_page_header.test.tsx.snap b/src/plugins/kibana_react/public/overview_page/overview_page_header/__snapshots__/overview_page_header.test.tsx.snap new file mode 100644 index 0000000000000..d4f37b0bb9521 --- /dev/null +++ b/src/plugins/kibana_react/public/overview_page/overview_page_header/__snapshots__/overview_page_header.test.tsx.snap @@ -0,0 +1,68 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`OverviewPageHeader render 1`] = ` +
+
+ + + + + +

+ Page Title +

+
+
+
+
+ + + + + + Add data + + + + + +
+
+
+`; diff --git a/src/plugins/kibana_react/public/overview_page/overview_page_header/_overview_page_header.scss b/src/plugins/kibana_react/public/overview_page/overview_page_header/_overview_page_header.scss new file mode 100644 index 0000000000000..ae53ac94bd006 --- /dev/null +++ b/src/plugins/kibana_react/public/overview_page/overview_page_header/_overview_page_header.scss @@ -0,0 +1,33 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +.kbnOverviewPageHeader { + background-color: $euiPageBackgroundColor; + border-bottom: $euiBorderWidthThin solid $euiColorLightShade; +} + +.kbnOverviewPageHeader__inner { + margin: 0 auto; + max-width: 1200px; + padding: $euiSizeXL $euiSize; + + .kbnOverviewPageHeader--hasOverlap & { + padding-bottom: $euiSizeXL + $euiSizeL; + } +} diff --git a/src/plugins/kibana_react/public/overview_page/overview_page_header/index.scss b/src/plugins/kibana_react/public/overview_page/overview_page_header/index.scss new file mode 100644 index 0000000000000..5fb572d07522f --- /dev/null +++ b/src/plugins/kibana_react/public/overview_page/overview_page_header/index.scss @@ -0,0 +1,20 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +@import './overview_page_header'; diff --git a/src/plugins/kibana_react/public/overview_page/overview_page_header/index.ts b/src/plugins/kibana_react/public/overview_page/overview_page_header/index.ts new file mode 100644 index 0000000000000..d5b81a72bf38f --- /dev/null +++ b/src/plugins/kibana_react/public/overview_page/overview_page_header/index.ts @@ -0,0 +1,20 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export * from './overview_page_header'; diff --git a/src/plugins/kibana_react/public/overview_page/overview_page_header/overview_page_header.test.tsx b/src/plugins/kibana_react/public/overview_page/overview_page_header/overview_page_header.test.tsx new file mode 100644 index 0000000000000..73e5dada02d09 --- /dev/null +++ b/src/plugins/kibana_react/public/overview_page/overview_page_header/overview_page_header.test.tsx @@ -0,0 +1,49 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React from 'react'; +import { OverviewPageHeader } from './overview_page_header'; +import { shallowWithIntl } from 'test_utils/enzyme_helpers'; + +jest.mock('../../app_links', () => ({ + RedirectAppLinks: jest.fn((element: JSX.Element) => element), +})); + +jest.mock('../../context', () => ({ + useKibana: jest.fn().mockReturnValue({ + services: { + application: { capabilities: { navLinks: { management: true, dev_tools: true } } }, + notifications: { toast: { addSuccess: jest.fn() } }, + }, + }), +})); + +afterAll(() => jest.clearAllMocks()); + +const mockTitle = 'Page Title'; +const addBasePathMock = jest.fn((path: string) => (path ? path : 'path')); + +describe('OverviewPageHeader', () => { + test('render', () => { + const component = shallowWithIntl( + + ); + expect(component).toMatchSnapshot(); + }); +}); diff --git a/src/plugins/kibana_react/public/overview_page/overview_page_header/overview_page_header.tsx b/src/plugins/kibana_react/public/overview_page/overview_page_header/overview_page_header.tsx new file mode 100644 index 0000000000000..645843b00f537 --- /dev/null +++ b/src/plugins/kibana_react/public/overview_page/overview_page_header/overview_page_header.tsx @@ -0,0 +1,149 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React, { FC } from 'react'; +import { + EuiButtonEmpty, + EuiFlexGroup, + EuiFlexItem, + EuiIcon, + EuiTitle, + IconType, +} from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import { CoreStart } from 'kibana/public'; +import { RedirectAppLinks } from '../../app_links'; +import { useKibana } from '../../context'; + +import './index.scss'; + +interface Props { + hideToolbar?: boolean; + iconType?: IconType; + overlap?: boolean; + showDevToolsLink?: boolean; + showManagementLink?: boolean; + title: JSX.Element | string; + addBasePath: (path: string) => string; +} + +export const OverviewPageHeader: FC = ({ + hideToolbar, + iconType, + overlap, + showDevToolsLink, + showManagementLink, + title, + addBasePath, +}) => { + const { + services: { application }, + } = useKibana(); + + const { + management: isManagementEnabled, + dev_tools: isDevToolsEnabled, + } = application.capabilities.navLinks; + + return ( +
+
+ + + + {iconType && ( + + + + )} + + + +

{title}

+
+
+
+
+ + {!hideToolbar && ( + + + + + + {i18n.translate('kibana-react.kbnOverviewPageHeader.addDataButtonLabel', { + defaultMessage: 'Add data', + })} + + + + + {showManagementLink && isManagementEnabled ? ( + + + + {i18n.translate( + 'kibana-react.kbnOverviewPageHeader.stackManagementButtonLabel', + { + defaultMessage: 'Manage', + } + )} + + + + ) : null} + + {showDevToolsLink && isDevToolsEnabled ? ( + + + + {i18n.translate('kibana-react.kbnOverviewPageHeader.devToolsButtonLabel', { + defaultMessage: 'Dev tools', + })} + + + + ) : null} + + + )} +
+
+
+ ); +}; diff --git a/src/plugins/kibana_react/public/table_list_view/table_list_view.tsx b/src/plugins/kibana_react/public/table_list_view/table_list_view.tsx index 2fa1debf51b5c..e0e295723a69d 100644 --- a/src/plugins/kibana_react/public/table_list_view/table_list_view.tsx +++ b/src/plugins/kibana_react/public/table_list_view/table_list_view.tsx @@ -556,3 +556,6 @@ class TableListView extends React.Component { const getUsageCollector = jest.fn(); const registerType = jest.fn(); const callCluster = jest.fn(); + const esClient = elasticsearchServiceMock.createClusterClient().asInternalUser; beforeAll(() => registerApplicationUsageCollector(logger, usageCollectionMock, registerType, getUsageCollector) @@ -62,7 +67,7 @@ describe('telemetry_application_usage', () => { test('if no savedObjectClient initialised, return undefined', async () => { expect(collector.isReady()).toBe(false); - expect(await collector.fetch(callCluster)).toBeUndefined(); + expect(await collector.fetch(callCluster, esClient)).toBeUndefined(); jest.runTimersToTime(ROLL_INDICES_START); }); @@ -80,7 +85,7 @@ describe('telemetry_application_usage', () => { jest.runTimersToTime(ROLL_TOTAL_INDICES_INTERVAL); // Force rollTotals to run expect(collector.isReady()).toBe(true); - expect(await collector.fetch(callCluster)).toStrictEqual({}); + expect(await collector.fetch(callCluster, esClient)).toStrictEqual({}); expect(savedObjectClient.bulkCreate).not.toHaveBeenCalled(); }); @@ -137,7 +142,7 @@ describe('telemetry_application_usage', () => { jest.runTimersToTime(ROLL_TOTAL_INDICES_INTERVAL); // Force rollTotals to run - expect(await collector.fetch(callCluster)).toStrictEqual({ + expect(await collector.fetch(callCluster, esClient)).toStrictEqual({ appId: { clicks_total: total + 1 + 10, clicks_7_days: total + 1, @@ -197,7 +202,7 @@ describe('telemetry_application_usage', () => { getUsageCollector.mockImplementation(() => savedObjectClient); - expect(await collector.fetch(callCluster)).toStrictEqual({ + expect(await collector.fetch(callCluster, esClient)).toStrictEqual({ appId: { clicks_total: 1, clicks_7_days: 0, diff --git a/src/plugins/kibana_usage_collection/server/collectors/core/core_usage_collector.ts b/src/plugins/kibana_usage_collection/server/collectors/core/core_usage_collector.ts new file mode 100644 index 0000000000000..297baf016e9e6 --- /dev/null +++ b/src/plugins/kibana_usage_collection/server/collectors/core/core_usage_collector.ts @@ -0,0 +1,132 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { UsageCollectionSetup } from 'src/plugins/usage_collection/server'; +import { CoreUsageData, CoreUsageDataStart } from '../../../../../core/server'; + +export function getCoreUsageCollector( + usageCollection: UsageCollectionSetup, + getCoreUsageDataService: () => CoreUsageDataStart +) { + return usageCollection.makeUsageCollector({ + type: 'core', + isReady: () => typeof getCoreUsageDataService() !== 'undefined', + schema: { + config: { + elasticsearch: { + sniffOnStart: { type: 'boolean' }, + sniffIntervalMs: { type: 'long' }, + sniffOnConnectionFault: { type: 'boolean' }, + numberOfHostsConfigured: { type: 'long' }, + requestHeadersWhitelistConfigured: { type: 'boolean' }, + customHeadersConfigured: { type: 'boolean' }, + shardTimeoutMs: { type: 'long' }, + requestTimeoutMs: { type: 'long' }, + pingTimeoutMs: { type: 'long' }, + logQueries: { type: 'boolean' }, + ssl: { + verificationMode: { type: 'keyword' }, + certificateAuthoritiesConfigured: { type: 'boolean' }, + certificateConfigured: { type: 'boolean' }, + keyConfigured: { type: 'boolean' }, + keystoreConfigured: { type: 'boolean' }, + truststoreConfigured: { type: 'boolean' }, + alwaysPresentCertificate: { type: 'boolean' }, + }, + apiVersion: { type: 'keyword' }, + healthCheckDelayMs: { type: 'long' }, + }, + + http: { + basePathConfigured: { type: 'boolean' }, + maxPayloadInBytes: { type: 'long' }, + rewriteBasePath: { type: 'boolean' }, + keepaliveTimeout: { type: 'long' }, + socketTimeout: { type: 'long' }, + compression: { + enabled: { type: 'boolean' }, + referrerWhitelistConfigured: { type: 'boolean' }, + }, + xsrf: { + disableProtection: { type: 'boolean' }, + whitelistConfigured: { type: 'boolean' }, + }, + requestId: { + allowFromAnyIp: { type: 'boolean' }, + ipAllowlistConfigured: { type: 'boolean' }, + }, + ssl: { + certificateAuthoritiesConfigured: { type: 'boolean' }, + certificateConfigured: { type: 'boolean' }, + cipherSuites: { type: 'array', items: { type: 'keyword' } }, + keyConfigured: { type: 'boolean' }, + keystoreConfigured: { type: 'boolean' }, + truststoreConfigured: { type: 'boolean' }, + redirectHttpFromPortConfigured: { type: 'boolean' }, + supportedProtocols: { type: 'array', items: { type: 'keyword' } }, + clientAuthentication: { type: 'keyword' }, + }, + }, + + logging: { + appendersTypesUsed: { type: 'array', items: { type: 'keyword' } }, + loggersConfiguredCount: { type: 'long' }, + }, + + savedObjects: { + maxImportPayloadBytes: { type: 'long' }, + maxImportExportSizeBytes: { type: 'long' }, + }, + }, + environment: { + memory: { + heapSizeLimit: { type: 'long' }, + heapTotalBytes: { type: 'long' }, + heapUsedBytes: { type: 'long' }, + }, + }, + services: { + savedObjects: { + indices: { + type: 'array', + items: { + docsCount: { type: 'long' }, + docsDeleted: { type: 'long' }, + alias: { type: 'text' }, + primaryStoreSizeBytes: { type: 'long' }, + storeSizeBytes: { type: 'long' }, + }, + }, + }, + }, + }, + fetch() { + return getCoreUsageDataService().getCoreUsageData(); + }, + }); +} + +export function registerCoreUsageCollector( + usageCollection: UsageCollectionSetup, + getCoreUsageDataService: () => CoreUsageDataStart +) { + usageCollection.registerCollector( + getCoreUsageCollector(usageCollection, getCoreUsageDataService) + ); +} diff --git a/src/plugins/kibana_usage_collection/server/collectors/core/index.test.ts b/src/plugins/kibana_usage_collection/server/collectors/core/index.test.ts new file mode 100644 index 0000000000000..b712e9ebbce48 --- /dev/null +++ b/src/plugins/kibana_usage_collection/server/collectors/core/index.test.ts @@ -0,0 +1,53 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { + CollectorOptions, + createUsageCollectionSetupMock, +} from '../../../../usage_collection/server/usage_collection.mock'; + +import { registerCoreUsageCollector } from '.'; +import { coreUsageDataServiceMock } from '../../../../../core/server/mocks'; +import { CoreUsageData } from 'src/core/server/'; + +describe('telemetry_core', () => { + let collector: CollectorOptions; + + const usageCollectionMock = createUsageCollectionSetupMock(); + usageCollectionMock.makeUsageCollector.mockImplementation((config) => { + collector = config; + return createUsageCollectionSetupMock().makeUsageCollector(config); + }); + + const callCluster = jest.fn().mockImplementation(() => ({})); + const coreUsageDataStart = coreUsageDataServiceMock.createStartContract(); + const getCoreUsageDataReturnValue = (Symbol('core telemetry') as any) as CoreUsageData; + coreUsageDataStart.getCoreUsageData.mockResolvedValue(getCoreUsageDataReturnValue); + + beforeAll(() => registerCoreUsageCollector(usageCollectionMock, () => coreUsageDataStart)); + + test('registered collector is set', () => { + expect(collector).not.toBeUndefined(); + expect(collector.type).toBe('core'); + }); + + test('fetch', async () => { + expect(await collector.fetch(callCluster)).toEqual(getCoreUsageDataReturnValue); + }); +}); diff --git a/src/plugins/kibana_usage_collection/server/collectors/core/index.ts b/src/plugins/kibana_usage_collection/server/collectors/core/index.ts new file mode 100644 index 0000000000000..79a4b83b41355 --- /dev/null +++ b/src/plugins/kibana_usage_collection/server/collectors/core/index.ts @@ -0,0 +1,20 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export { registerCoreUsageCollector } from './core_usage_collector'; diff --git a/src/plugins/kibana_usage_collection/server/collectors/index.ts b/src/plugins/kibana_usage_collection/server/collectors/index.ts index 1f9fe130fa45d..2408dc84c2e56 100644 --- a/src/plugins/kibana_usage_collection/server/collectors/index.ts +++ b/src/plugins/kibana_usage_collection/server/collectors/index.ts @@ -23,3 +23,4 @@ export { registerApplicationUsageCollector } from './application_usage'; export { registerKibanaUsageCollector } from './kibana'; export { registerOpsStatsCollector } from './ops_stats'; export { registerCspCollector } from './csp'; +export { registerCoreUsageCollector } from './core'; diff --git a/src/plugins/kibana_usage_collection/server/collectors/kibana/get_saved_object_counts.ts b/src/plugins/kibana_usage_collection/server/collectors/kibana/get_saved_object_counts.ts index 1adc0dc6896fd..e88d90fe5b24b 100644 --- a/src/plugins/kibana_usage_collection/server/collectors/kibana/get_saved_object_counts.ts +++ b/src/plugins/kibana_usage_collection/server/collectors/kibana/get_saved_object_counts.ts @@ -39,9 +39,12 @@ const TYPES = [ ]; export interface KibanaSavedObjectCounts { - [pluginName: string]: { - total: number; - }; + dashboard: { total: number }; + visualization: { total: number }; + search: { total: number }; + index_pattern: { total: number }; + graph_workspace: { total: number }; + timelion_sheet: { total: number }; } export async function getSavedObjectsCounts( @@ -71,7 +74,7 @@ export async function getSavedObjectsCounts( // Initialise the object with all zeros for all the types const allZeros: KibanaSavedObjectCounts = TYPES.reduce( (acc, type) => ({ ...acc, [snakeCase(type)]: { total: 0 } }), - {} + {} as KibanaSavedObjectCounts ); // Add the doc_count from each bucket diff --git a/src/plugins/kibana_usage_collection/server/collectors/kibana/kibana_usage_collector.ts b/src/plugins/kibana_usage_collection/server/collectors/kibana/kibana_usage_collector.ts index 9cc079a9325d5..5b56e1a9b596f 100644 --- a/src/plugins/kibana_usage_collection/server/collectors/kibana/kibana_usage_collector.ts +++ b/src/plugins/kibana_usage_collection/server/collectors/kibana/kibana_usage_collector.ts @@ -22,15 +22,28 @@ import { take } from 'rxjs/operators'; import { SharedGlobalConfig } from 'kibana/server'; import { UsageCollectionSetup } from 'src/plugins/usage_collection/server'; import { KIBANA_STATS_TYPE } from '../../../common/constants'; -import { getSavedObjectsCounts } from './get_saved_object_counts'; +import { getSavedObjectsCounts, KibanaSavedObjectCounts } from './get_saved_object_counts'; + +interface KibanaUsage extends KibanaSavedObjectCounts { + index: string; +} export function getKibanaUsageCollector( usageCollection: UsageCollectionSetup, legacyConfig$: Observable ) { - return usageCollection.makeUsageCollector({ + return usageCollection.makeUsageCollector({ type: 'kibana', isReady: () => true, + schema: { + index: { type: 'keyword' }, + dashboard: { total: { type: 'long' } }, + visualization: { total: { type: 'long' } }, + search: { total: { type: 'long' } }, + index_pattern: { total: { type: 'long' } }, + graph_workspace: { total: { type: 'long' } }, + timelion_sheet: { total: { type: 'long' } }, + }, async fetch(callCluster) { const { kibana: { index }, diff --git a/src/plugins/kibana_usage_collection/server/collectors/management/schema.ts b/src/plugins/kibana_usage_collection/server/collectors/management/schema.ts new file mode 100644 index 0000000000000..792ac24b4de3d --- /dev/null +++ b/src/plugins/kibana_usage_collection/server/collectors/management/schema.ts @@ -0,0 +1,116 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { MakeSchemaFrom } from 'src/plugins/usage_collection/server'; +import { UsageStats } from './telemetry_management_collector'; + +// Retrieved by changing all the current settings in Kibana (we'll need to revisit it in the future). +// I would suggest we use flattened type for the mappings of this collector. +export const stackManagementSchema: MakeSchemaFrom = { + 'visualize:enableLabs': { type: 'boolean' }, + 'visualization:heatmap:maxBuckets': { type: 'long' }, + 'visualization:colorMapping': { type: 'text' }, + 'visualization:regionmap:showWarnings': { type: 'boolean' }, + 'visualization:dimmingOpacity': { type: 'float' }, + 'visualization:tileMap:maxPrecision': { type: 'long' }, + 'securitySolution:ipReputationLinks': { type: 'text' }, + 'csv:separator': { type: 'keyword' }, + 'visualization:tileMap:WMSdefaults': { type: 'text' }, + 'timelion:target_buckets': { type: 'long' }, + 'timelion:max_buckets': { type: 'long' }, + 'timelion:es.timefield': { type: 'keyword' }, + 'timelion:min_interval': { type: 'keyword' }, + 'timelion:default_rows': { type: 'long' }, + 'timelion:default_columns': { type: 'long' }, + 'timelion:quandl.key': { type: 'keyword' }, + 'timelion:es.default_index': { type: 'keyword' }, + 'timelion:showTutorial': { type: 'boolean' }, + 'securitySolution:timeDefaults': { type: 'keyword' }, + 'securitySolution:defaultAnomalyScore': { type: 'long' }, + 'securitySolution:defaultIndex': { type: 'keyword' }, // it's an array + 'securitySolution:refreshIntervalDefaults': { type: 'keyword' }, + 'securitySolution:newsFeedUrl': { type: 'keyword' }, + 'securitySolution:enableNewsFeed': { type: 'boolean' }, + 'search:includeFrozen': { type: 'boolean' }, + 'courier:maxConcurrentShardRequests': { type: 'long' }, + 'courier:batchSearches': { type: 'boolean' }, + 'courier:setRequestPreference': { type: 'keyword' }, + 'courier:customRequestPreference': { type: 'keyword' }, + 'courier:ignoreFilterIfFieldNotInIndex': { type: 'boolean' }, + 'rollups:enableIndexPatterns': { type: 'boolean' }, + 'xpackReporting:customPdfLogo': { type: 'text' }, + 'notifications:lifetime:warning': { type: 'long' }, + 'notifications:lifetime:banner': { type: 'long' }, + 'notifications:lifetime:info': { type: 'long' }, + 'notifications:banner': { type: 'text' }, + 'notifications:lifetime:error': { type: 'long' }, + 'doc_table:highlight': { type: 'boolean' }, + 'discover:searchOnPageLoad': { type: 'boolean' }, + // eslint-disable-next-line @typescript-eslint/naming-convention + 'doc_table:hideTimeColumn': { type: 'boolean' }, + 'discover:sampleSize': { type: 'long' }, + defaultColumns: { type: 'keyword' }, // it's an array + 'context:defaultSize': { type: 'long' }, + 'discover:aggs:terms:size': { type: 'long' }, + 'context:tieBreakerFields': { type: 'keyword' }, // it's an array + 'discover:sort:defaultOrder': { type: 'keyword' }, + 'context:step': { type: 'long' }, + 'accessibility:disableAnimations': { type: 'boolean' }, + 'ml:fileDataVisualizerMaxFileSize': { type: 'keyword' }, + 'ml:anomalyDetection:results:enableTimeDefaults': { type: 'boolean' }, + 'ml:anomalyDetection:results:timeDefaults': { type: 'keyword' }, + 'truncate:maxHeight': { type: 'long' }, + 'timepicker:timeDefaults': { type: 'keyword' }, + 'timepicker:refreshIntervalDefaults': { type: 'keyword' }, + 'timepicker:quickRanges': { type: 'keyword' }, + 'theme:version': { type: 'keyword' }, + 'theme:darkMode': { type: 'boolean' }, + 'state:storeInSessionStorage': { type: 'boolean' }, + 'savedObjects:perPage': { type: 'long' }, + 'search:queryLanguage': { type: 'keyword' }, + 'shortDots:enable': { type: 'boolean' }, + 'sort:options': { type: 'keyword' }, + 'savedObjects:listingLimit': { type: 'long' }, + 'query:queryString:options': { type: 'keyword' }, + pageNavigation: { type: 'keyword' }, + 'metrics:max_buckets': { type: 'long' }, + 'query:allowLeadingWildcards': { type: 'boolean' }, + metaFields: { type: 'keyword' }, // it's an array + 'indexPattern:placeholder': { type: 'keyword' }, + 'histogram:barTarget': { type: 'long' }, + 'histogram:maxBars': { type: 'long' }, + 'format:number:defaultLocale': { type: 'keyword' }, + 'format:percent:defaultPattern': { type: 'keyword' }, + 'format:number:defaultPattern': { type: 'keyword' }, + 'history:limit': { type: 'long' }, + 'format:defaultTypeMap': { type: 'keyword' }, + 'format:currency:defaultPattern': { type: 'keyword' }, + defaultIndex: { type: 'keyword' }, + 'format:bytes:defaultPattern': { type: 'keyword' }, + 'filters:pinnedByDefault': { type: 'boolean' }, + 'filterEditor:suggestValues': { type: 'boolean' }, + 'fields:popularLimit': { type: 'long' }, + dateNanosFormat: { type: 'keyword' }, + defaultRoute: { type: 'keyword' }, + 'dateFormat:tz': { type: 'keyword' }, + 'dateFormat:scaled': { type: 'keyword' }, + 'csv:quoteValues': { type: 'boolean' }, + 'dateFormat:dow': { type: 'keyword' }, + dateFormat: { type: 'keyword' }, +}; diff --git a/src/plugins/kibana_usage_collection/server/collectors/management/telemetry_management_collector.ts b/src/plugins/kibana_usage_collection/server/collectors/management/telemetry_management_collector.ts index 3a777beebd90a..612b1714020ef 100644 --- a/src/plugins/kibana_usage_collection/server/collectors/management/telemetry_management_collector.ts +++ b/src/plugins/kibana_usage_collection/server/collectors/management/telemetry_management_collector.ts @@ -19,8 +19,13 @@ import { IUiSettingsClient } from 'kibana/server'; import { UsageCollectionSetup } from 'src/plugins/usage_collection/server'; +import { stackManagementSchema } from './schema'; -export type UsageStats = Record; +export interface UsageStats extends Record { + // We don't support `type` yet. Only interfaces. So I added at least 1 known key to the generic + // Record extension to avoid eslint reverting it back to a `type` + 'visualize:enableLabs': boolean; +} export function createCollectorFetch(getUiSettingsClient: () => IUiSettingsClient | undefined) { return async function fetchUsageStats(): Promise { @@ -45,10 +50,11 @@ export function registerManagementUsageCollector( usageCollection: UsageCollectionSetup, getUiSettingsClient: () => IUiSettingsClient | undefined ) { - const collector = usageCollection.makeUsageCollector({ + const collector = usageCollection.makeUsageCollector({ type: 'stack_management', isReady: () => typeof getUiSettingsClient() !== 'undefined', fetch: createCollectorFetch(getUiSettingsClient), + schema: stackManagementSchema, }); usageCollection.registerCollector(collector); diff --git a/src/plugins/kibana_usage_collection/server/collectors/ui_metric/schema.ts b/src/plugins/kibana_usage_collection/server/collectors/ui_metric/schema.ts new file mode 100644 index 0000000000000..53bb1f9b93949 --- /dev/null +++ b/src/plugins/kibana_usage_collection/server/collectors/ui_metric/schema.ts @@ -0,0 +1,103 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +import { MakeSchemaFrom } from 'src/plugins/usage_collection/server'; +import { UIMetricUsage } from './telemetry_ui_metric_collector'; + +const commonSchema: MakeSchemaFrom[string] = { + type: 'array', + items: { + key: { type: 'keyword' }, + value: { type: 'long' }, + }, +}; + +// TODO: Find a way to retrieve it automatically +// plugin `data` registers all UI Metric for each appId where searches are performed (keys below are copy-pasted from application_usage) +const uiMetricFromDataPluginSchema: MakeSchemaFrom = { + // OSS + dashboards: commonSchema, + dev_tools: commonSchema, + discover: commonSchema, + home: commonSchema, + kibana: commonSchema, // It's a forward app so we'll likely never report it + management: commonSchema, + short_url_redirect: commonSchema, // It's a forward app so we'll likely never report it + timelion: commonSchema, + visualize: commonSchema, + + // X-Pack + apm: commonSchema, + csm: commonSchema, + canvas: commonSchema, + dashboard_mode: commonSchema, // It's a forward app so we'll likely never report it + enterpriseSearch: commonSchema, + appSearch: commonSchema, + workplaceSearch: commonSchema, + graph: commonSchema, + logs: commonSchema, + metrics: commonSchema, + infra: commonSchema, // It's a forward app so we'll likely never report it + ingestManager: commonSchema, + lens: commonSchema, + maps: commonSchema, + ml: commonSchema, + monitoring: commonSchema, + 'observability-overview': commonSchema, + security_account: commonSchema, + security_access_agreement: commonSchema, + security_capture_url: commonSchema, // It's a forward app so we'll likely never report it + security_logged_out: commonSchema, + security_login: commonSchema, + security_logout: commonSchema, + security_overwritten_session: commonSchema, + securitySolution: commonSchema, + 'securitySolution:overview': commonSchema, + 'securitySolution:detections': commonSchema, + 'securitySolution:hosts': commonSchema, + 'securitySolution:network': commonSchema, + 'securitySolution:timelines': commonSchema, + 'securitySolution:case': commonSchema, + 'securitySolution:administration': commonSchema, + siem: commonSchema, + space_selector: commonSchema, + uptime: commonSchema, +}; + +// TODO: Find a way to retrieve it automatically +// Searching `reportUiStats` across Kibana +export const uiMetricSchema: MakeSchemaFrom = { + console: commonSchema, + DashboardPanelVersionInUrl: commonSchema, + Kibana_home: commonSchema, // eslint-disable-line @typescript-eslint/naming-convention + visualize: commonSchema, + canvas: commonSchema, + cross_cluster_replication: commonSchema, + index_lifecycle_management: commonSchema, + index_management: commonSchema, + ingest_pipelines: commonSchema, + apm: commonSchema, + infra_logs: commonSchema, + infra_metrics: commonSchema, + stack_monitoring: commonSchema, + remote_clusters: commonSchema, + rollup_jobs: commonSchema, + securitySolution: commonSchema, + snapshot_restore: commonSchema, + ...uiMetricFromDataPluginSchema, +}; diff --git a/src/plugins/kibana_usage_collection/server/collectors/ui_metric/telemetry_ui_metric_collector.ts b/src/plugins/kibana_usage_collection/server/collectors/ui_metric/telemetry_ui_metric_collector.ts index 9c02a9cbf3204..4cae892d30b5d 100644 --- a/src/plugins/kibana_usage_collection/server/collectors/ui_metric/telemetry_ui_metric_collector.ts +++ b/src/plugins/kibana_usage_collection/server/collectors/ui_metric/telemetry_ui_metric_collector.ts @@ -23,11 +23,19 @@ import { SavedObjectsServiceSetup, } from 'kibana/server'; import { UsageCollectionSetup } from 'src/plugins/usage_collection/server'; +import { uiMetricSchema } from './schema'; interface UIMetricsSavedObjects extends SavedObjectAttributes { count: number; } +interface UIMetricElement { + key: string; + value: number; +} + +export type UIMetricUsage = Record; + export function registerUiMetricUsageCollector( usageCollection: UsageCollectionSetup, registerType: SavedObjectsServiceSetup['registerType'], @@ -46,8 +54,9 @@ export function registerUiMetricUsageCollector( }, }); - const collector = usageCollection.makeUsageCollector({ + const collector = usageCollection.makeUsageCollector({ type: 'ui_metric', + schema: uiMetricSchema, fetch: async () => { const savedObjectsClient = getSavedObjectsClient(); if (typeof savedObjectsClient === 'undefined') { @@ -73,7 +82,7 @@ export function registerUiMetricUsageCollector( ...accum, [appName]: [...(accum[appName] || []), pair], }; - }, {} as Record>); + }, {} as UIMetricUsage); return uiMetricsByAppName; }, diff --git a/src/plugins/kibana_usage_collection/server/plugin.ts b/src/plugins/kibana_usage_collection/server/plugin.ts index 260acd19ab516..198fdbb7a8703 100644 --- a/src/plugins/kibana_usage_collection/server/plugin.ts +++ b/src/plugins/kibana_usage_collection/server/plugin.ts @@ -31,6 +31,7 @@ import { SavedObjectsServiceSetup, OpsMetrics, Logger, + CoreUsageDataStart, } from '../../../core/server'; import { registerApplicationUsageCollector, @@ -39,6 +40,7 @@ import { registerOpsStatsCollector, registerUiMetricUsageCollector, registerCspCollector, + registerCoreUsageCollector, } from './collectors'; interface KibanaUsageCollectionPluginsDepsSetup { @@ -53,6 +55,7 @@ export class KibanaUsageCollectionPlugin implements Plugin { private savedObjectsClient?: ISavedObjectsRepository; private uiSettingsClient?: IUiSettingsClient; private metric$: Subject; + private coreUsageData?: CoreUsageDataStart; constructor(initializerContext: PluginInitializerContext) { this.logger = initializerContext.logger.get(); @@ -72,6 +75,7 @@ export class KibanaUsageCollectionPlugin implements Plugin { const savedObjectsClient = new SavedObjectsClient(this.savedObjectsClient); this.uiSettingsClient = uiSettings.asScopedToClient(savedObjectsClient); core.metrics.getOpsMetrics$().subscribe(this.metric$); + this.coreUsageData = core.coreUsageData; } public stop() { @@ -86,6 +90,7 @@ export class KibanaUsageCollectionPlugin implements Plugin { ) { const getSavedObjectsClient = () => this.savedObjectsClient; const getUiSettingsClient = () => this.uiSettingsClient; + const getCoreUsageDataService = () => this.coreUsageData!; registerOpsStatsCollector(usageCollection, metric$); registerKibanaUsageCollector(usageCollection, this.legacyConfig$); @@ -98,5 +103,6 @@ export class KibanaUsageCollectionPlugin implements Plugin { getSavedObjectsClient ); registerCspCollector(usageCollection, coreSetup.http); + registerCoreUsageCollector(usageCollection, getCoreUsageDataService); } } diff --git a/src/plugins/kibana_utils/kibana.json b/src/plugins/kibana_utils/kibana.json index 7e2127c27548e..3e20b68bca431 100644 --- a/src/plugins/kibana_utils/kibana.json +++ b/src/plugins/kibana_utils/kibana.json @@ -2,6 +2,7 @@ "id": "kibanaUtils", "version": "kibana", "ui": true, + "server": false, "extraPublicDirs": [ "common", "demos/state_containers/todomvc", diff --git a/src/plugins/kibana_utils/public/history/redirect_when_missing.tsx b/src/plugins/kibana_utils/public/history/redirect_when_missing.tsx index d8121b656deeb..80e30d2b5dffe 100644 --- a/src/plugins/kibana_utils/public/history/redirect_when_missing.tsx +++ b/src/plugins/kibana_utils/public/history/redirect_when_missing.tsx @@ -20,12 +20,19 @@ import React, { Fragment } from 'react'; import { History } from 'history'; import { i18n } from '@kbn/i18n'; +import { EuiLoadingSpinner } from '@elastic/eui'; import ReactDOM from 'react-dom'; -import ReactMarkdown from 'react-markdown'; import { ApplicationStart, HttpStart, ToastsSetup } from 'kibana/public'; import { SavedObjectNotFound } from '..'; +const ReactMarkdown = React.lazy(() => import('react-markdown')); +const ErrorRenderer = (props: { children: string }) => ( + }> + + +); + interface Mapping { [key: string]: string | { app: string; path: string }; } @@ -96,16 +103,7 @@ export function redirectWhenMissing({ defaultMessage: 'Saved object is missing', }), text: (element: HTMLElement) => { - ReactDOM.render( - - {error.message} - , - element - ); + ReactDOM.render({error.message}, element); return () => ReactDOM.unmountComponentAtNode(element); }, }); diff --git a/src/plugins/kibana_utils/tsconfig.json b/src/plugins/kibana_utils/tsconfig.json new file mode 100644 index 0000000000000..bd65e06c78608 --- /dev/null +++ b/src/plugins/kibana_utils/tsconfig.json @@ -0,0 +1,22 @@ +{ + "extends": "../../../tsconfig.base.json", + "compilerOptions": { + "composite": true, + "outDir": "./target/types", + "emitDeclarationOnly": true, + "declaration": true, + "declarationMap": true + }, + "include": [ + "common/**/*", + "demos/**/*", + "public/**/*", + "server/**/*", + "index.ts", + "../../../typings/**/*" + ], + "references": [ + { "path": "../../test_utils/tsconfig.json" }, + { "path": "../../core/tsconfig.json" } + ] +} diff --git a/src/plugins/legacy_export/server/routes/import.ts b/src/plugins/legacy_export/server/routes/import.ts index 8d33983ad7e3c..135d79d782fd7 100644 --- a/src/plugins/legacy_export/server/routes/import.ts +++ b/src/plugins/legacy_export/server/routes/import.ts @@ -28,7 +28,7 @@ export const registerImportRoute = (router: IRouter, maxImportPayloadBytes: numb validate: { body: schema.object({ objects: schema.arrayOf(schema.recordOf(schema.string(), schema.any())), - version: schema.string(), + version: schema.maybe(schema.string()), }), query: schema.object({ force: schema.boolean({ defaultValue: false }), diff --git a/src/plugins/management/common/contants.ts b/src/plugins/management/common/contants.ts new file mode 100644 index 0000000000000..6ff585510dab1 --- /dev/null +++ b/src/plugins/management/common/contants.ts @@ -0,0 +1,20 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export const MANAGEMENT_APP_ID = 'management'; diff --git a/src/plugins/management/public/components/management_app_wrapper/management_app_wrapper.tsx b/src/plugins/management/public/components/management_app_wrapper/management_app_wrapper.tsx index 02da2a46540c2..bcfb86c331084 100644 --- a/src/plugins/management/public/components/management_app_wrapper/management_app_wrapper.tsx +++ b/src/plugins/management/public/components/management_app_wrapper/management_app_wrapper.tsx @@ -32,7 +32,7 @@ interface ManagementSectionWrapperProps { export class ManagementAppWrapper extends Component { private unmount?: Unmount; - private mountElementRef = createRef(); + private mountElementRef = createRef(); componentDidMount() { const { setBreadcrumbs, app, onAppMounted, history } = this.props; @@ -64,6 +64,6 @@ export class ManagementAppWrapper extends Component; + return
; } } diff --git a/src/plugins/management/public/index.ts b/src/plugins/management/public/index.ts index f6c23ccf0143f..f3e25b90b73c7 100644 --- a/src/plugins/management/public/index.ts +++ b/src/plugins/management/public/index.ts @@ -32,3 +32,5 @@ export { ManagementStart, DefinedSections, } from './types'; + +export { MANAGEMENT_APP_ID } from '../common/contants'; diff --git a/src/plugins/management/public/plugin.ts b/src/plugins/management/public/plugin.ts index 808578c470ae1..122e73796753c 100644 --- a/src/plugins/management/public/plugin.ts +++ b/src/plugins/management/public/plugin.ts @@ -33,6 +33,7 @@ import { AppNavLinkStatus, } from '../../../core/public'; +import { MANAGEMENT_APP_ID } from '../common/contants'; import { ManagementSectionsService, getSectionsServiceStartPrivate, @@ -72,7 +73,7 @@ export class ManagementPlugin implements Plugin) => Promise; + visualizationLabel: string; +} + +export function LegacyMapDeprecationMessage(props: Props) { + const getMapsMessage = !props.isMapsAvailable ? ( + + default distribution + + ), + }} + /> + ) : null; + + const button = props.isMapsAvailable ? ( +
+ + + +
+ ) : null; + + return ( + +

+ +

+ {button} +
+ ); +} diff --git a/src/plugins/maps_legacy/public/get_service_settings.ts b/src/plugins/maps_legacy/public/get_service_settings.ts new file mode 100644 index 0000000000000..8d0656237976d --- /dev/null +++ b/src/plugins/maps_legacy/public/get_service_settings.ts @@ -0,0 +1,39 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { lazyLoadMapsLegacyModules } from './lazy_load_bundle'; +// @ts-expect-error +import { getMapsLegacyConfig } from './kibana_services'; +import { IServiceSettings } from './map/service_settings_types'; + +let loadPromise: Promise; + +export async function getServiceSettings(): Promise { + if (typeof loadPromise !== 'undefined') { + return loadPromise; + } + + loadPromise = new Promise(async (resolve) => { + const modules = await lazyLoadMapsLegacyModules(); + const config = getMapsLegacyConfig(); + // @ts-expect-error + resolve(new modules.ServiceSettings(config, config.tilemap)); + }); + return loadPromise; +} diff --git a/src/plugins/maps_legacy/public/index.ts b/src/plugins/maps_legacy/public/index.ts index 8f14cd1b15e2c..fe5338b890ec8 100644 --- a/src/plugins/maps_legacy/public/index.ts +++ b/src/plugins/maps_legacy/public/index.ts @@ -19,8 +19,6 @@ // @ts-ignore import { PluginInitializerContext } from 'kibana/public'; -// @ts-ignore -import { L } from './leaflet'; import { MapsLegacyPlugin } from './plugin'; // @ts-ignore import * as colorUtil from './map/color_util'; @@ -29,14 +27,14 @@ import { KibanaMapLayer } from './map/kibana_map_layer'; // @ts-ignore import { convertToGeoJson } from './map/convert_to_geojson'; // @ts-ignore -import { scaleBounds, getPrecision, geoContains } from './map/decode_geo_hash'; +import { getPrecision, geoContains } from './map/decode_geo_hash'; import { VectorLayer, FileLayerField, FileLayer, TmsLayer, IServiceSettings, -} from './map/service_settings'; +} from './map/service_settings_types'; // @ts-ignore import { mapTooltipProvider } from './tooltip_provider'; @@ -48,7 +46,6 @@ export function plugin(initializerContext: PluginInitializerContext) { /** @public */ export { - scaleBounds, getPrecision, geoContains, colorUtil, @@ -60,13 +57,15 @@ export { FileLayer, TmsLayer, mapTooltipProvider, - L, }; export * from './common/types'; export { ORIGIN } from './common/constants/origin'; export { WmsOptions } from './components/wms_options'; +export { LegacyMapDeprecationMessage } from './components/legacy_map_deprecation_message'; + +export { lazyLoadMapsLegacyModules } from './lazy_load_bundle'; export type MapsLegacyPluginSetup = ReturnType; export type MapsLegacyPluginStart = ReturnType; diff --git a/src/plugins/maps_legacy/public/lazy_load_bundle/index.ts b/src/plugins/maps_legacy/public/lazy_load_bundle/index.ts new file mode 100644 index 0000000000000..292949503a616 --- /dev/null +++ b/src/plugins/maps_legacy/public/lazy_load_bundle/index.ts @@ -0,0 +1,43 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +let loadModulesPromise: Promise; + +interface LazyLoadedMapsLegacyModules { + KibanaMap: unknown; + L: unknown; + ServiceSettings: unknown; +} + +export async function lazyLoadMapsLegacyModules(): Promise { + if (typeof loadModulesPromise !== 'undefined') { + return loadModulesPromise; + } + + loadModulesPromise = new Promise(async (resolve) => { + const { KibanaMap, L, ServiceSettings } = await import('./lazy'); + + resolve({ + KibanaMap, + L, + ServiceSettings, + }); + }); + return loadModulesPromise; +} diff --git a/src/plugins/maps_legacy/public/lazy_load_bundle/lazy/index.ts b/src/plugins/maps_legacy/public/lazy_load_bundle/lazy/index.ts new file mode 100644 index 0000000000000..5031b29e74b9a --- /dev/null +++ b/src/plugins/maps_legacy/public/lazy_load_bundle/lazy/index.ts @@ -0,0 +1,25 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +// @ts-expect-error +export { KibanaMap } from '../../map/kibana_map'; +// @ts-expect-error +export { ServiceSettings } from '../../map/service_settings'; +// @ts-expect-error +export { L } from '../../leaflet'; diff --git a/src/plugins/maps_legacy/public/map/base_maps_visualization.js b/src/plugins/maps_legacy/public/map/base_maps_visualization.js index 2d78fdc246e19..406dae43c9b5e 100644 --- a/src/plugins/maps_legacy/public/map/base_maps_visualization.js +++ b/src/plugins/maps_legacy/public/map/base_maps_visualization.js @@ -17,25 +17,22 @@ * under the License. */ -import _ from 'lodash'; import { i18n } from '@kbn/i18n'; import * as Rx from 'rxjs'; import { filter, first } from 'rxjs/operators'; import { getEmsTileLayerId, getUiSettings, getToasts } from '../kibana_services'; +import { lazyLoadMapsLegacyModules } from '../lazy_load_bundle'; +import { getServiceSettings } from '../get_service_settings'; const WMS_MINZOOM = 0; const WMS_MAXZOOM = 22; //increase this to 22. Better for WMS -export function BaseMapsVisualizationProvider(getKibanaMap, mapServiceSettings) { +export function BaseMapsVisualizationProvider() { /** * Abstract base class for a visualization consisting of a map with a single baselayer. * @class BaseMapsVisualization * @constructor */ - - const serviceSettings = mapServiceSettings; - const toastService = getToasts(); - return class BaseMapsVisualization { constructor(element, vis) { this.vis = vis; @@ -95,9 +92,9 @@ export function BaseMapsVisualizationProvider(getKibanaMap, mapServiceSettings) const centerFromUIState = uiState.get('mapCenter'); options.zoom = !isNaN(zoomFromUiState) ? zoomFromUiState : this.vis.params.mapZoom; options.center = centerFromUIState ? centerFromUIState : this.vis.params.mapCenter; - const services = { toastService }; - this._kibanaMap = getKibanaMap(this._container, options, services); + const modules = await lazyLoadMapsLegacyModules(); + this._kibanaMap = new modules.KibanaMap(this._container, options); this._kibanaMap.setMinZoom(WMS_MINZOOM); //use a default this._kibanaMap.setMaxZoom(WMS_MAXZOOM); //use a default @@ -138,6 +135,7 @@ export function BaseMapsVisualizationProvider(getKibanaMap, mapServiceSettings) const mapParams = this._getMapsParams(); if (!this._tmsConfigured()) { try { + const serviceSettings = await getServiceSettings(); const tmsServices = await serviceSettings.getTMSServices(); const userConfiguredTmsLayer = tmsServices[0]; const initBasemapLayer = userConfiguredTmsLayer @@ -147,7 +145,7 @@ export function BaseMapsVisualizationProvider(getKibanaMap, mapServiceSettings) this._setTmsLayer(initBasemapLayer); } } catch (e) { - toastService.addWarning(e.message); + getToasts().addWarning(e.message); return; } return; @@ -174,7 +172,7 @@ export function BaseMapsVisualizationProvider(getKibanaMap, mapServiceSettings) this._setTmsLayer(selectedTmsLayer); } } catch (tmsLoadingError) { - toastService.addWarning(tmsLoadingError.message); + getToasts().addWarning(tmsLoadingError.message); } } @@ -189,13 +187,14 @@ export function BaseMapsVisualizationProvider(getKibanaMap, mapServiceSettings) isDesaturated = true; } const isDarkMode = getUiSettings().get('theme:darkMode'); + const serviceSettings = await getServiceSettings(); const meta = await serviceSettings.getAttributesForTMSLayer( tmsLayer, isDesaturated, isDarkMode ); const showZoomMessage = serviceSettings.shouldShowZoomMessage(tmsLayer); - const options = _.cloneDeep(tmsLayer); + const options = { ...tmsLayer }; delete options.id; delete options.subdomains; this._kibanaMap.setBaseLayer({ @@ -228,12 +227,11 @@ export function BaseMapsVisualizationProvider(getKibanaMap, mapServiceSettings) } _getMapsParams() { - return _.assign( - {}, - this.vis.type.visConfig.defaults, - { type: this.vis.type.name }, - this._params - ); + return { + ...this.vis.type.visConfig.defaults, + type: this.vis.type.name, + ...this._params, + }; } _whenBaseLayerIsLoaded() { diff --git a/src/plugins/maps_legacy/public/map/decode_geo_hash.ts b/src/plugins/maps_legacy/public/map/decode_geo_hash.ts index 8c39ada03a46b..65184a8244777 100644 --- a/src/plugins/maps_legacy/public/map/decode_geo_hash.ts +++ b/src/plugins/maps_legacy/public/map/decode_geo_hash.ts @@ -17,8 +17,6 @@ * under the License. */ -import _ from 'lodash'; - interface DecodedGeoHash { latitude: number[]; longitude: number[]; @@ -101,33 +99,6 @@ interface GeoBoundingBox { bottom_right: GeoBoundingBoxCoordinate; } -export function scaleBounds(bounds: GeoBoundingBox): GeoBoundingBox { - const scale = 0.5; // scale bounds by 50% - - const topLeft = bounds.top_left; - const bottomRight = bounds.bottom_right; - let latDiff = _.round(Math.abs(topLeft.lat - bottomRight.lat), 5); - const lonDiff = _.round(Math.abs(bottomRight.lon - topLeft.lon), 5); - // map height can be zero when vis is first created - if (latDiff === 0) latDiff = lonDiff; - - const latDelta = latDiff * scale; - let topLeftLat = _.round(topLeft.lat, 5) + latDelta; - if (topLeftLat > 90) topLeftLat = 90; - let bottomRightLat = _.round(bottomRight.lat, 5) - latDelta; - if (bottomRightLat < -90) bottomRightLat = -90; - const lonDelta = lonDiff * scale; - let topLeftLon = _.round(topLeft.lon, 5) - lonDelta; - if (topLeftLon < -180) topLeftLon = -180; - let bottomRightLon = _.round(bottomRight.lon, 5) + lonDelta; - if (bottomRightLon > 180) bottomRightLon = 180; - - return { - top_left: { lat: topLeftLat, lon: topLeftLon }, - bottom_right: { lat: bottomRightLat, lon: bottomRightLon }, - }; -} - export function geoContains(collar?: GeoBoundingBox, bounds?: GeoBoundingBox) { if (!bounds || !collar) return false; // test if bounds top_left is outside collar diff --git a/src/plugins/maps_legacy/public/map/grid_dimensions.js b/src/plugins/maps_legacy/public/map/grid_dimensions.js index d146adf2ca67f..0f84e972104ba 100644 --- a/src/plugins/maps_legacy/public/map/grid_dimensions.js +++ b/src/plugins/maps_legacy/public/map/grid_dimensions.js @@ -17,8 +17,6 @@ * under the License. */ -import _ from 'lodash'; - // geohash precision mapping of geohash grid cell dimensions (width x height, in meters) at equator. // https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-bucket-geohashgrid-aggregation.html#_cell_dimensions_at_the_equator const gridAtEquator = { @@ -37,5 +35,5 @@ const gridAtEquator = { }; export function gridDimensions(precision) { - return _.get(gridAtEquator, precision); + return gridAtEquator[precision]; } diff --git a/src/plugins/maps_legacy/public/map/kibana_map.js b/src/plugins/maps_legacy/public/map/kibana_map.js index ad5d2c089b875..3948692e55676 100644 --- a/src/plugins/maps_legacy/public/map/kibana_map.js +++ b/src/plugins/maps_legacy/public/map/kibana_map.js @@ -20,7 +20,7 @@ import { EventEmitter } from 'events'; import { createZoomWarningMsg } from './map_messages'; import $ from 'jquery'; -import _ from 'lodash'; +import { get, isEqual, escape } from 'lodash'; import { zoomToPrecision } from './zoom_to_precision'; import { i18n } from '@kbn/i18n'; import { ORIGIN } from '../common/constants/origin'; @@ -380,7 +380,7 @@ export class KibanaMap extends EventEmitter { const distanceX = latLngC.distanceTo(latLngX); // calculate distance between c and x (latitude) const distanceY = latLngC.distanceTo(latLngY); // calculate distance between c and y (longitude) - return _.min([distanceX, distanceY]); + return Math.min(distanceX, distanceY); } _getLeafletBounds(resizeOnFail) { @@ -544,7 +544,7 @@ export class KibanaMap extends EventEmitter { } setBaseLayer(settings) { - if (_.isEqual(settings, this._baseLayerSettings)) { + if (isEqual(settings, this._baseLayerSettings)) { return; } @@ -567,7 +567,7 @@ export class KibanaMap extends EventEmitter { let baseLayer; if (settings.baseLayerType === 'wms') { //This is user-input that is rendered with the Leaflet attribution control. Needs to be sanitized. - this._baseLayerSettings.options.attribution = _.escape(settings.options.attribution); + this._baseLayerSettings.options.attribution = escape(settings.options.attribution); baseLayer = this._getWMSBaseLayer(settings.options); } else if (settings.baseLayerType === 'tms') { baseLayer = this._getTMSBaseLayer(settings.options); @@ -661,7 +661,7 @@ export class KibanaMap extends EventEmitter { _updateDesaturation() { const tiles = $('img.leaflet-tile-loaded'); // Don't apply client-side styling to EMS basemaps - if (_.get(this._baseLayerSettings, 'options.origin') === ORIGIN.EMS) { + if (get(this._baseLayerSettings, 'options.origin') === ORIGIN.EMS) { tiles.addClass('filters-off'); } else { if (this._baseLayerIsDesaturated) { diff --git a/src/plugins/maps_legacy/public/map/service_settings.d.ts b/src/plugins/maps_legacy/public/map/service_settings_types.ts similarity index 100% rename from src/plugins/maps_legacy/public/map/service_settings.d.ts rename to src/plugins/maps_legacy/public/map/service_settings_types.ts diff --git a/src/plugins/maps_legacy/public/plugin.ts b/src/plugins/maps_legacy/public/plugin.ts index 8c9f1e9cef194..17cee226cb70c 100644 --- a/src/plugins/maps_legacy/public/plugin.ts +++ b/src/plugins/maps_legacy/public/plugin.ts @@ -22,15 +22,12 @@ import { CoreSetup, CoreStart, Plugin, PluginInitializerContext } from 'kibana/p // @ts-ignore import { setToasts, setUiSettings, setKibanaVersion, setMapsLegacyConfig } from './kibana_services'; // @ts-ignore -import { ServiceSettings } from './map/service_settings'; -// @ts-ignore import { getPrecision, getZoomPrecision } from './map/precision'; -// @ts-ignore -import { KibanaMap } from './map/kibana_map'; import { MapsLegacyPluginSetup, MapsLegacyPluginStart } from './index'; import { MapsLegacyConfig } from '../config'; // @ts-ignore import { BaseMapsVisualizationProvider } from './map/base_maps_visualization'; +import { getServiceSettings } from './get_service_settings'; /** * These are the interfaces with your public contracts. You should export these @@ -67,17 +64,13 @@ export class MapsLegacyPlugin implements Plugin new KibanaMap(...args); - const getBaseMapsVis = () => - new BaseMapsVisualizationProvider(getKibanaMapFactoryProvider, serviceSettings); + const getBaseMapsVis = () => new BaseMapsVisualizationProvider(); return { - serviceSettings, + getServiceSettings, getZoomPrecision, getPrecision, config, - getKibanaMapFactoryProvider, getBaseMapsVis, }; } diff --git a/src/plugins/navigation/public/top_nav_menu/__snapshots__/top_nav_menu_item.test.tsx.snap b/src/plugins/navigation/public/top_nav_menu/__snapshots__/top_nav_menu_item.test.tsx.snap index 570699aa0c0e2..155377e5ea335 100644 --- a/src/plugins/navigation/public/top_nav_menu/__snapshots__/top_nav_menu_item.test.tsx.snap +++ b/src/plugins/navigation/public/top_nav_menu/__snapshots__/top_nav_menu_item.test.tsx.snap @@ -2,7 +2,6 @@ exports[`TopNavMenu Should render emphasized item which should be clickable 1`] = ` * > * { - // TEMP fix to adjust spacing between EuiHeaderList__list items - margin: 0 $euiSizeXS; +.kbnTopNavMenu { + margin-right: $euiSizeXS; } diff --git a/src/plugins/navigation/public/top_nav_menu/top_nav_menu.test.tsx b/src/plugins/navigation/public/top_nav_menu/top_nav_menu.test.tsx index 212bc19208ca8..147feee3cd472 100644 --- a/src/plugins/navigation/public/top_nav_menu/top_nav_menu.test.tsx +++ b/src/plugins/navigation/public/top_nav_menu/top_nav_menu.test.tsx @@ -164,10 +164,6 @@ describe('TopNavMenu', () => { // menu is rendered outside of the component expect(component.find(TOP_NAV_ITEM_SELECTOR).length).toBe(0); - - const buttons = portalTarget.querySelectorAll('button'); - expect(buttons.length).toBe(menuItems.length + 1); // should be n+1 buttons in mobile for popover button - expect(buttons[buttons.length - 1].getAttribute('aria-label')).toBe('Open navigation menu'); // last button should be mobile button }); }); }); diff --git a/src/plugins/navigation/public/top_nav_menu/top_nav_menu.tsx b/src/plugins/navigation/public/top_nav_menu/top_nav_menu.tsx index a27addeb14393..1739b7d915adb 100644 --- a/src/plugins/navigation/public/top_nav_menu/top_nav_menu.tsx +++ b/src/plugins/navigation/public/top_nav_menu/top_nav_menu.tsx @@ -88,7 +88,7 @@ export function TopNavMenu(props: TopNavMenuProps): ReactElement | null { function renderMenu(className: string): ReactElement | null { if (!config || config.length === 0) return null; return ( - + {renderItems()} ); diff --git a/src/plugins/navigation/public/top_nav_menu/top_nav_menu_item.tsx b/src/plugins/navigation/public/top_nav_menu/top_nav_menu_item.tsx index 96a205b737273..5c463902f77f5 100644 --- a/src/plugins/navigation/public/top_nav_menu/top_nav_menu_item.tsx +++ b/src/plugins/navigation/public/top_nav_menu/top_nav_menu_item.tsx @@ -48,11 +48,11 @@ export function TopNavMenuItem(props: TopNavMenuData) { }; const btn = props.emphasize ? ( - + {upperFirst(props.label || props.id!)} ) : ( - + {upperFirst(props.label || props.id!)} ); diff --git a/src/plugins/newsfeed/common/constants.ts b/src/plugins/newsfeed/common/constants.ts index 6bc95873a342d..7716ad24aa848 100644 --- a/src/plugins/newsfeed/common/constants.ts +++ b/src/plugins/newsfeed/common/constants.ts @@ -18,6 +18,8 @@ */ export const NEWSFEED_FALLBACK_LANGUAGE = 'en'; +export const NEWSFEED_FALLBACK_FETCH_INTERVAL = 86400000; // 1 day +export const NEWSFEED_FALLBACK_MAIN_INTERVAL = 120000; // 2 minutes export const NEWSFEED_LAST_FETCH_STORAGE_KEY = 'newsfeed.lastfetchtime'; export const NEWSFEED_HASH_SET_STORAGE_KEY = 'newsfeed.hashes'; diff --git a/src/plugins/newsfeed/public/components/flyout_list.tsx b/src/plugins/newsfeed/public/components/flyout_list.tsx index 6e9444c950107..d4cdf72fee613 100644 --- a/src/plugins/newsfeed/public/components/flyout_list.tsx +++ b/src/plugins/newsfeed/public/components/flyout_list.tsx @@ -30,6 +30,7 @@ import { EuiText, EuiBadge, EuiHeaderAlert, + EuiPortal, } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; import { NewsfeedContext } from './newsfeed_header_nav_button'; @@ -42,70 +43,75 @@ export const NewsfeedFlyout = () => { const closeFlyout = useCallback(() => setFlyoutVisible(false), [setFlyoutVisible]); return ( - - - -

- -

-
-
- - {!newsFetchResult ? ( - - ) : newsFetchResult.feedItems.length > 0 ? ( - newsFetchResult.feedItems.map((item: NewsfeedItem) => { - return ( - - {item.linkText} - - } - date={item.publishOn.format('DD MMMM YYYY')} - badge={item.badge ? {item.badge} : undefined} + + + + +

+ - ); - }) - ) : ( - - )} - - - - - - - - - - {newsFetchResult ? ( - -

- -

-
- ) : null} -
-
-
- +

+
+
+ + {!newsFetchResult ? ( + + ) : newsFetchResult.feedItems.length > 0 ? ( + newsFetchResult.feedItems.map((item: NewsfeedItem) => { + return ( + + {item.linkText} + + } + date={item.publishOn.format('DD MMMM YYYY')} + badge={item.badge ? {item.badge} : undefined} + /> + ); + }) + ) : ( + + )} + + + + + + + + + + {newsFetchResult ? ( + +

+ +

+
+ ) : null} +
+
+
+
+
); }; diff --git a/src/plugins/newsfeed/public/components/newsfeed_header_nav_button.tsx b/src/plugins/newsfeed/public/components/newsfeed_header_nav_button.tsx index 628cfde18b0d5..7924544640086 100644 --- a/src/plugins/newsfeed/public/components/newsfeed_header_nav_button.tsx +++ b/src/plugins/newsfeed/public/components/newsfeed_header_nav_button.tsx @@ -19,7 +19,8 @@ import React, { useState, Fragment, useEffect } from 'react'; import * as Rx from 'rxjs'; -import { EuiHeaderSectionItemButton, EuiIcon, EuiNotificationBadge } from '@elastic/eui'; +import { EuiHeaderSectionItemButton, EuiIcon } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; import { NewsfeedFlyout } from './flyout_list'; import { FetchResult } from '../types'; @@ -65,15 +66,19 @@ export const NewsfeedNavButton = ({ apiFetchResult }: Props) => { aria-controls="keyPadMenu" aria-expanded={flyoutVisible} aria-haspopup="true" - aria-label="Newsfeed menu" + aria-label={ + showBadge + ? i18n.translate('newsfeed.headerButton.unreadAriaLabel', { + defaultMessage: 'Newsfeed menu - unread items available', + }) + : i18n.translate('newsfeed.headerButton.readAriaLabel', { + defaultMessage: 'Newsfeed menu - all items read', + }) + } + notification={showBadge ? true : null} onClick={showFlyout} > - {showBadge ? ( - - ▪ - - ) : null} {flyoutVisible ? : null} diff --git a/src/plugins/newsfeed/public/index.ts b/src/plugins/newsfeed/public/index.ts index b70606b09a34f..04ee6729c7b5e 100644 --- a/src/plugins/newsfeed/public/index.ts +++ b/src/plugins/newsfeed/public/index.ts @@ -18,9 +18,21 @@ */ import { PluginInitializerContext } from 'src/core/public'; -import { Setup, Start, NewsfeedPublicPlugin } from './plugin'; +import { + NewsfeedPublicPluginSetup, + NewsfeedPublicPluginStart, + NewsfeedPublicPlugin, +} from './plugin'; +import { FetchResult, NewsfeedItem } from './types'; +import { NewsfeedApiEndpoint } from './lib/api'; -export { Setup, Start }; +export { + NewsfeedPublicPluginSetup, + NewsfeedPublicPluginStart, + FetchResult, + NewsfeedItem, + NewsfeedApiEndpoint, +}; export function plugin(initializerContext: PluginInitializerContext) { return new NewsfeedPublicPlugin(initializerContext); diff --git a/src/plugins/newsfeed/public/lib/api.test.ts b/src/plugins/newsfeed/public/lib/api.test.ts index 21331b9d82575..89918acce6c71 100644 --- a/src/plugins/newsfeed/public/lib/api.test.ts +++ b/src/plugins/newsfeed/public/lib/api.test.ts @@ -47,6 +47,10 @@ Object.defineProperty(window, 'sessionStorage', { writable: true, }); +jest.mock('uuid', () => ({ + v4: () => 'NEW_UUID', +})); + describe('NewsfeedApiDriver', () => { const kibanaVersion = '99.999.9-test_version'; // It'll remove the `-test_version` bit const userLanguage = 'en'; @@ -65,14 +69,18 @@ describe('NewsfeedApiDriver', () => { it('returns true if last fetch time precedes page load time', () => { sessionStoragetGet.throws('Wrong key passed!'); - sessionStoragetGet.withArgs(NEWSFEED_LAST_FETCH_STORAGE_KEY).returns(322642800000); // 1980-03-23 + sessionStoragetGet + .withArgs(`${NEWSFEED_LAST_FETCH_STORAGE_KEY}.NEW_UUID`) + .returns(322642800000); // 1980-03-23 const driver = getDriver(); expect(driver.shouldFetch()).toBe(true); }); it('returns false if last fetch time is recent enough', () => { sessionStoragetGet.throws('Wrong key passed!'); - sessionStoragetGet.withArgs(NEWSFEED_LAST_FETCH_STORAGE_KEY).returns(3005017200000); // 2065-03-23 + sessionStoragetGet + .withArgs(`${NEWSFEED_LAST_FETCH_STORAGE_KEY}.NEW_UUID`) + .returns(3005017200000); // 2065-03-23 const driver = getDriver(); expect(driver.shouldFetch()).toBe(false); }); @@ -105,7 +113,7 @@ describe('NewsfeedApiDriver', () => { it('concatenates the previous hashes with the current', () => { localStorageGet.throws('Wrong key passed!'); - localStorageGet.withArgs(NEWSFEED_HASH_SET_STORAGE_KEY).returns('happyness'); + localStorageGet.withArgs(`${NEWSFEED_HASH_SET_STORAGE_KEY}.NEW_UUID`).returns('happyness'); const driver = getDriver(); const items: NewsfeedItem[] = [ { @@ -554,7 +562,7 @@ describe('getApi', () => { it('hasNew is false when service returns hashes that are all stored', (done) => { localStorageGet.throws('Wrong key passed!'); - localStorageGet.withArgs(NEWSFEED_HASH_SET_STORAGE_KEY).returns('happyness'); + localStorageGet.withArgs(`${NEWSFEED_HASH_SET_STORAGE_KEY}.NEW_UUID`).returns('happyness'); const mockApiItems: ApiItem[] = [ { title: { en: 'hasNew test' }, diff --git a/src/plugins/newsfeed/public/lib/api.ts b/src/plugins/newsfeed/public/lib/api.ts index 7253c0f3e294c..0e1ae24897176 100644 --- a/src/plugins/newsfeed/public/lib/api.ts +++ b/src/plugins/newsfeed/public/lib/api.ts @@ -19,10 +19,12 @@ import * as Rx from 'rxjs'; import moment from 'moment'; +import uuid from 'uuid'; import { i18n } from '@kbn/i18n'; import { catchError, filter, mergeMap, tap } from 'rxjs/operators'; import { HttpSetup } from 'src/core/public'; import { + NEWSFEED_DEFAULT_SERVICE_BASE_URL, NEWSFEED_FALLBACK_LANGUAGE, NEWSFEED_LAST_FETCH_STORAGE_KEY, NEWSFEED_HASH_SET_STORAGE_KEY, @@ -31,9 +33,19 @@ import { ApiItem, NewsfeedItem, FetchResult, NewsfeedPluginBrowserConfig } from type ApiConfig = NewsfeedPluginBrowserConfig['service']; +export enum NewsfeedApiEndpoint { + KIBANA = 'kibana', + KIBANA_ANALYTICS = 'kibana-analytics', + SECURITY_SOLUTION = 'security-solution', + OBSERVABILITY = 'observability', +} + export class NewsfeedApiDriver { + private readonly id = uuid.v4(); private readonly kibanaVersion: string; private readonly loadedTime = moment().utc(); // the date is compared to time in UTC format coming from the service + private readonly lastFetchStorageKey: string; + private readonly hashSetStorageKey: string; constructor( kibanaVersion: string, @@ -42,10 +54,12 @@ export class NewsfeedApiDriver { ) { // The API only accepts versions in the format `X.Y.Z`, so we need to drop the `-SNAPSHOT` or any other label after it this.kibanaVersion = kibanaVersion.replace(/^(\d+\.\d+\.\d+).*/, '$1'); + this.lastFetchStorageKey = `${NEWSFEED_LAST_FETCH_STORAGE_KEY}.${this.id}`; + this.hashSetStorageKey = `${NEWSFEED_HASH_SET_STORAGE_KEY}.${this.id}`; } shouldFetch(): boolean { - const lastFetchUtc: string | null = sessionStorage.getItem(NEWSFEED_LAST_FETCH_STORAGE_KEY); + const lastFetchUtc: string | null = sessionStorage.getItem(this.lastFetchStorageKey); if (lastFetchUtc == null) { return true; } @@ -63,12 +77,12 @@ export class NewsfeedApiDriver { } updateLastFetch() { - sessionStorage.setItem(NEWSFEED_LAST_FETCH_STORAGE_KEY, Date.now().toString()); + sessionStorage.setItem(this.lastFetchStorageKey, Date.now().toString()); } updateHashes(items: NewsfeedItem[]): { previous: string[]; current: string[] } { // replace localStorage hashes with new hashes - const stored: string | null = localStorage.getItem(NEWSFEED_HASH_SET_STORAGE_KEY); + const stored: string | null = localStorage.getItem(this.hashSetStorageKey); let old: string[] = []; if (stored != null) { old = stored.split(','); @@ -76,21 +90,23 @@ export class NewsfeedApiDriver { const newHashes = items.map((i) => i.hash); const updatedHashes = [...new Set(old.concat(newHashes))]; - localStorage.setItem(NEWSFEED_HASH_SET_STORAGE_KEY, updatedHashes.join(',')); + localStorage.setItem(this.hashSetStorageKey, updatedHashes.join(',')); return { previous: old, current: updatedHashes }; } fetchNewsfeedItems(http: HttpSetup, config: ApiConfig): Rx.Observable { const urlPath = config.pathTemplate.replace('{VERSION}', this.kibanaVersion); - const fullUrl = config.urlRoot + urlPath; + const fullUrl = (config.urlRoot || NEWSFEED_DEFAULT_SERVICE_BASE_URL) + urlPath; return Rx.from( http .fetch(fullUrl, { method: 'GET', }) - .then(({ items }) => this.modelItems(items)) + .then(({ items }: { items: ApiItem[] }) => { + return this.modelItems(items); + }) ); } @@ -137,7 +153,7 @@ export class NewsfeedApiDriver { const tempItem: NewsfeedItem = { title: title[chosenLanguage], description: description[chosenLanguage], - linkText: linkText[chosenLanguage], + linkText: linkText != null ? linkText[chosenLanguage] : null, linkUrl: linkUrl[chosenLanguage], badge: badge != null ? badge![chosenLanguage] : null, publishOn: moment(publishOnUtc), @@ -176,9 +192,10 @@ export function getApi( ): Rx.Observable { const userLanguage = i18n.getLocale(); const fetchInterval = config.fetchInterval.asMilliseconds(); + const mainInterval = config.mainInterval.asMilliseconds(); const driver = new NewsfeedApiDriver(kibanaVersion, userLanguage, fetchInterval); - return Rx.timer(0, config.mainInterval.asMilliseconds()).pipe( + return Rx.timer(0, mainInterval).pipe( filter(() => driver.shouldFetch()), mergeMap(() => driver.fetchNewsfeedItems(http, config.service).pipe( diff --git a/src/plugins/newsfeed/public/plugin.tsx b/src/plugins/newsfeed/public/plugin.tsx index 1a1915ccbed3e..ae74f43531b05 100644 --- a/src/plugins/newsfeed/public/plugin.tsx +++ b/src/plugins/newsfeed/public/plugin.tsx @@ -18,20 +18,21 @@ */ import * as Rx from 'rxjs'; -import { catchError, takeUntil } from 'rxjs/operators'; +import { catchError, takeUntil, share } from 'rxjs/operators'; import ReactDOM from 'react-dom'; import React from 'react'; import moment from 'moment'; import { I18nProvider } from '@kbn/i18n/react'; import { PluginInitializerContext, CoreSetup, CoreStart, Plugin } from 'src/core/public'; -import { NewsfeedPluginBrowserConfig } from './types'; +import { NewsfeedPluginBrowserConfig, FetchResult } from './types'; import { NewsfeedNavButton, NewsfeedApiFetchResult } from './components/newsfeed_header_nav_button'; -import { getApi } from './lib/api'; +import { getApi, NewsfeedApiEndpoint } from './lib/api'; -export type Setup = object; -export type Start = object; +export type NewsfeedPublicPluginSetup = ReturnType; +export type NewsfeedPublicPluginStart = ReturnType; -export class NewsfeedPublicPlugin implements Plugin { +export class NewsfeedPublicPlugin + implements Plugin { private readonly kibanaVersion: string; private readonly config: NewsfeedPluginBrowserConfig; private readonly stop$ = new Rx.ReplaySubject(1); @@ -47,27 +48,37 @@ export class NewsfeedPublicPlugin implements Plugin { }); } - public setup(core: CoreSetup): Setup { + public setup(core: CoreSetup) { return {}; } - public start(core: CoreStart): Start { - const api$ = this.fetchNewsfeed(core); + public start(core: CoreStart) { + const api$ = this.fetchNewsfeed(core, this.config).pipe(share()); core.chrome.navControls.registerRight({ order: 1000, mount: (target) => this.mount(api$, target), }); - return {}; + return { + createNewsFeed$: (endpoint: NewsfeedApiEndpoint) => { + const config = Object.assign({}, this.config, { + service: { pathTemplate: `/${endpoint}/v{VERSION}.json` }, + }); + return this.fetchNewsfeed(core, config); + }, + }; } public stop() { this.stop$.next(); } - private fetchNewsfeed(core: CoreStart) { + private fetchNewsfeed( + core: CoreStart, + config: NewsfeedPluginBrowserConfig + ): Rx.Observable { const { http } = core; - return getApi(http, this.config, this.kibanaVersion).pipe( + return getApi(http, config, this.kibanaVersion).pipe( takeUntil(this.stop$), // stop the interval when stop method is called catchError(() => Rx.of(null)) // do not throw error ); diff --git a/src/plugins/newsfeed/public/types.ts b/src/plugins/newsfeed/public/types.ts index a9dab6791d7aa..4c64ad02d3fdd 100644 --- a/src/plugins/newsfeed/public/types.ts +++ b/src/plugins/newsfeed/public/types.ts @@ -35,7 +35,7 @@ export interface ApiItem { publish_on: Date; title: { [lang: string]: string }; description: { [lang: string]: string }; - link_text: { [lang: string]: string }; + link_text?: { [lang: string]: string }; link_url: { [lang: string]: string }; badge?: { [lang: string]: string } | null; languages?: string[] | null; @@ -45,7 +45,7 @@ export interface ApiItem { export interface NewsfeedItem { title: string; description: string; - linkText: string; + linkText: string | null; linkUrl: string; badge: string | null; publishOn: Moment; diff --git a/src/plugins/region_map/kibana.json b/src/plugins/region_map/kibana.json index 6e1980c327dc0..e679baf6d6f06 100644 --- a/src/plugins/region_map/kibana.json +++ b/src/plugins/region_map/kibana.json @@ -10,11 +10,12 @@ "expressions", "mapsLegacy", "kibanaLegacy", - "data" + "data", + "share" ], "requiredBundles": [ "kibanaUtils", - "kibanaReact", - "charts" + "charts", + "visDefaultEditor" ] } diff --git a/src/plugins/region_map/public/choropleth_layer.js b/src/plugins/region_map/public/choropleth_layer.js index 30fa8b544cdec..14a91e189e0d5 100644 --- a/src/plugins/region_map/public/choropleth_layer.js +++ b/src/plugins/region_map/public/choropleth_layer.js @@ -33,7 +33,7 @@ const EMPTY_STYLE = { fillOpacity: 0, }; -export default class ChoroplethLayer extends KibanaMapLayer { +export class ChoroplethLayer extends KibanaMapLayer { static _doInnerJoin(sortedMetrics, sortedGeojsonFeatures, joinField) { let j = 0; for (let i = 0; i < sortedGeojsonFeatures.length; i++) { @@ -71,7 +71,16 @@ export default class ChoroplethLayer extends KibanaMapLayer { } } - constructor(name, attribution, format, showAllShapes, meta, layerConfig, serviceSettings) { + constructor( + name, + attribution, + format, + showAllShapes, + meta, + layerConfig, + serviceSettings, + leaflet + ) { super(); this._serviceSettings = serviceSettings; this._metrics = null; @@ -84,9 +93,10 @@ export default class ChoroplethLayer extends KibanaMapLayer { this._showAllShapes = showAllShapes; this._layerName = name; this._layerConfig = layerConfig; + this._leaflet = leaflet; // eslint-disable-next-line no-undef - this._leafletLayer = L.geoJson(null, { + this._leafletLayer = this._leaflet.geoJson(null, { onEachFeature: (feature, layer) => { layer.on('click', () => { this.emit('select', feature.properties[this._joinField]); @@ -97,7 +107,7 @@ export default class ChoroplethLayer extends KibanaMapLayer { const tooltipContents = this._tooltipFormatter(feature); if (!location) { // eslint-disable-next-line no-undef - const leafletGeojson = L.geoJson(feature); + const leafletGeojson = this._leaflet.geoJson(feature); location = leafletGeojson.getBounds().getCenter(); } this.emit('showTooltip', { @@ -425,7 +435,7 @@ CORS configuration of the server permits requests from the Kibana application on const { min, max } = getMinMax(this._metrics); // eslint-disable-next-line no-undef - const boundsOfAllFeatures = new L.LatLngBounds(); + const boundsOfAllFeatures = new this._leaflet.LatLngBounds(); return { leafletStyleFunction: (geojsonFeature) => { const match = geojsonFeature.__kbnJoinedMetric; @@ -433,7 +443,7 @@ CORS configuration of the server permits requests from the Kibana application on return emptyStyle(); } // eslint-disable-next-line no-undef - const boundsOfFeature = L.geoJson(geojsonFeature).getBounds(); + const boundsOfFeature = this._leaflet.geoJson(geojsonFeature).getBounds(); boundsOfAllFeatures.extend(boundsOfFeature); return { diff --git a/src/plugins/region_map/public/components/region_map_options.tsx b/src/plugins/region_map/public/components/region_map_options.tsx index be3d7fe86ab3f..4d564d7347a1e 100644 --- a/src/plugins/region_map/public/components/region_map_options.tsx +++ b/src/plugins/region_map/public/components/region_map_options.tsx @@ -37,11 +37,11 @@ const mapFieldForOption = ({ description, name }: FileLayerField) => ({ }); export type RegionMapOptionsProps = { - serviceSettings: IServiceSettings; + getServiceSettings: () => Promise; } & VisOptionsProps; function RegionMapOptions(props: RegionMapOptionsProps) { - const { serviceSettings, stateParams, vis, setValue } = props; + const { getServiceSettings, stateParams, vis, setValue } = props; const { vectorLayers } = vis.type.editorConfig.collections; const vectorLayerOptions = useMemo(() => vectorLayers.map(mapLayerForOption), [vectorLayers]); const fieldOptions = useMemo( @@ -54,10 +54,11 @@ function RegionMapOptions(props: RegionMapOptionsProps) { const setEmsHotLink = useCallback( async (layer: VectorLayer) => { + const serviceSettings = await getServiceSettings(); const emsHotLink = await serviceSettings.getEMSHotLink(layer); setValue('emsHotLink', emsHotLink); }, - [setValue, serviceSettings] + [setValue, getServiceSettings] ); const setLayer = useCallback( diff --git a/src/plugins/region_map/public/get_deprecation_message.tsx b/src/plugins/region_map/public/get_deprecation_message.tsx new file mode 100644 index 0000000000000..ea5cdf42c3111 --- /dev/null +++ b/src/plugins/region_map/public/get_deprecation_message.tsx @@ -0,0 +1,93 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { i18n } from '@kbn/i18n'; +import React from 'react'; +import { UrlGeneratorContract } from 'src/plugins/share/public'; +import { getCoreService, getQueryService, getShareService } from './kibana_services'; +import { Vis } from '../../visualizations/public'; +import { LegacyMapDeprecationMessage } from '../../maps_legacy/public'; + +function getEmsLayerId(id: string | number, layerId: string) { + if (typeof id === 'string') { + return id; + } + + // Region maps from 6.x will have numerical EMS id refering to S3 bucket id. + // In this case, use layerId with contains the EMS layer name. + const split = layerId.split('.'); + return split.length === 2 ? split[1] : undefined; +} + +export function getDeprecationMessage(vis: Vis) { + let mapsRegionMapUrlGenerator: + | UrlGeneratorContract<'MAPS_APP_REGION_MAP_URL_GENERATOR'> + | undefined; + try { + mapsRegionMapUrlGenerator = getShareService().urlGenerators.getUrlGenerator( + 'MAPS_APP_REGION_MAP_URL_GENERATOR' + ); + } catch (error) { + // ignore error thrown when url generator is not available + } + + const title = i18n.translate('regionMap.mapVis.regionMapTitle', { defaultMessage: 'Region Map' }); + + async function onClick(e: React.MouseEvent) { + e.preventDefault(); + + const query = getQueryService(); + const createUrlParams: { [key: string]: any } = { + label: vis.title ? vis.title : title, + emsLayerId: vis.params.selectedLayer.isEMS + ? getEmsLayerId(vis.params.selectedLayer.id, vis.params.selectedLayer.layerId) + : undefined, + leftFieldName: vis.params.selectedLayer.isEMS ? vis.params.selectedJoinField.name : undefined, + colorSchema: vis.params.colorSchema, + indexPatternId: vis.data.indexPattern?.id, + indexPatternTitle: vis.data.indexPattern?.title, + metricAgg: 'count', + filters: query.filterManager.getFilters(), + query: query.queryString.getQuery(), + timeRange: query.timefilter.timefilter.getTime(), + }; + + const bucketAggs = vis.data?.aggs?.byType('buckets'); + if (bucketAggs?.length && bucketAggs[0].type.dslName === 'terms') { + createUrlParams.termsFieldName = bucketAggs[0].getField()?.name; + } + + const metricAggs = vis.data?.aggs?.byType('metrics'); + if (metricAggs?.length) { + createUrlParams.metricAgg = metricAggs[0].type.dslName; + createUrlParams.metricFieldName = metricAggs[0].getField()?.name; + } + + const url = await mapsRegionMapUrlGenerator!.createUrl(createUrlParams); + getCoreService().application.navigateToUrl(url); + } + + return ( + + ); +} diff --git a/src/plugins/region_map/public/kibana_services.ts b/src/plugins/region_map/public/kibana_services.ts index 8367325c7415b..7edbf2da36fc7 100644 --- a/src/plugins/region_map/public/kibana_services.ts +++ b/src/plugins/region_map/public/kibana_services.ts @@ -17,10 +17,14 @@ * under the License. */ +import { CoreStart } from 'kibana/public'; import { NotificationsStart } from 'kibana/public'; import { createGetterSetter } from '../../kibana_utils/public'; import { DataPublicPluginStart } from '../../data/public'; import { KibanaLegacyStart } from '../../kibana_legacy/public'; +import { SharePluginStart } from '../../share/public'; + +export const [getCoreService, setCoreService] = createGetterSetter('Core'); export const [getFormatService, setFormatService] = createGetterSetter< DataPublicPluginStart['fieldFormats'] @@ -30,6 +34,12 @@ export const [getNotifications, setNotifications] = createGetterSetter('Query'); + +export const [getShareService, setShareService] = createGetterSetter('Share'); + export const [getKibanaLegacy, setKibanaLegacy] = createGetterSetter( 'KibanaLegacy' ); diff --git a/src/plugins/region_map/public/plugin.ts b/src/plugins/region_map/public/plugin.ts index ec9ee94310578..e9978803ad5e2 100644 --- a/src/plugins/region_map/public/plugin.ts +++ b/src/plugins/region_map/public/plugin.ts @@ -31,17 +31,25 @@ import { createRegionMapFn } from './region_map_fn'; // @ts-ignore import { createRegionMapTypeDefinition } from './region_map_type'; import { IServiceSettings, MapsLegacyPluginSetup } from '../../maps_legacy/public'; -import { setFormatService, setNotifications, setKibanaLegacy } from './kibana_services'; +import { + setCoreService, + setFormatService, + setNotifications, + setKibanaLegacy, + setQueryService, + setShareService, +} from './kibana_services'; import { DataPublicPluginStart } from '../../data/public'; import { RegionMapsConfigType } from './index'; import { MapsLegacyConfig } from '../../maps_legacy/config'; import { KibanaLegacyStart } from '../../kibana_legacy/public'; +import { SharePluginStart } from '../../share/public'; /** @private */ interface RegionMapVisualizationDependencies { uiSettings: IUiSettingsClient; regionmapsConfig: RegionMapsConfig; - serviceSettings: IServiceSettings; + getServiceSettings: () => Promise; BaseMapsVisualization: any; } @@ -57,6 +65,7 @@ export interface RegionMapPluginStartDependencies { data: DataPublicPluginStart; notifications: NotificationsStart; kibanaLegacy: KibanaLegacyStart; + share: SharePluginStart; } /** @internal */ @@ -93,7 +102,7 @@ export class RegionMapPlugin implements Plugin = { uiSettings: core.uiSettings, regionmapsConfig: config as RegionMapsConfig, - serviceSettings: mapsLegacy.serviceSettings, + getServiceSettings: mapsLegacy.getServiceSettings, BaseMapsVisualization: mapsLegacy.getBaseMapsVis(), }; @@ -108,10 +117,13 @@ export class RegionMapPlugin implements Plugin , + optionsTemplate: (props) => ( + + ), collections: { colorSchemas: truncatedColorSchemas, vectorLayers: [], @@ -97,6 +101,7 @@ provided base maps, or add your own. Darker colors represent higher values.', ]), }, setup: async (vis) => { + const serviceSettings = await getServiceSettings(); const tmsLayers = await serviceSettings.getTMSServices(); vis.type.editorConfig.collections.tmsLayers = tmsLayers; if (!vis.params.wms.selectedTmsLayer && tmsLayers.length) { diff --git a/src/plugins/region_map/public/region_map_visualization.js b/src/plugins/region_map/public/region_map_visualization.js index 43959c367558f..9b20a35630c86 100644 --- a/src/plugins/region_map/public/region_map_visualization.js +++ b/src/plugins/region_map/public/region_map_visualization.js @@ -18,18 +18,16 @@ */ import { i18n } from '@kbn/i18n'; -import ChoroplethLayer from './choropleth_layer'; import { getFormatService, getNotifications, getKibanaLegacy } from './kibana_services'; import { truncatedColorMaps } from '../../charts/public'; import { tooltipFormatter } from './tooltip_formatter'; -import { mapTooltipProvider, ORIGIN } from '../../maps_legacy/public'; -import _ from 'lodash'; +import { mapTooltipProvider, ORIGIN, lazyLoadMapsLegacyModules } from '../../maps_legacy/public'; export function createRegionMapVisualization({ regionmapsConfig, - serviceSettings, uiSettings, BaseMapsVisualization, + getServiceSettings, }) { return class RegionMapsVisualization extends BaseMapsVisualization { constructor(container, vis) { @@ -71,7 +69,7 @@ export function createRegionMapVisualization({ return; } - this._updateChoroplethLayerForNewMetrics( + await this._updateChoroplethLayerForNewMetrics( selectedLayer.name, selectedLayer.attribution, this._params.showAllShapes, @@ -98,10 +96,13 @@ export function createRegionMapVisualization({ // Do not use the selectedLayer from the visState. // These settings are stored in the URL and can be used to inject dirty display content. + const { escape } = await import('lodash'); + if ( fileLayerConfig.isEMS || //Hosted by EMS. Metadata needs to be resolved through EMS (fileLayerConfig.layerId && fileLayerConfig.layerId.startsWith(`${ORIGIN.EMS}.`)) //fallback for older saved objects ) { + const serviceSettings = await getServiceSettings(); return await serviceSettings.loadFileLayerConfig(fileLayerConfig); } @@ -113,7 +114,7 @@ export function createRegionMapVisualization({ if (configuredLayer) { return { ...configuredLayer, - attribution: _.escape(configuredLayer.attribution ? configuredLayer.attribution : ''), + attribution: escape(configuredLayer.attribution ? configuredLayer.attribution : ''), }; } @@ -133,7 +134,7 @@ export function createRegionMapVisualization({ return; } - this._updateChoroplethLayerForNewProperties( + await this._updateChoroplethLayerForNewProperties( selectedLayer.name, selectedLayer.attribution, this._params.showAllShapes @@ -151,24 +152,24 @@ export function createRegionMapVisualization({ ); } - _updateChoroplethLayerForNewMetrics(name, attribution, showAllData, newMetrics) { + async _updateChoroplethLayerForNewMetrics(name, attribution, showAllData, newMetrics) { if ( this._choroplethLayer && this._choroplethLayer.canReuseInstanceForNewMetrics(name, showAllData, newMetrics) ) { return; } - return this._recreateChoroplethLayer(name, attribution, showAllData); + await this._recreateChoroplethLayer(name, attribution, showAllData); } - _updateChoroplethLayerForNewProperties(name, attribution, showAllData) { + async _updateChoroplethLayerForNewProperties(name, attribution, showAllData) { if (this._choroplethLayer && this._choroplethLayer.canReuseInstance(name, showAllData)) { return; } - return this._recreateChoroplethLayer(name, attribution, showAllData); + await this._recreateChoroplethLayer(name, attribution, showAllData); } - _recreateChoroplethLayer(name, attribution, showAllData) { + async _recreateChoroplethLayer(name, attribution, showAllData) { this._kibanaMap.removeLayer(this._choroplethLayer); if (this._choroplethLayer) { @@ -179,9 +180,10 @@ export function createRegionMapVisualization({ showAllData, this._params.selectedLayer.meta, this._params.selectedLayer, - serviceSettings + await getServiceSettings() ); } else { + const { ChoroplethLayer } = await import('./choropleth_layer'); this._choroplethLayer = new ChoroplethLayer( name, attribution, @@ -189,7 +191,8 @@ export function createRegionMapVisualization({ showAllData, this._params.selectedLayer.meta, this._params.selectedLayer, - serviceSettings + await getServiceSettings(), + (await lazyLoadMapsLegacyModules()).L ); } diff --git a/src/plugins/saved_objects/public/save_modal/__snapshots__/saved_object_save_modal.test.tsx.snap b/src/plugins/saved_objects/public/save_modal/__snapshots__/saved_object_save_modal.test.tsx.snap index eff5ab4f1e2c7..c923c5c2aed90 100644 --- a/src/plugins/saved_objects/public/save_modal/__snapshots__/saved_object_save_modal.test.tsx.snap +++ b/src/plugins/saved_objects/public/save_modal/__snapshots__/saved_object_save_modal.test.tsx.snap @@ -25,6 +25,7 @@ exports[`SavedObjectSaveModal should render matching snapshot 1`] = ` + {!this.props.showDescription && this.props.description && ( - - {this.props.description} - + + {this.props.description} + )} + + + {this.renderCopyOnSave()} string | undefined; + originatingAppName?: string; + returnToOriginSwitchLabel?: string; documentInfo: SaveModalDocumentInfo; objectType: string; onClose: () => void; @@ -73,11 +75,13 @@ export function SavedObjectSaveModalOrigin(props: OriginSaveModalProps) { setReturnToOriginMode(event.target.checked); }} label={ - + props.returnToOriginSwitchLabel ?? ( + + ) } /> diff --git a/src/plugins/saved_objects/public/saved_object/saved_object.test.ts b/src/plugins/saved_objects/public/saved_object/saved_object.test.ts index 53abe55ef0ea7..849e11dc3dd9f 100644 --- a/src/plugins/saved_objects/public/saved_object/saved_object.test.ts +++ b/src/plugins/saved_objects/public/saved_object/saved_object.test.ts @@ -26,10 +26,9 @@ import { SavedObjectSaveOpts, } from '../types'; -// @ts-ignore -import StubIndexPattern from 'test_utils/stub_index_pattern'; import { coreMock } from '../../../../core/public/mocks'; import { dataPluginMock, createSearchSourceMock } from '../../../../plugins/data/public/mocks'; +import { getStubIndexPattern, StubIndexPattern } from '../../../../plugins/data/public/test_utils'; import { SavedObjectAttributes, SimpleSavedObject } from 'kibana/public'; import { IIndexPattern } from '../../../data/common/index_patterns'; @@ -294,14 +293,14 @@ describe('Saved Object', () => { type: 'dashboard', } as SimpleSavedObject); - const indexPattern = new StubIndexPattern( + const indexPattern = getStubIndexPattern( 'my-index', getConfig, null, [], coreMock.createSetup() ); - indexPattern.title = indexPattern.id; + indexPattern.title = indexPattern.id!; savedObject.searchSource!.setField('index', indexPattern); return savedObject.save(saveOptionsMock).then(() => { const args = (savedObjectsClientStub.create as jest.Mock).mock.calls[0]; @@ -335,7 +334,7 @@ describe('Saved Object', () => { type: 'dashboard', } as SimpleSavedObject); - const indexPattern = new StubIndexPattern( + const indexPattern = getStubIndexPattern( 'non-existant-index', getConfig, null, @@ -662,14 +661,14 @@ describe('Saved Object', () => { const savedObject = new SavedObjectClass(config); savedObject.hydrateIndexPattern = jest.fn().mockImplementation(() => { - const indexPattern = new StubIndexPattern( + const indexPattern = getStubIndexPattern( indexPatternId, getConfig, null, [], coreMock.createSetup() ); - indexPattern.title = indexPattern.id; + indexPattern.title = indexPattern.id!; savedObject.searchSource!.setField('index', indexPattern); return Bluebird.resolve(indexPattern); }); diff --git a/src/plugins/saved_objects_management/public/lib/resolve_saved_objects.ts b/src/plugins/saved_objects_management/public/lib/resolve_saved_objects.ts index 679ea5ffc23ee..eb95c213e680d 100644 --- a/src/plugins/saved_objects_management/public/lib/resolve_saved_objects.ts +++ b/src/plugins/saved_objects_management/public/lib/resolve_saved_objects.ts @@ -24,10 +24,11 @@ import { SavedObject, SavedObjectLoader } from '../../../saved_objects/public'; import { DataPublicPluginStart, IndexPatternsContract, - IIndexPattern, injectSearchSourceReferences, + IndexPatternSpec, } from '../../../data/public'; import { FailedImport } from './process_import_response'; +import { DuplicateIndexPatternError, IndexPattern } from '../../../data/public'; type SavedObjectsRawDoc = Record; @@ -70,11 +71,10 @@ function addJsonFieldToIndexPattern( async function importIndexPattern( doc: SavedObjectsRawDoc, indexPatterns: IndexPatternsContract, - overwriteAll: boolean, + overwriteAll: boolean = false, openConfirm: OverlayStart['openConfirm'] ) { // TODO: consolidate this is the code in create_index_pattern_wizard.js - const emptyPattern = await indexPatterns.make(); const { title, timeFieldName, @@ -84,50 +84,53 @@ async function importIndexPattern( type, typeMeta, } = doc._source; - const importedIndexPattern = { + const indexPatternSpec: IndexPatternSpec = { id: doc._id, title, timeFieldName, - } as IIndexPattern; + }; + let emptyPattern: IndexPattern; if (type) { - importedIndexPattern.type = type; + indexPatternSpec.type = type; } - addJsonFieldToIndexPattern(importedIndexPattern, fields, 'fields', title); - addJsonFieldToIndexPattern(importedIndexPattern, fieldFormatMap, 'fieldFormatMap', title); - addJsonFieldToIndexPattern(importedIndexPattern, sourceFilters, 'sourceFilters', title); - addJsonFieldToIndexPattern(importedIndexPattern, typeMeta, 'typeMeta', title); - Object.assign(emptyPattern, importedIndexPattern); - - let newId = await emptyPattern.create(overwriteAll); - if (!newId) { - // We can override and we want to prompt for confirmation - const isConfirmed = await openConfirm( - i18n.translate('savedObjectsManagement.indexPattern.confirmOverwriteLabel', { - values: { title }, - defaultMessage: "Are you sure you want to overwrite '{title}'?", - }), - { - title: i18n.translate('savedObjectsManagement.indexPattern.confirmOverwriteTitle', { - defaultMessage: 'Overwrite {type}?', - values: { type }, + addJsonFieldToIndexPattern(indexPatternSpec, fields, 'fields', title); + addJsonFieldToIndexPattern(indexPatternSpec, fieldFormatMap, 'fieldFormatMap', title); + addJsonFieldToIndexPattern(indexPatternSpec, sourceFilters, 'sourceFilters', title); + addJsonFieldToIndexPattern(indexPatternSpec, typeMeta, 'typeMeta', title); + try { + emptyPattern = await indexPatterns.createAndSave(indexPatternSpec, overwriteAll, true); + } catch (err) { + if (err instanceof DuplicateIndexPatternError) { + // We can override and we want to prompt for confirmation + const isConfirmed = await openConfirm( + i18n.translate('savedObjectsManagement.indexPattern.confirmOverwriteLabel', { + values: { title }, + defaultMessage: "Are you sure you want to overwrite '{title}'?", }), - confirmButtonText: i18n.translate( - 'savedObjectsManagement.indexPattern.confirmOverwriteButton', - { - defaultMessage: 'Overwrite', - } - ), - } - ); + { + title: i18n.translate('savedObjectsManagement.indexPattern.confirmOverwriteTitle', { + defaultMessage: 'Overwrite {type}?', + values: { type }, + }), + confirmButtonText: i18n.translate( + 'savedObjectsManagement.indexPattern.confirmOverwriteButton', + { + defaultMessage: 'Overwrite', + } + ), + } + ); - if (isConfirmed) { - newId = (await emptyPattern.create(true)) as string; - } else { - return; + if (isConfirmed) { + emptyPattern = await indexPatterns.createAndSave(indexPatternSpec, true, true); + } else { + return; + } } } - indexPatterns.clearCache(newId); - return newId; + + indexPatterns.clearCache(emptyPattern!.id); + return emptyPattern!.id; } async function importDocument(obj: SavedObject, doc: SavedObjectsRawDoc, overwriteAll: boolean) { diff --git a/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.test.tsx b/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.test.tsx index 1bc3dc8066520..0adf55ed6bebb 100644 --- a/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.test.tsx +++ b/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.test.tsx @@ -544,11 +544,13 @@ describe('SavedObjectsTable', () => { expect(mockSavedObjectsClient.bulkGet).toHaveBeenCalledWith(mockSelectedSavedObjects); expect(mockSavedObjectsClient.delete).toHaveBeenCalledWith( mockSavedObjects[0].type, - mockSavedObjects[0].id + mockSavedObjects[0].id, + { force: true } ); expect(mockSavedObjectsClient.delete).toHaveBeenCalledWith( mockSavedObjects[1].type, - mockSavedObjects[1].id + mockSavedObjects[1].id, + { force: true } ); expect(component.state('selectedSavedObjects').length).toBe(0); }); diff --git a/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.tsx b/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.tsx index d879a71cc2269..5011c0299abe8 100644 --- a/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.tsx +++ b/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.tsx @@ -468,7 +468,7 @@ export class SavedObjectsTable extends Component - savedObjectsClient.delete(object.type, object.id) + savedObjectsClient.delete(object.type, object.id, { force: true }) ); await Promise.all(deletes); diff --git a/src/plugins/security_oss/README.md b/src/plugins/security_oss/README.md new file mode 100644 index 0000000000000..6143149fec384 --- /dev/null +++ b/src/plugins/security_oss/README.md @@ -0,0 +1,4 @@ +# `securityOss` plugin + +`securityOss` is responsible for educating users about Elastic's free security features, +so they can properly protect the data within their clusters. diff --git a/src/plugins/security_oss/kibana.json b/src/plugins/security_oss/kibana.json new file mode 100644 index 0000000000000..70e37d586f1db --- /dev/null +++ b/src/plugins/security_oss/kibana.json @@ -0,0 +1,10 @@ +{ + "id": "securityOss", + "version": "8.0.0", + "kibanaVersion": "kibana", + "configPath": ["security"], + "ui": true, + "server": true, + "requiredPlugins": [], + "requiredBundles": [] +} diff --git a/src/plugins/security_oss/public/config.ts b/src/plugins/security_oss/public/config.ts new file mode 100644 index 0000000000000..17f6b5a53eb6c --- /dev/null +++ b/src/plugins/security_oss/public/config.ts @@ -0,0 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export interface ConfigType { + showInsecureClusterWarning: boolean; +} diff --git a/src/plugins/security_oss/public/index.ts b/src/plugins/security_oss/public/index.ts new file mode 100644 index 0000000000000..2e63a9316c99b --- /dev/null +++ b/src/plugins/security_oss/public/index.ts @@ -0,0 +1,26 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { PluginInitializerContext } from 'kibana/public'; + +import { SecurityOssPlugin } from './plugin'; + +export { SecurityOssPluginSetup, SecurityOssPluginStart } from './plugin'; +export const plugin = (initializerContext: PluginInitializerContext) => + new SecurityOssPlugin(initializerContext); diff --git a/src/plugins/security_oss/public/insecure_cluster_service/components/default_alert.test.tsx b/src/plugins/security_oss/public/insecure_cluster_service/components/default_alert.test.tsx new file mode 100644 index 0000000000000..b414ab78cdfdb --- /dev/null +++ b/src/plugins/security_oss/public/insecure_cluster_service/components/default_alert.test.tsx @@ -0,0 +1,37 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { defaultAlertText } from './default_alert'; + +describe('defaultAlertText', () => { + it('creates a valid MountPoint that can cleanup correctly', () => { + const mountPoint = defaultAlertText(jest.fn()); + + const el = document.createElement('div'); + const unmount = mountPoint(el); + + expect(el.querySelectorAll('[data-test-subj="insecureClusterDefaultAlertText"]')).toHaveLength( + 1 + ); + + unmount(); + + expect(el).toMatchInlineSnapshot(`
`); + }); +}); diff --git a/src/plugins/security_oss/public/insecure_cluster_service/components/default_alert.tsx b/src/plugins/security_oss/public/insecure_cluster_service/components/default_alert.tsx new file mode 100644 index 0000000000000..f2eeedb5b7372 --- /dev/null +++ b/src/plugins/security_oss/public/insecure_cluster_service/components/default_alert.tsx @@ -0,0 +1,97 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { + EuiButton, + EuiCheckbox, + EuiFlexGroup, + EuiFlexItem, + EuiSpacer, + EuiText, +} from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import { I18nProvider, FormattedMessage } from '@kbn/i18n/react'; +import { MountPoint } from 'kibana/public'; +import React, { useState } from 'react'; +import { render, unmountComponentAtNode } from 'react-dom'; + +export const defaultAlertTitle = i18n.translate('security.checkup.insecureClusterTitle', { + defaultMessage: 'Please secure your installation', +}); + +export const defaultAlertText: (onDismiss: (persist: boolean) => void) => MountPoint = ( + onDismiss +) => (e) => { + const AlertText = () => { + const [persist, setPersist] = useState(false); + + return ( + +
+ + + + + setPersist(changeEvent.target.checked)} + label={i18n.translate('security.checkup.dontShowAgain', { + defaultMessage: `Don't show again`, + })} + /> + + + + + {i18n.translate('security.checkup.learnMoreButtonText', { + defaultMessage: `Learn more`, + })} + + + + onDismiss(persist)} + data-test-subj="defaultDismissAlertButton" + > + {i18n.translate('security.checkup.dismissButtonText', { + defaultMessage: `Dismiss`, + })} + + + +
+
+ ); + }; + + render(, e); + + return () => unmountComponentAtNode(e); +}; diff --git a/src/plugins/security_oss/public/insecure_cluster_service/components/index.ts b/src/plugins/security_oss/public/insecure_cluster_service/components/index.ts new file mode 100644 index 0000000000000..9334dad2b8193 --- /dev/null +++ b/src/plugins/security_oss/public/insecure_cluster_service/components/index.ts @@ -0,0 +1,20 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export { defaultAlertTitle, defaultAlertText } from './default_alert'; diff --git a/src/plugins/security_oss/public/insecure_cluster_service/index.ts b/src/plugins/security_oss/public/insecure_cluster_service/index.ts new file mode 100644 index 0000000000000..7817dc383c168 --- /dev/null +++ b/src/plugins/security_oss/public/insecure_cluster_service/index.ts @@ -0,0 +1,24 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export { + InsecureClusterService, + InsecureClusterServiceSetup, + InsecureClusterServiceStart, +} from './insecure_cluster_service'; diff --git a/src/plugins/security_oss/public/insecure_cluster_service/insecure_cluster_service.mock.tsx b/src/plugins/security_oss/public/insecure_cluster_service/insecure_cluster_service.mock.tsx new file mode 100644 index 0000000000000..630becb49dd4c --- /dev/null +++ b/src/plugins/security_oss/public/insecure_cluster_service/insecure_cluster_service.mock.tsx @@ -0,0 +1,37 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { + InsecureClusterServiceSetup, + InsecureClusterServiceStart, +} from './insecure_cluster_service'; + +export const mockInsecureClusterService = { + createSetup: () => { + return { + setAlertTitle: jest.fn(), + setAlertText: jest.fn(), + } as InsecureClusterServiceSetup; + }, + createStart: () => { + return { + hideAlert: jest.fn(), + } as InsecureClusterServiceStart; + }, +}; diff --git a/src/plugins/security_oss/public/insecure_cluster_service/insecure_cluster_service.test.tsx b/src/plugins/security_oss/public/insecure_cluster_service/insecure_cluster_service.test.tsx new file mode 100644 index 0000000000000..a81f361689743 --- /dev/null +++ b/src/plugins/security_oss/public/insecure_cluster_service/insecure_cluster_service.test.tsx @@ -0,0 +1,336 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { InsecureClusterService } from './insecure_cluster_service'; +import { ConfigType } from '../config'; +import { coreMock } from '../../../../core/public/mocks'; +import { nextTick } from 'test_utils/enzyme_helpers'; + +let mockOnDismissCallback: (persist: boolean) => void = jest.fn().mockImplementation(() => { + throw new Error('expected callback to be replaced!'); +}); + +jest.mock('./components', () => { + return { + defaultAlertTitle: 'mocked default alert title', + defaultAlertText: (onDismiss: any) => { + mockOnDismissCallback = onDismiss; + return 'mocked default alert text'; + }, + }; +}); + +interface InitOpts { + displayAlert?: boolean; + isAnonymousPath?: boolean; + tenant?: string; +} + +function initCore({ + displayAlert = true, + isAnonymousPath = false, + tenant = '/server-base-path', +}: InitOpts = {}) { + const coreSetup = coreMock.createSetup(); + (coreSetup.http.basePath.serverBasePath as string) = tenant; + + const coreStart = coreMock.createStart(); + coreStart.http.get.mockImplementation(async (url: unknown) => { + if (url === '/internal/security_oss/display_insecure_cluster_alert') { + return { displayAlert }; + } + throw new Error(`unexpected call to http.get: ${url}`); + }); + coreStart.http.anonymousPaths.isAnonymous.mockReturnValue(isAnonymousPath); + + coreStart.notifications.toasts.addWarning.mockReturnValue({ id: 'mock_alert_id' }); + return { coreSetup, coreStart }; +} + +describe('InsecureClusterService', () => { + describe('display scenarios', () => { + it('does not display an alert when the warning is explicitly disabled via config', async () => { + const config: ConfigType = { showInsecureClusterWarning: false }; + const { coreSetup, coreStart } = initCore({ displayAlert: true }); + const storage = coreMock.createStorage(); + + const service = new InsecureClusterService(config, storage); + service.setup({ core: coreSetup }); + service.start({ core: coreStart }); + + await nextTick(); + + expect(coreStart.http.get).not.toHaveBeenCalled(); + expect(coreStart.notifications.toasts.addWarning).not.toHaveBeenCalled(); + + expect(coreStart.notifications.toasts.remove).not.toHaveBeenCalled(); + expect(storage.setItem).not.toHaveBeenCalled(); + }); + + it('does not display an alert when the endpoint check returns false', async () => { + const config: ConfigType = { showInsecureClusterWarning: true }; + const { coreSetup, coreStart } = initCore({ displayAlert: false }); + const storage = coreMock.createStorage(); + + const service = new InsecureClusterService(config, storage); + service.setup({ core: coreSetup }); + service.start({ core: coreStart }); + + await nextTick(); + + expect(coreStart.http.get).toHaveBeenCalledTimes(1); + expect(coreStart.notifications.toasts.addWarning).not.toHaveBeenCalled(); + + expect(coreStart.notifications.toasts.remove).not.toHaveBeenCalled(); + expect(storage.setItem).not.toHaveBeenCalled(); + }); + + it('does not display an alert when on an anonymous path', async () => { + const config: ConfigType = { showInsecureClusterWarning: true }; + const { coreSetup, coreStart } = initCore({ displayAlert: true, isAnonymousPath: true }); + const storage = coreMock.createStorage(); + + const service = new InsecureClusterService(config, storage); + service.setup({ core: coreSetup }); + service.start({ core: coreStart }); + + await nextTick(); + + expect(coreStart.http.get).not.toHaveBeenCalled(); + expect(coreStart.notifications.toasts.addWarning).not.toHaveBeenCalled(); + + expect(coreStart.notifications.toasts.remove).not.toHaveBeenCalled(); + expect(storage.setItem).not.toHaveBeenCalled(); + }); + + it('only reads storage information from the current tenant', async () => { + const config: ConfigType = { showInsecureClusterWarning: true }; + const { coreSetup, coreStart } = initCore({ + displayAlert: true, + tenant: '/my-specific-tenant', + }); + + const storage = coreMock.createStorage(); + storage.getItem.mockReturnValue(JSON.stringify({ show: false })); + + const service = new InsecureClusterService(config, storage); + service.setup({ core: coreSetup }); + service.start({ core: coreStart }); + + await nextTick(); + + expect(storage.getItem).toHaveBeenCalledTimes(1); + expect(storage.getItem).toHaveBeenCalledWith( + 'insecureClusterWarningVisibility/my-specific-tenant' + ); + }); + + it('does not display an alert when hidden via storage', async () => { + const config: ConfigType = { showInsecureClusterWarning: true }; + const { coreSetup, coreStart } = initCore({ displayAlert: true }); + + const storage = coreMock.createStorage(); + storage.getItem.mockReturnValue(JSON.stringify({ show: false })); + + const service = new InsecureClusterService(config, storage); + service.setup({ core: coreSetup }); + service.start({ core: coreStart }); + + await nextTick(); + + expect(coreStart.http.get).not.toHaveBeenCalled(); + expect(coreStart.notifications.toasts.addWarning).not.toHaveBeenCalled(); + + expect(coreStart.notifications.toasts.remove).not.toHaveBeenCalled(); + expect(storage.setItem).not.toHaveBeenCalled(); + }); + + it('displays an alert when persisted preference is corrupted', async () => { + const config: ConfigType = { showInsecureClusterWarning: true }; + const { coreSetup, coreStart } = initCore({ displayAlert: true }); + + const storage = coreMock.createStorage(); + storage.getItem.mockReturnValue('{ this is a string of invalid JSON'); + + const service = new InsecureClusterService(config, storage); + service.setup({ core: coreSetup }); + service.start({ core: coreStart }); + + await nextTick(); + + expect(coreStart.http.get).toHaveBeenCalledTimes(1); + expect(coreStart.notifications.toasts.addWarning).toHaveBeenCalledTimes(1); + + expect(coreStart.notifications.toasts.remove).not.toHaveBeenCalled(); + expect(storage.setItem).not.toHaveBeenCalled(); + }); + + it('displays an alert when enabled via config and endpoint checks', async () => { + const config: ConfigType = { showInsecureClusterWarning: true }; + const { coreSetup, coreStart } = initCore({ displayAlert: true }); + const storage = coreMock.createStorage(); + + const service = new InsecureClusterService(config, storage); + service.setup({ core: coreSetup }); + service.start({ core: coreStart }); + + await nextTick(); + + expect(coreStart.http.get).toHaveBeenCalledTimes(1); + expect(coreStart.notifications.toasts.addWarning).toHaveBeenCalledTimes(1); + expect(coreStart.notifications.toasts.addWarning.mock.calls[0]).toMatchInlineSnapshot(` + Array [ + Object { + "iconType": "alert", + "text": "mocked default alert text", + "title": "mocked default alert title", + }, + Object { + "toastLifeTimeMs": 864000000, + }, + ] + `); + + expect(coreStart.notifications.toasts.remove).not.toHaveBeenCalled(); + expect(storage.setItem).not.toHaveBeenCalled(); + }); + + it('dismisses the alert when requested, and remembers this preference', async () => { + const config: ConfigType = { showInsecureClusterWarning: true }; + const { coreSetup, coreStart } = initCore({ displayAlert: true }); + const storage = coreMock.createStorage(); + + const service = new InsecureClusterService(config, storage); + service.setup({ core: coreSetup }); + service.start({ core: coreStart }); + + await nextTick(); + + expect(coreStart.http.get).toHaveBeenCalledTimes(1); + expect(coreStart.notifications.toasts.addWarning).toHaveBeenCalledTimes(1); + + mockOnDismissCallback(true); + + expect(coreStart.notifications.toasts.remove).toHaveBeenCalledTimes(1); + expect(storage.setItem).toHaveBeenCalledWith( + 'insecureClusterWarningVisibility/server-base-path', + JSON.stringify({ show: false }) + ); + }); + }); + + describe('#setup', () => { + it('allows the alert title and text to be replaced exactly once', async () => { + const config: ConfigType = { showInsecureClusterWarning: true }; + const storage = coreMock.createStorage(); + + const { coreSetup } = initCore(); + + const service = new InsecureClusterService(config, storage); + const { setAlertTitle, setAlertText } = service.setup({ core: coreSetup }); + setAlertTitle('some new title'); + setAlertText('some new alert text'); + + expect(() => setAlertTitle('')).toThrowErrorMatchingInlineSnapshot( + `"alert title has already been set"` + ); + expect(() => setAlertText('')).toThrowErrorMatchingInlineSnapshot( + `"alert text has already been set"` + ); + }); + + it('allows the alert title and text to be replaced', async () => { + const config: ConfigType = { showInsecureClusterWarning: true }; + const { coreSetup, coreStart } = initCore({ displayAlert: true }); + const storage = coreMock.createStorage(); + + const service = new InsecureClusterService(config, storage); + const { setAlertTitle, setAlertText } = service.setup({ core: coreSetup }); + setAlertTitle('some new title'); + setAlertText('some new alert text'); + + service.start({ core: coreStart }); + + await nextTick(); + + expect(coreStart.http.get).toHaveBeenCalledTimes(1); + expect(coreStart.notifications.toasts.addWarning).toHaveBeenCalledTimes(1); + expect(coreStart.notifications.toasts.addWarning.mock.calls[0]).toMatchInlineSnapshot(` + Array [ + Object { + "iconType": "alert", + "text": "some new alert text", + "title": "some new title", + }, + Object { + "toastLifeTimeMs": 864000000, + }, + ] + `); + + expect(coreStart.notifications.toasts.remove).not.toHaveBeenCalled(); + expect(storage.setItem).not.toHaveBeenCalled(); + }); + }); + + describe('#start', () => { + it('allows the alert to be hidden via start contract, and remembers this preference', async () => { + const config: ConfigType = { showInsecureClusterWarning: true }; + const { coreSetup, coreStart } = initCore({ displayAlert: true }); + const storage = coreMock.createStorage(); + + const service = new InsecureClusterService(config, storage); + service.setup({ core: coreSetup }); + const { hideAlert } = service.start({ core: coreStart }); + + await nextTick(); + + expect(coreStart.http.get).toHaveBeenCalledTimes(1); + expect(coreStart.notifications.toasts.addWarning).toHaveBeenCalledTimes(1); + + hideAlert(true); + + expect(coreStart.notifications.toasts.remove).toHaveBeenCalledTimes(1); + expect(storage.setItem).toHaveBeenCalledWith( + 'insecureClusterWarningVisibility/server-base-path', + JSON.stringify({ show: false }) + ); + }); + + it('allows the alert to be hidden via start contract, and does not remember the preference', async () => { + const config: ConfigType = { showInsecureClusterWarning: true }; + const { coreSetup, coreStart } = initCore({ displayAlert: true }); + const storage = coreMock.createStorage(); + + const service = new InsecureClusterService(config, storage); + service.setup({ core: coreSetup }); + const { hideAlert } = service.start({ core: coreStart }); + + await nextTick(); + + expect(coreStart.http.get).toHaveBeenCalledTimes(1); + expect(coreStart.notifications.toasts.addWarning).toHaveBeenCalledTimes(1); + + hideAlert(false); + + expect(coreStart.notifications.toasts.remove).toHaveBeenCalledTimes(1); + expect(storage.setItem).not.toHaveBeenCalled(); + }); + }); +}); diff --git a/src/plugins/security_oss/public/insecure_cluster_service/insecure_cluster_service.tsx b/src/plugins/security_oss/public/insecure_cluster_service/insecure_cluster_service.tsx new file mode 100644 index 0000000000000..e6255233354b7 --- /dev/null +++ b/src/plugins/security_oss/public/insecure_cluster_service/insecure_cluster_service.tsx @@ -0,0 +1,164 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { CoreSetup, CoreStart, MountPoint, Toast } from 'kibana/public'; + +import { BehaviorSubject, combineLatest, from } from 'rxjs'; +import { distinctUntilChanged, map } from 'rxjs/operators'; +import { ConfigType } from '../config'; +import { defaultAlertText, defaultAlertTitle } from './components'; + +interface SetupDeps { + core: Pick; +} + +interface StartDeps { + core: Pick; +} + +export interface InsecureClusterServiceSetup { + setAlertTitle: (alertTitle: string | MountPoint) => void; + setAlertText: (alertText: string | MountPoint) => void; +} + +export interface InsecureClusterServiceStart { + hideAlert: (persist: boolean) => void; +} + +export class InsecureClusterService { + private enabled: boolean; + + private alertVisibility$: BehaviorSubject; + + private storage: Storage; + + private alertToast?: Toast; + + private alertTitle?: string | MountPoint; + + private alertText?: string | MountPoint; + + private storageKey?: string; + + constructor(config: Pick, storage: Storage) { + this.storage = storage; + this.enabled = config.showInsecureClusterWarning; + this.alertVisibility$ = new BehaviorSubject(this.enabled); + } + + public setup({ core }: SetupDeps): InsecureClusterServiceSetup { + const tenant = core.http.basePath.serverBasePath; + this.storageKey = `insecureClusterWarningVisibility${tenant}`; + this.enabled = this.enabled && this.getPersistedVisibilityPreference(); + this.alertVisibility$.next(this.enabled); + + return { + setAlertTitle: (alertTitle: string | MountPoint) => { + if (this.alertTitle) { + throw new Error('alert title has already been set'); + } + this.alertTitle = alertTitle; + }, + setAlertText: (alertText: string | MountPoint) => { + if (this.alertText) { + throw new Error('alert text has already been set'); + } + this.alertText = alertText; + }, + }; + } + + public start({ core }: StartDeps): InsecureClusterServiceStart { + const shouldInitialize = + this.enabled && !core.http.anonymousPaths.isAnonymous(window.location.pathname); + + if (shouldInitialize) { + this.initializeAlert(core); + } + + return { + hideAlert: (persist: boolean) => this.setAlertVisibility(false, persist), + }; + } + + private initializeAlert(core: StartDeps['core']) { + const displayAlert$ = from( + core.http + .get<{ displayAlert: boolean }>('/internal/security_oss/display_insecure_cluster_alert') + .catch((e) => { + // in the event we can't make this call, assume we shouldn't display this alert. + return { displayAlert: false }; + }) + ); + + // 10 days is reasonably long enough to call "forever" for a page load. + // Can't go too much longer than this. See https://github.com/elastic/kibana/issues/64264#issuecomment-618400354 + const oneMinute = 60000; + const tenDays = oneMinute * 60 * 24 * 10; + + combineLatest([displayAlert$, this.alertVisibility$]) + .pipe( + map(([{ displayAlert }, isAlertVisible]) => displayAlert && isAlertVisible), + distinctUntilChanged() + ) + .subscribe((showAlert) => { + if (showAlert && !this.alertToast) { + this.alertToast = core.notifications.toasts.addWarning( + { + title: this.alertTitle ?? defaultAlertTitle, + text: + this.alertText ?? + defaultAlertText((persist: boolean) => this.setAlertVisibility(false, persist)), + iconType: 'alert', + }, + { + toastLifeTimeMs: tenDays, + } + ); + } else if (!showAlert && this.alertToast) { + core.notifications.toasts.remove(this.alertToast); + this.alertToast = undefined; + } + }); + } + + private setAlertVisibility(show: boolean, persist: boolean) { + if (!this.enabled) { + return; + } + this.alertVisibility$.next(show); + if (persist) { + this.setPersistedVisibilityPreference(show); + } + } + + private getPersistedVisibilityPreference() { + const entry = this.storage.getItem(this.storageKey!) ?? '{}'; + try { + const { show = true } = JSON.parse(entry); + return show; + } catch (e) { + return true; + } + } + + private setPersistedVisibilityPreference(show: boolean) { + this.storage.setItem(this.storageKey!, JSON.stringify({ show })); + } +} diff --git a/src/plugins/security_oss/public/mocks.ts b/src/plugins/security_oss/public/mocks.ts new file mode 100644 index 0000000000000..f4913d2de671b --- /dev/null +++ b/src/plugins/security_oss/public/mocks.ts @@ -0,0 +1,20 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export { mockSecurityOssPlugin } from './plugin.mock'; diff --git a/src/plugins/security_oss/public/plugin.mock.ts b/src/plugins/security_oss/public/plugin.mock.ts new file mode 100644 index 0000000000000..c513d241dccbb --- /dev/null +++ b/src/plugins/security_oss/public/plugin.mock.ts @@ -0,0 +1,34 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { mockInsecureClusterService } from './insecure_cluster_service/insecure_cluster_service.mock'; +import { SecurityOssPluginSetup, SecurityOssPluginStart } from './plugin'; + +export const mockSecurityOssPlugin = { + createSetup: () => { + return { + insecureCluster: mockInsecureClusterService.createSetup(), + } as DeeplyMockedKeys; + }, + createStart: () => { + return { + insecureCluster: mockInsecureClusterService.createStart(), + } as DeeplyMockedKeys; + }, +}; diff --git a/src/plugins/security_oss/public/plugin.ts b/src/plugins/security_oss/public/plugin.ts new file mode 100644 index 0000000000000..2f3eed0bde5eb --- /dev/null +++ b/src/plugins/security_oss/public/plugin.ts @@ -0,0 +1,58 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { CoreSetup, CoreStart, Plugin, PluginInitializerContext } from 'src/core/public'; +import { ConfigType } from './config'; +import { + InsecureClusterService, + InsecureClusterServiceSetup, + InsecureClusterServiceStart, +} from './insecure_cluster_service'; + +export interface SecurityOssPluginSetup { + insecureCluster: InsecureClusterServiceSetup; +} + +export interface SecurityOssPluginStart { + insecureCluster: InsecureClusterServiceStart; +} + +export class SecurityOssPlugin + implements Plugin { + private readonly config: ConfigType; + + private insecureClusterService: InsecureClusterService; + + constructor(private readonly initializerContext: PluginInitializerContext) { + this.config = this.initializerContext.config.get(); + this.insecureClusterService = new InsecureClusterService(this.config, localStorage); + } + + public setup(core: CoreSetup) { + return { + insecureCluster: this.insecureClusterService.setup({ core }), + }; + } + + public start(core: CoreStart) { + return { + insecureCluster: this.insecureClusterService.start({ core }), + }; + } +} diff --git a/src/plugins/security_oss/server/check_cluster_data.test.ts b/src/plugins/security_oss/server/check_cluster_data.test.ts new file mode 100644 index 0000000000000..a8245931daf04 --- /dev/null +++ b/src/plugins/security_oss/server/check_cluster_data.test.ts @@ -0,0 +1,148 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { elasticsearchServiceMock, loggingSystemMock } from '../../../core/server/mocks'; +import { createClusterDataCheck } from './check_cluster_data'; + +describe('checkClusterForUserData', () => { + it('returns false if no data is found', async () => { + const esClient = elasticsearchServiceMock.createElasticsearchClient(); + esClient.cat.indices.mockResolvedValue( + elasticsearchServiceMock.createApiResponse({ body: [] }) + ); + + const log = loggingSystemMock.createLogger(); + + const response = await createClusterDataCheck()(esClient, log); + expect(response).toEqual(false); + expect(esClient.cat.indices).toHaveBeenCalledTimes(1); + }); + + it('returns false if data only exists in system indices', async () => { + const esClient = elasticsearchServiceMock.createElasticsearchClient(); + esClient.cat.indices.mockResolvedValue( + elasticsearchServiceMock.createApiResponse({ + body: [ + { + index: '.kibana', + 'docs.count': 500, + }, + { + index: 'kibana_sample_ecommerce_data', + 'docs.count': 20, + }, + { + index: '.somethingElse', + 'docs.count': 20, + }, + ], + }) + ); + + const log = loggingSystemMock.createLogger(); + + const response = await createClusterDataCheck()(esClient, log); + expect(response).toEqual(false); + expect(esClient.cat.indices).toHaveBeenCalledTimes(1); + }); + + it('returns true if data exists in non-system indices', async () => { + const esClient = elasticsearchServiceMock.createElasticsearchClient(); + esClient.cat.indices.mockResolvedValue( + elasticsearchServiceMock.createApiResponse({ + body: [ + { + index: '.kibana', + 'docs.count': 500, + }, + { + index: 'some_real_index', + 'docs.count': 20, + }, + ], + }) + ); + + const log = loggingSystemMock.createLogger(); + + const response = await createClusterDataCheck()(esClient, log); + expect(response).toEqual(true); + }); + + it('checks each time until the first true response is returned, then stops checking', async () => { + const esClient = elasticsearchServiceMock.createElasticsearchClient(); + esClient.cat.indices + .mockResolvedValueOnce( + elasticsearchServiceMock.createApiResponse({ + body: [], + }) + ) + .mockRejectedValueOnce(new Error('something terrible happened')) + .mockResolvedValueOnce( + elasticsearchServiceMock.createApiResponse({ + body: [ + { + index: '.kibana', + 'docs.count': 500, + }, + ], + }) + ) + .mockResolvedValueOnce( + elasticsearchServiceMock.createApiResponse({ + body: [ + { + index: 'some_real_index', + 'docs.count': 20, + }, + ], + }) + ); + + const log = loggingSystemMock.createLogger(); + + const doesClusterHaveUserData = createClusterDataCheck(); + + let response = await doesClusterHaveUserData(esClient, log); + expect(response).toEqual(false); + + response = await doesClusterHaveUserData(esClient, log); + expect(response).toEqual(false); + + response = await doesClusterHaveUserData(esClient, log); + expect(response).toEqual(false); + + response = await doesClusterHaveUserData(esClient, log); + expect(response).toEqual(true); + + expect(esClient.cat.indices).toHaveBeenCalledTimes(4); + expect(log.warn.mock.calls).toMatchInlineSnapshot(` + Array [ + Array [ + "Error encountered while checking cluster for user data: Error: something terrible happened", + ], + ] + `); + + response = await doesClusterHaveUserData(esClient, log); + expect(response).toEqual(true); + // Same number of calls as above. We should not have to interrogate again. + expect(esClient.cat.indices).toHaveBeenCalledTimes(4); + }); +}); diff --git a/src/plugins/security_oss/server/check_cluster_data.ts b/src/plugins/security_oss/server/check_cluster_data.ts new file mode 100644 index 0000000000000..a3aeb50ae280a --- /dev/null +++ b/src/plugins/security_oss/server/check_cluster_data.ts @@ -0,0 +1,47 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { ElasticsearchClient, Logger } from 'kibana/server'; + +export const createClusterDataCheck = () => { + let clusterHasUserData = false; + + return async function doesClusterHaveUserData(esClient: ElasticsearchClient, log: Logger) { + if (!clusterHasUserData) { + try { + const indices = await esClient.cat.indices< + Array<{ index: string; ['docs.count']: string }> + >({ + format: 'json', + h: ['index', 'docs.count'], + }); + clusterHasUserData = indices.body.some((indexCount) => { + const isInternalIndex = + indexCount.index.startsWith('.') || indexCount.index.startsWith('kibana_sample_'); + + return !isInternalIndex && parseInt(indexCount['docs.count'], 10) > 0; + }); + } catch (e) { + log.warn(`Error encountered while checking cluster for user data: ${e}`); + clusterHasUserData = false; + } + } + return clusterHasUserData; + }; +}; diff --git a/src/plugins/security_oss/server/config.ts b/src/plugins/security_oss/server/config.ts new file mode 100644 index 0000000000000..17fb46065aee5 --- /dev/null +++ b/src/plugins/security_oss/server/config.ts @@ -0,0 +1,26 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { schema, TypeOf } from '@kbn/config-schema'; + +export type ConfigType = TypeOf; + +export const ConfigSchema = schema.object({ + showInsecureClusterWarning: schema.boolean({ defaultValue: true }), +}); diff --git a/src/plugins/security_oss/server/index.ts b/src/plugins/security_oss/server/index.ts new file mode 100644 index 0000000000000..f35ae39daaff3 --- /dev/null +++ b/src/plugins/security_oss/server/index.ts @@ -0,0 +1,35 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { TypeOf } from '@kbn/config-schema'; + +import { PluginConfigDescriptor, PluginInitializerContext } from 'kibana/server'; +import { ConfigSchema } from './config'; +import { SecurityOssPlugin } from './plugin'; + +export { SecurityOssPluginSetup } from './plugin'; + +export const config: PluginConfigDescriptor> = { + schema: ConfigSchema, + exposeToBrowser: { + showInsecureClusterWarning: true, + }, +}; + +export const plugin = (context: PluginInitializerContext) => new SecurityOssPlugin(context); diff --git a/src/plugins/security_oss/server/plugin.test.ts b/src/plugins/security_oss/server/plugin.test.ts new file mode 100644 index 0000000000000..417da0c7e73bb --- /dev/null +++ b/src/plugins/security_oss/server/plugin.test.ts @@ -0,0 +1,37 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { coreMock } from '../../../core/server/mocks'; +import { SecurityOssPlugin } from './plugin'; + +describe('SecurityOss Plugin', () => { + describe('#setup', () => { + it('exposes the proper contract', async () => { + const context = coreMock.createPluginInitializerContext(); + const plugin = new SecurityOssPlugin(context); + const core = coreMock.createSetup(); + const contract = plugin.setup(core); + expect(Object.keys(contract)).toMatchInlineSnapshot(` + Array [ + "showInsecureClusterWarning$", + ] + `); + }); + }); +}); diff --git a/src/plugins/security_oss/server/plugin.ts b/src/plugins/security_oss/server/plugin.ts new file mode 100644 index 0000000000000..e48827f21a13a --- /dev/null +++ b/src/plugins/security_oss/server/plugin.ts @@ -0,0 +1,62 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { CoreSetup, Logger, Plugin, PluginInitializerContext } from 'kibana/server'; +import { BehaviorSubject, Observable } from 'rxjs'; +import { createClusterDataCheck } from './check_cluster_data'; +import { ConfigType } from './config'; +import { setupDisplayInsecureClusterAlertRoute } from './routes'; + +export interface SecurityOssPluginSetup { + /** + * Allows consumers to show/hide the insecure cluster warning. + */ + showInsecureClusterWarning$: BehaviorSubject; +} + +export class SecurityOssPlugin implements Plugin { + private readonly config$: Observable; + private readonly logger: Logger; + + constructor(initializerContext: PluginInitializerContext) { + this.config$ = initializerContext.config.create(); + this.logger = initializerContext.logger.get(); + } + + public setup(core: CoreSetup) { + const router = core.http.createRouter(); + const showInsecureClusterWarning$ = new BehaviorSubject(true); + + setupDisplayInsecureClusterAlertRoute({ + router, + log: this.logger, + config$: this.config$, + displayModifier$: showInsecureClusterWarning$, + doesClusterHaveUserData: createClusterDataCheck(), + }); + + return { + showInsecureClusterWarning$, + }; + } + + public start() {} + + public stop() {} +} diff --git a/src/plugins/security_oss/server/routes/display_insecure_cluster_alert.ts b/src/plugins/security_oss/server/routes/display_insecure_cluster_alert.ts new file mode 100644 index 0000000000000..0f0f72f054b4c --- /dev/null +++ b/src/plugins/security_oss/server/routes/display_insecure_cluster_alert.ts @@ -0,0 +1,63 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { IRouter, Logger } from 'kibana/server'; +import { combineLatest, Observable } from 'rxjs'; +import { createClusterDataCheck } from '../check_cluster_data'; +import { ConfigType } from '../config'; + +interface Deps { + router: IRouter; + log: Logger; + config$: Observable; + displayModifier$: Observable; + doesClusterHaveUserData: ReturnType; +} + +export const setupDisplayInsecureClusterAlertRoute = ({ + router, + log, + config$, + displayModifier$, + doesClusterHaveUserData, +}: Deps) => { + let showInsecureClusterWarning = false; + + combineLatest([config$, displayModifier$]).subscribe(([config, displayModifier]) => { + showInsecureClusterWarning = config.showInsecureClusterWarning && displayModifier; + }); + + router.get( + { + path: '/internal/security_oss/display_insecure_cluster_alert', + validate: false, + }, + async (context, request, response) => { + if (!showInsecureClusterWarning) { + return response.ok({ body: { displayAlert: false } }); + } + + const hasData = await doesClusterHaveUserData( + context.core.elasticsearch.client.asInternalUser, + log + ); + return response.ok({ body: { displayAlert: hasData } }); + } + ); +}; diff --git a/src/plugins/security_oss/server/routes/index.ts b/src/plugins/security_oss/server/routes/index.ts new file mode 100644 index 0000000000000..ceff0b12c9cb1 --- /dev/null +++ b/src/plugins/security_oss/server/routes/index.ts @@ -0,0 +1,20 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export { setupDisplayInsecureClusterAlertRoute } from './display_insecure_cluster_alert'; diff --git a/src/plugins/security_oss/server/routes/integration_tests/display_insecure_cluster_alert.test.ts b/src/plugins/security_oss/server/routes/integration_tests/display_insecure_cluster_alert.test.ts new file mode 100644 index 0000000000000..d62a5040be6b3 --- /dev/null +++ b/src/plugins/security_oss/server/routes/integration_tests/display_insecure_cluster_alert.test.ts @@ -0,0 +1,134 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { loggingSystemMock } from '../../../../../core/server/mocks'; +import { setupServer } from '../../../../../core/server/test_utils'; +import { setupDisplayInsecureClusterAlertRoute } from '../display_insecure_cluster_alert'; +import { ConfigType } from '../../config'; +import { BehaviorSubject, of } from 'rxjs'; +import { UnwrapPromise } from '@kbn/utility-types'; +import { createClusterDataCheck } from '../../check_cluster_data'; +import supertest from 'supertest'; + +type SetupServerReturn = UnwrapPromise>; +const pluginId = Symbol('securityOss'); + +interface SetupOpts { + config?: ConfigType; + displayModifier$?: BehaviorSubject; + doesClusterHaveUserData?: ReturnType; +} + +describe('GET /internal/security_oss/display_insecure_cluster_alert', () => { + let server: SetupServerReturn['server']; + let httpSetup: SetupServerReturn['httpSetup']; + + const setupTestServer = async ({ + config = { showInsecureClusterWarning: true }, + displayModifier$ = new BehaviorSubject(true), + doesClusterHaveUserData = jest.fn().mockResolvedValue(true), + }: SetupOpts) => { + ({ server, httpSetup } = await setupServer(pluginId)); + + const router = httpSetup.createRouter('/'); + const log = loggingSystemMock.createLogger(); + + setupDisplayInsecureClusterAlertRoute({ + router, + log, + config$: of(config), + displayModifier$, + doesClusterHaveUserData, + }); + + await server.start(); + + return { + log, + }; + }; + + afterEach(async () => { + await server.stop(); + }); + + it('responds `false` if plugin is not configured to display alerts', async () => { + await setupTestServer({ + config: { showInsecureClusterWarning: false }, + }); + + await supertest(httpSetup.server.listener) + .get('/internal/security_oss/display_insecure_cluster_alert') + .expect(200, { displayAlert: false }); + }); + + it('responds `false` if cluster does not contain user data', async () => { + await setupTestServer({ + config: { showInsecureClusterWarning: true }, + doesClusterHaveUserData: jest.fn().mockResolvedValue(false), + }); + + await supertest(httpSetup.server.listener) + .get('/internal/security_oss/display_insecure_cluster_alert') + .expect(200, { displayAlert: false }); + }); + + it('responds `false` if displayModifier$ is set to false', async () => { + await setupTestServer({ + config: { showInsecureClusterWarning: true }, + doesClusterHaveUserData: jest.fn().mockResolvedValue(true), + displayModifier$: new BehaviorSubject(false), + }); + + await supertest(httpSetup.server.listener) + .get('/internal/security_oss/display_insecure_cluster_alert') + .expect(200, { displayAlert: false }); + }); + + it('responds `true` if cluster contains user data', async () => { + await setupTestServer({ + config: { showInsecureClusterWarning: true }, + doesClusterHaveUserData: jest.fn().mockResolvedValue(true), + }); + + await supertest(httpSetup.server.listener) + .get('/internal/security_oss/display_insecure_cluster_alert') + .expect(200, { displayAlert: true }); + }); + + it('responds to changing displayModifier$ values', async () => { + const displayModifier$ = new BehaviorSubject(true); + + await setupTestServer({ + config: { showInsecureClusterWarning: true }, + doesClusterHaveUserData: jest.fn().mockResolvedValue(true), + displayModifier$, + }); + + await supertest(httpSetup.server.listener) + .get('/internal/security_oss/display_insecure_cluster_alert') + .expect(200, { displayAlert: true }); + + displayModifier$.next(false); + + await supertest(httpSetup.server.listener) + .get('/internal/security_oss/display_insecure_cluster_alert') + .expect(200, { displayAlert: false }); + }); +}); diff --git a/src/plugins/share/public/index.ts b/src/plugins/share/public/index.ts index e3d6c41a278cd..950ecebeaadc7 100644 --- a/src/plugins/share/public/index.ts +++ b/src/plugins/share/public/index.ts @@ -40,4 +40,6 @@ export { import { SharePlugin } from './plugin'; +export { KibanaURL } from './kibana_url'; + export const plugin = () => new SharePlugin(); diff --git a/src/plugins/share/public/kibana_url.ts b/src/plugins/share/public/kibana_url.ts new file mode 100644 index 0000000000000..40c3372579f6a --- /dev/null +++ b/src/plugins/share/public/kibana_url.ts @@ -0,0 +1,44 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +// TODO: Replace this logic with KibanaURL once it is available. +// https://github.com/elastic/kibana/issues/64497 +export class KibanaURL { + public readonly path: string; + public readonly appName: string; + public readonly appPath: string; + + constructor(path: string) { + const match = path.match(/^.*\/app\/([^\/#]+)(.+)$/); + + if (!match) { + throw new Error('Unexpected URL path.'); + } + + const [, appName, appPath] = match; + + if (!appName || !appPath) { + throw new Error('Could not parse URL path.'); + } + + this.path = path; + this.appName = appName; + this.appPath = appPath; + } +} diff --git a/src/plugins/share/public/types.ts b/src/plugins/share/public/types.ts index 9dcfc3d9e8143..19f33a820a11a 100644 --- a/src/plugins/share/public/types.ts +++ b/src/plugins/share/public/types.ts @@ -18,7 +18,8 @@ */ import { ComponentType } from 'react'; -import { EuiContextMenuPanelDescriptor, EuiContextMenuPanelItemDescriptor } from '@elastic/eui'; +import { EuiContextMenuPanelDescriptor } from '@elastic/eui'; +import { EuiContextMenuPanelItemDescriptorEntry } from '@elastic/eui/src/components/context_menu/context_menu'; /** * @public @@ -53,7 +54,8 @@ export interface ShareContext { * used to order the individual items in a flat list returned by all registered * menu providers. * */ -export interface ShareContextMenuPanelItem extends Omit { +export interface ShareContextMenuPanelItem + extends Omit { name: string; // EUI will accept a `ReactNode` for the `name` prop, but `ShareContentMenu` assumes a `string`. sortOrder?: number; } diff --git a/src/plugins/telemetry/schema/oss_plugins.json b/src/plugins/telemetry/schema/oss_plugins.json index 5bce03a292760..160e99a40790c 100644 --- a/src/plugins/telemetry/schema/oss_plugins.json +++ b/src/plugins/telemetry/schema/oss_plugins.json @@ -29,7 +29,10 @@ "sample-data": { "properties": { "installed": { - "type": "keyword" + "type": "array", + "items": { + "type": "keyword" + } }, "last_install_date": { "type": "date" @@ -44,7 +47,10 @@ "type": "keyword" }, "uninstalled": { - "type": "keyword" + "type": "array", + "items": { + "type": "keyword" + } } } }, @@ -1284,6 +1290,235 @@ } } }, + "core": { + "properties": { + "config": { + "properties": { + "elasticsearch": { + "properties": { + "sniffOnStart": { + "type": "boolean" + }, + "sniffIntervalMs": { + "type": "long" + }, + "sniffOnConnectionFault": { + "type": "boolean" + }, + "numberOfHostsConfigured": { + "type": "long" + }, + "requestHeadersWhitelistConfigured": { + "type": "boolean" + }, + "customHeadersConfigured": { + "type": "boolean" + }, + "shardTimeoutMs": { + "type": "long" + }, + "requestTimeoutMs": { + "type": "long" + }, + "pingTimeoutMs": { + "type": "long" + }, + "logQueries": { + "type": "boolean" + }, + "ssl": { + "properties": { + "verificationMode": { + "type": "keyword" + }, + "certificateAuthoritiesConfigured": { + "type": "boolean" + }, + "certificateConfigured": { + "type": "boolean" + }, + "keyConfigured": { + "type": "boolean" + }, + "keystoreConfigured": { + "type": "boolean" + }, + "truststoreConfigured": { + "type": "boolean" + }, + "alwaysPresentCertificate": { + "type": "boolean" + } + } + }, + "apiVersion": { + "type": "keyword" + }, + "healthCheckDelayMs": { + "type": "long" + } + } + }, + "http": { + "properties": { + "basePathConfigured": { + "type": "boolean" + }, + "maxPayloadInBytes": { + "type": "long" + }, + "rewriteBasePath": { + "type": "boolean" + }, + "keepaliveTimeout": { + "type": "long" + }, + "socketTimeout": { + "type": "long" + }, + "compression": { + "properties": { + "enabled": { + "type": "boolean" + }, + "referrerWhitelistConfigured": { + "type": "boolean" + } + } + }, + "xsrf": { + "properties": { + "disableProtection": { + "type": "boolean" + }, + "whitelistConfigured": { + "type": "boolean" + } + } + }, + "requestId": { + "properties": { + "allowFromAnyIp": { + "type": "boolean" + }, + "ipAllowlistConfigured": { + "type": "boolean" + } + } + }, + "ssl": { + "properties": { + "certificateAuthoritiesConfigured": { + "type": "boolean" + }, + "certificateConfigured": { + "type": "boolean" + }, + "cipherSuites": { + "type": "array", + "items": { + "type": "keyword" + } + }, + "keyConfigured": { + "type": "boolean" + }, + "keystoreConfigured": { + "type": "boolean" + }, + "truststoreConfigured": { + "type": "boolean" + }, + "redirectHttpFromPortConfigured": { + "type": "boolean" + }, + "supportedProtocols": { + "type": "array", + "items": { + "type": "keyword" + } + }, + "clientAuthentication": { + "type": "keyword" + } + } + } + } + }, + "logging": { + "properties": { + "appendersTypesUsed": { + "type": "array", + "items": { + "type": "keyword" + } + }, + "loggersConfiguredCount": { + "type": "long" + } + } + }, + "savedObjects": { + "properties": { + "maxImportPayloadBytes": { + "type": "long" + }, + "maxImportExportSizeBytes": { + "type": "long" + } + } + } + } + }, + "environment": { + "properties": { + "memory": { + "properties": { + "heapSizeLimit": { + "type": "long" + }, + "heapTotalBytes": { + "type": "long" + }, + "heapUsedBytes": { + "type": "long" + } + } + } + } + }, + "services": { + "properties": { + "savedObjects": { + "properties": { + "indices": { + "type": "array", + "items": { + "properties": { + "docsCount": { + "type": "long" + }, + "docsDeleted": { + "type": "long" + }, + "alias": { + "type": "text" + }, + "primaryStoreSizeBytes": { + "type": "long" + }, + "storeSizeBytes": { + "type": "long" + } + } + } + } + } + } + } + } + } + }, "csp": { "properties": { "strict": { @@ -1297,6 +1532,1071 @@ } } }, + "kibana": { + "properties": { + "index": { + "type": "keyword" + }, + "dashboard": { + "properties": { + "total": { + "type": "long" + } + } + }, + "visualization": { + "properties": { + "total": { + "type": "long" + } + } + }, + "search": { + "properties": { + "total": { + "type": "long" + } + } + }, + "index_pattern": { + "properties": { + "total": { + "type": "long" + } + } + }, + "graph_workspace": { + "properties": { + "total": { + "type": "long" + } + } + }, + "timelion_sheet": { + "properties": { + "total": { + "type": "long" + } + } + } + } + }, + "stack_management": { + "properties": { + "visualize:enableLabs": { + "type": "boolean" + }, + "visualization:heatmap:maxBuckets": { + "type": "long" + }, + "visualization:colorMapping": { + "type": "text" + }, + "visualization:regionmap:showWarnings": { + "type": "boolean" + }, + "visualization:dimmingOpacity": { + "type": "float" + }, + "visualization:tileMap:maxPrecision": { + "type": "long" + }, + "securitySolution:ipReputationLinks": { + "type": "text" + }, + "csv:separator": { + "type": "keyword" + }, + "visualization:tileMap:WMSdefaults": { + "type": "text" + }, + "timelion:target_buckets": { + "type": "long" + }, + "timelion:max_buckets": { + "type": "long" + }, + "timelion:es.timefield": { + "type": "keyword" + }, + "timelion:min_interval": { + "type": "keyword" + }, + "timelion:default_rows": { + "type": "long" + }, + "timelion:default_columns": { + "type": "long" + }, + "timelion:quandl.key": { + "type": "keyword" + }, + "timelion:es.default_index": { + "type": "keyword" + }, + "timelion:showTutorial": { + "type": "boolean" + }, + "securitySolution:timeDefaults": { + "type": "keyword" + }, + "securitySolution:defaultAnomalyScore": { + "type": "long" + }, + "securitySolution:defaultIndex": { + "type": "keyword" + }, + "securitySolution:refreshIntervalDefaults": { + "type": "keyword" + }, + "securitySolution:newsFeedUrl": { + "type": "keyword" + }, + "securitySolution:enableNewsFeed": { + "type": "boolean" + }, + "search:includeFrozen": { + "type": "boolean" + }, + "courier:maxConcurrentShardRequests": { + "type": "long" + }, + "courier:batchSearches": { + "type": "boolean" + }, + "courier:setRequestPreference": { + "type": "keyword" + }, + "courier:customRequestPreference": { + "type": "keyword" + }, + "courier:ignoreFilterIfFieldNotInIndex": { + "type": "boolean" + }, + "rollups:enableIndexPatterns": { + "type": "boolean" + }, + "xpackReporting:customPdfLogo": { + "type": "text" + }, + "notifications:lifetime:warning": { + "type": "long" + }, + "notifications:lifetime:banner": { + "type": "long" + }, + "notifications:lifetime:info": { + "type": "long" + }, + "notifications:banner": { + "type": "text" + }, + "notifications:lifetime:error": { + "type": "long" + }, + "doc_table:highlight": { + "type": "boolean" + }, + "discover:searchOnPageLoad": { + "type": "boolean" + }, + "doc_table:hideTimeColumn": { + "type": "boolean" + }, + "discover:sampleSize": { + "type": "long" + }, + "defaultColumns": { + "type": "keyword" + }, + "context:defaultSize": { + "type": "long" + }, + "discover:aggs:terms:size": { + "type": "long" + }, + "context:tieBreakerFields": { + "type": "keyword" + }, + "discover:sort:defaultOrder": { + "type": "keyword" + }, + "context:step": { + "type": "long" + }, + "accessibility:disableAnimations": { + "type": "boolean" + }, + "ml:fileDataVisualizerMaxFileSize": { + "type": "keyword" + }, + "ml:anomalyDetection:results:enableTimeDefaults": { + "type": "boolean" + }, + "ml:anomalyDetection:results:timeDefaults": { + "type": "keyword" + }, + "truncate:maxHeight": { + "type": "long" + }, + "timepicker:timeDefaults": { + "type": "keyword" + }, + "timepicker:refreshIntervalDefaults": { + "type": "keyword" + }, + "timepicker:quickRanges": { + "type": "keyword" + }, + "theme:version": { + "type": "keyword" + }, + "theme:darkMode": { + "type": "boolean" + }, + "state:storeInSessionStorage": { + "type": "boolean" + }, + "savedObjects:perPage": { + "type": "long" + }, + "search:queryLanguage": { + "type": "keyword" + }, + "shortDots:enable": { + "type": "boolean" + }, + "sort:options": { + "type": "keyword" + }, + "savedObjects:listingLimit": { + "type": "long" + }, + "query:queryString:options": { + "type": "keyword" + }, + "pageNavigation": { + "type": "keyword" + }, + "metrics:max_buckets": { + "type": "long" + }, + "query:allowLeadingWildcards": { + "type": "boolean" + }, + "metaFields": { + "type": "keyword" + }, + "indexPattern:placeholder": { + "type": "keyword" + }, + "histogram:barTarget": { + "type": "long" + }, + "histogram:maxBars": { + "type": "long" + }, + "format:number:defaultLocale": { + "type": "keyword" + }, + "format:percent:defaultPattern": { + "type": "keyword" + }, + "format:number:defaultPattern": { + "type": "keyword" + }, + "history:limit": { + "type": "long" + }, + "format:defaultTypeMap": { + "type": "keyword" + }, + "format:currency:defaultPattern": { + "type": "keyword" + }, + "defaultIndex": { + "type": "keyword" + }, + "format:bytes:defaultPattern": { + "type": "keyword" + }, + "filters:pinnedByDefault": { + "type": "boolean" + }, + "filterEditor:suggestValues": { + "type": "boolean" + }, + "fields:popularLimit": { + "type": "long" + }, + "dateNanosFormat": { + "type": "keyword" + }, + "defaultRoute": { + "type": "keyword" + }, + "dateFormat:tz": { + "type": "keyword" + }, + "dateFormat:scaled": { + "type": "keyword" + }, + "csv:quoteValues": { + "type": "boolean" + }, + "dateFormat:dow": { + "type": "keyword" + }, + "dateFormat": { + "type": "keyword" + } + } + }, + "ui_metric": { + "properties": { + "console": { + "type": "array", + "items": { + "properties": { + "key": { + "type": "keyword" + }, + "value": { + "type": "long" + } + } + } + }, + "DashboardPanelVersionInUrl": { + "type": "array", + "items": { + "properties": { + "key": { + "type": "keyword" + }, + "value": { + "type": "long" + } + } + } + }, + "Kibana_home": { + "type": "array", + "items": { + "properties": { + "key": { + "type": "keyword" + }, + "value": { + "type": "long" + } + } + } + }, + "visualize": { + "type": "array", + "items": { + "properties": { + "key": { + "type": "keyword" + }, + "value": { + "type": "long" + } + } + } + }, + "canvas": { + "type": "array", + "items": { + "properties": { + "key": { + "type": "keyword" + }, + "value": { + "type": "long" + } + } + } + }, + "cross_cluster_replication": { + "type": "array", + "items": { + "properties": { + "key": { + "type": "keyword" + }, + "value": { + "type": "long" + } + } + } + }, + "index_lifecycle_management": { + "type": "array", + "items": { + "properties": { + "key": { + "type": "keyword" + }, + "value": { + "type": "long" + } + } + } + }, + "index_management": { + "type": "array", + "items": { + "properties": { + "key": { + "type": "keyword" + }, + "value": { + "type": "long" + } + } + } + }, + "ingest_pipelines": { + "type": "array", + "items": { + "properties": { + "key": { + "type": "keyword" + }, + "value": { + "type": "long" + } + } + } + }, + "apm": { + "type": "array", + "items": { + "properties": { + "key": { + "type": "keyword" + }, + "value": { + "type": "long" + } + } + } + }, + "infra_logs": { + "type": "array", + "items": { + "properties": { + "key": { + "type": "keyword" + }, + "value": { + "type": "long" + } + } + } + }, + "infra_metrics": { + "type": "array", + "items": { + "properties": { + "key": { + "type": "keyword" + }, + "value": { + "type": "long" + } + } + } + }, + "stack_monitoring": { + "type": "array", + "items": { + "properties": { + "key": { + "type": "keyword" + }, + "value": { + "type": "long" + } + } + } + }, + "remote_clusters": { + "type": "array", + "items": { + "properties": { + "key": { + "type": "keyword" + }, + "value": { + "type": "long" + } + } + } + }, + "rollup_jobs": { + "type": "array", + "items": { + "properties": { + "key": { + "type": "keyword" + }, + "value": { + "type": "long" + } + } + } + }, + "securitySolution": { + "type": "array", + "items": { + "properties": { + "key": { + "type": "keyword" + }, + "value": { + "type": "long" + } + } + } + }, + "snapshot_restore": { + "type": "array", + "items": { + "properties": { + "key": { + "type": "keyword" + }, + "value": { + "type": "long" + } + } + } + }, + "dashboards": { + "type": "array", + "items": { + "properties": { + "key": { + "type": "keyword" + }, + "value": { + "type": "long" + } + } + } + }, + "dev_tools": { + "type": "array", + "items": { + "properties": { + "key": { + "type": "keyword" + }, + "value": { + "type": "long" + } + } + } + }, + "discover": { + "type": "array", + "items": { + "properties": { + "key": { + "type": "keyword" + }, + "value": { + "type": "long" + } + } + } + }, + "home": { + "type": "array", + "items": { + "properties": { + "key": { + "type": "keyword" + }, + "value": { + "type": "long" + } + } + } + }, + "kibana": { + "type": "array", + "items": { + "properties": { + "key": { + "type": "keyword" + }, + "value": { + "type": "long" + } + } + } + }, + "management": { + "type": "array", + "items": { + "properties": { + "key": { + "type": "keyword" + }, + "value": { + "type": "long" + } + } + } + }, + "short_url_redirect": { + "type": "array", + "items": { + "properties": { + "key": { + "type": "keyword" + }, + "value": { + "type": "long" + } + } + } + }, + "timelion": { + "type": "array", + "items": { + "properties": { + "key": { + "type": "keyword" + }, + "value": { + "type": "long" + } + } + } + }, + "csm": { + "type": "array", + "items": { + "properties": { + "key": { + "type": "keyword" + }, + "value": { + "type": "long" + } + } + } + }, + "dashboard_mode": { + "type": "array", + "items": { + "properties": { + "key": { + "type": "keyword" + }, + "value": { + "type": "long" + } + } + } + }, + "enterpriseSearch": { + "type": "array", + "items": { + "properties": { + "key": { + "type": "keyword" + }, + "value": { + "type": "long" + } + } + } + }, + "appSearch": { + "type": "array", + "items": { + "properties": { + "key": { + "type": "keyword" + }, + "value": { + "type": "long" + } + } + } + }, + "workplaceSearch": { + "type": "array", + "items": { + "properties": { + "key": { + "type": "keyword" + }, + "value": { + "type": "long" + } + } + } + }, + "graph": { + "type": "array", + "items": { + "properties": { + "key": { + "type": "keyword" + }, + "value": { + "type": "long" + } + } + } + }, + "logs": { + "type": "array", + "items": { + "properties": { + "key": { + "type": "keyword" + }, + "value": { + "type": "long" + } + } + } + }, + "metrics": { + "type": "array", + "items": { + "properties": { + "key": { + "type": "keyword" + }, + "value": { + "type": "long" + } + } + } + }, + "infra": { + "type": "array", + "items": { + "properties": { + "key": { + "type": "keyword" + }, + "value": { + "type": "long" + } + } + } + }, + "ingestManager": { + "type": "array", + "items": { + "properties": { + "key": { + "type": "keyword" + }, + "value": { + "type": "long" + } + } + } + }, + "lens": { + "type": "array", + "items": { + "properties": { + "key": { + "type": "keyword" + }, + "value": { + "type": "long" + } + } + } + }, + "maps": { + "type": "array", + "items": { + "properties": { + "key": { + "type": "keyword" + }, + "value": { + "type": "long" + } + } + } + }, + "ml": { + "type": "array", + "items": { + "properties": { + "key": { + "type": "keyword" + }, + "value": { + "type": "long" + } + } + } + }, + "monitoring": { + "type": "array", + "items": { + "properties": { + "key": { + "type": "keyword" + }, + "value": { + "type": "long" + } + } + } + }, + "observability-overview": { + "type": "array", + "items": { + "properties": { + "key": { + "type": "keyword" + }, + "value": { + "type": "long" + } + } + } + }, + "security_account": { + "type": "array", + "items": { + "properties": { + "key": { + "type": "keyword" + }, + "value": { + "type": "long" + } + } + } + }, + "security_access_agreement": { + "type": "array", + "items": { + "properties": { + "key": { + "type": "keyword" + }, + "value": { + "type": "long" + } + } + } + }, + "security_capture_url": { + "type": "array", + "items": { + "properties": { + "key": { + "type": "keyword" + }, + "value": { + "type": "long" + } + } + } + }, + "security_logged_out": { + "type": "array", + "items": { + "properties": { + "key": { + "type": "keyword" + }, + "value": { + "type": "long" + } + } + } + }, + "security_login": { + "type": "array", + "items": { + "properties": { + "key": { + "type": "keyword" + }, + "value": { + "type": "long" + } + } + } + }, + "security_logout": { + "type": "array", + "items": { + "properties": { + "key": { + "type": "keyword" + }, + "value": { + "type": "long" + } + } + } + }, + "security_overwritten_session": { + "type": "array", + "items": { + "properties": { + "key": { + "type": "keyword" + }, + "value": { + "type": "long" + } + } + } + }, + "securitySolution:overview": { + "type": "array", + "items": { + "properties": { + "key": { + "type": "keyword" + }, + "value": { + "type": "long" + } + } + } + }, + "securitySolution:detections": { + "type": "array", + "items": { + "properties": { + "key": { + "type": "keyword" + }, + "value": { + "type": "long" + } + } + } + }, + "securitySolution:hosts": { + "type": "array", + "items": { + "properties": { + "key": { + "type": "keyword" + }, + "value": { + "type": "long" + } + } + } + }, + "securitySolution:network": { + "type": "array", + "items": { + "properties": { + "key": { + "type": "keyword" + }, + "value": { + "type": "long" + } + } + } + }, + "securitySolution:timelines": { + "type": "array", + "items": { + "properties": { + "key": { + "type": "keyword" + }, + "value": { + "type": "long" + } + } + } + }, + "securitySolution:case": { + "type": "array", + "items": { + "properties": { + "key": { + "type": "keyword" + }, + "value": { + "type": "long" + } + } + } + }, + "securitySolution:administration": { + "type": "array", + "items": { + "properties": { + "key": { + "type": "keyword" + }, + "value": { + "type": "long" + } + } + } + }, + "siem": { + "type": "array", + "items": { + "properties": { + "key": { + "type": "keyword" + }, + "value": { + "type": "long" + } + } + } + }, + "space_selector": { + "type": "array", + "items": { + "properties": { + "key": { + "type": "keyword" + }, + "value": { + "type": "long" + } + } + } + }, + "uptime": { + "type": "array", + "items": { + "properties": { + "key": { + "type": "keyword" + }, + "value": { + "type": "long" + } + } + } + } + } + }, "telemetry": { "properties": { "opt_in_status": { @@ -1310,12 +2610,169 @@ } } }, + "static_telemetry": { + "properties": { + "ece": { + "properties": { + "kb_uuid": { + "type": "keyword" + }, + "es_uuid": { + "type": "keyword" + }, + "account_id": { + "type": "keyword" + }, + "license": { + "properties": { + "uuid": { + "type": "keyword" + }, + "type": { + "type": "keyword" + }, + "issued_to": { + "type": "text" + }, + "issuer": { + "type": "text" + }, + "issue_date_in_millis": { + "type": "long" + }, + "start_date_in_millis": { + "type": "long" + }, + "expiry_date_in_millis": { + "type": "long" + }, + "max_resource_units": { + "type": "long" + } + } + } + } + }, + "ess": { + "properties": { + "kb_uuid": { + "type": "keyword" + }, + "es_uuid": { + "type": "keyword" + }, + "account_id": { + "type": "keyword" + }, + "license": { + "properties": { + "uuid": { + "type": "keyword" + }, + "type": { + "type": "keyword" + }, + "issued_to": { + "type": "text" + }, + "issuer": { + "type": "text" + }, + "issue_date_in_millis": { + "type": "long" + }, + "start_date_in_millis": { + "type": "long" + }, + "expiry_date_in_millis": { + "type": "long" + }, + "max_resource_units": { + "type": "long" + } + } + } + } + }, + "eck": { + "properties": { + "operator_uuid": { + "type": "keyword" + }, + "operator_roles": { + "type": "keyword" + }, + "custom_operator_namespace": { + "type": "boolean" + }, + "distribution": { + "type": "text" + }, + "build": { + "properties": { + "hash": { + "type": "text" + }, + "date": { + "type": "date" + }, + "version": { + "type": "keyword" + } + } + } + } + } + } + }, "tsvb-validation": { "properties": { "failed_validations": { "type": "long" } } + }, + "vis_type_vega": { + "properties": { + "vega_lib_specs_total": { + "type": "long" + }, + "vega_lite_lib_specs_total": { + "type": "long" + }, + "vega_use_map_total": { + "type": "long" + } + } + }, + "visualization_types": { + "properties": { + "DYNAMIC_KEY": { + "properties": { + "total": { + "type": "long" + }, + "spaces_min": { + "type": "long" + }, + "spaces_max": { + "type": "long" + }, + "spaces_avg": { + "type": "long" + }, + "saved_7_days_total": { + "type": "long" + }, + "saved_30_days_total": { + "type": "long" + }, + "saved_90_days_total": { + "type": "long" + } + } + } + } } } } diff --git a/src/plugins/telemetry/server/collectors/usage/schema.ts b/src/plugins/telemetry/server/collectors/usage/schema.ts new file mode 100644 index 0000000000000..4bfb6f75c7c8f --- /dev/null +++ b/src/plugins/telemetry/server/collectors/usage/schema.ts @@ -0,0 +1,58 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { MakeSchemaFrom } from 'src/plugins/usage_collection/server'; +import { LicenseUsage, StaticTelemetryUsage } from './telemetry_usage_collector'; + +const licenseSchema: MakeSchemaFrom = { + uuid: { type: 'keyword' }, + type: { type: 'keyword' }, + issued_to: { type: 'text' }, + issuer: { type: 'text' }, + issue_date_in_millis: { type: 'long' }, + start_date_in_millis: { type: 'long' }, + expiry_date_in_millis: { type: 'long' }, + max_resource_units: { type: 'long' }, +}; + +export const staticTelemetrySchema: MakeSchemaFrom = { + ece: { + kb_uuid: { type: 'keyword' }, + es_uuid: { type: 'keyword' }, + account_id: { type: 'keyword' }, + license: licenseSchema, + }, + ess: { + kb_uuid: { type: 'keyword' }, + es_uuid: { type: 'keyword' }, + account_id: { type: 'keyword' }, + license: licenseSchema, + }, + eck: { + operator_uuid: { type: 'keyword' }, + operator_roles: { type: 'keyword' }, + custom_operator_namespace: { type: 'boolean' }, + distribution: { type: 'text' }, + build: { + hash: { type: 'text' }, + date: { type: 'date' }, + version: { type: 'keyword' }, + }, + }, +}; diff --git a/src/plugins/telemetry/server/collectors/usage/telemetry_usage_collector.ts b/src/plugins/telemetry/server/collectors/usage/telemetry_usage_collector.ts index bde7cfa5c4445..39f8ef0151a0b 100644 --- a/src/plugins/telemetry/server/collectors/usage/telemetry_usage_collector.ts +++ b/src/plugins/telemetry/server/collectors/usage/telemetry_usage_collector.ts @@ -29,6 +29,7 @@ import { TelemetryConfigType } from '../../config'; // look for telemetry.yml in the same places we expect kibana.yml import { ensureDeepObject } from './ensure_deep_object'; +import { staticTelemetrySchema } from './schema'; /** * The maximum file size before we ignore it (note: this limit is arbitrary). @@ -60,10 +61,12 @@ export function isFileReadable(path: string): boolean { * @param configPath The config file path. * @returns The unmodified JSON object if the file exists and is a valid YAML file. */ -export async function readTelemetryFile(path: string): Promise { +export async function readTelemetryFile( + configPath: string +): Promise { try { - if (isFileReadable(path)) { - const yaml = readFileSync(path); + if (isFileReadable(configPath)) { + const yaml = readFileSync(configPath); const data = safeLoad(yaml.toString()); // don't bother returning empty objects @@ -79,11 +82,48 @@ export async function readTelemetryFile(path: string): Promise Promise ) { - return usageCollection.makeUsageCollector({ + return usageCollection.makeUsageCollector({ type: 'static_telemetry', isReady: () => true, fetch: async () => { @@ -91,6 +131,7 @@ export function createTelemetryUsageCollector( const telemetryPath = join(dirname(configPath), 'telemetry.yml'); return await readTelemetryFile(telemetryPath); }, + schema: staticTelemetrySchema, }); } diff --git a/src/plugins/telemetry/server/fetcher.test.ts b/src/plugins/telemetry/server/fetcher.test.ts index 245adf59799cc..45712df772e1c 100644 --- a/src/plugins/telemetry/server/fetcher.test.ts +++ b/src/plugins/telemetry/server/fetcher.test.ts @@ -23,19 +23,93 @@ import { coreMock } from '../../../core/server/mocks'; describe('FetcherTask', () => { describe('sendIfDue', () => { - it('returns undefined and warns when it fails to get telemetry configs', async () => { + it('stops when it fails to get telemetry configs', async () => { const initializerContext = coreMock.createPluginInitializerContext({}); const fetcherTask = new FetcherTask(initializerContext); const mockError = new Error('Some message.'); - fetcherTask['getCurrentConfigs'] = async () => { - throw mockError; - }; + const getCurrentConfigs = jest.fn().mockRejectedValue(mockError); + const fetchTelemetry = jest.fn(); + const sendTelemetry = jest.fn(); + Object.assign(fetcherTask, { + getCurrentConfigs, + fetchTelemetry, + sendTelemetry, + }); const result = await fetcherTask['sendIfDue'](); expect(result).toBe(undefined); + expect(getCurrentConfigs).toBeCalledTimes(1); + expect(fetchTelemetry).toBeCalledTimes(0); + expect(sendTelemetry).toBeCalledTimes(0); expect(fetcherTask['logger'].warn).toBeCalledTimes(1); expect(fetcherTask['logger'].warn).toHaveBeenCalledWith( - `Error fetching telemetry configs: ${mockError}` + `Error getting telemetry configs. (${mockError})` ); }); + + it('stops when all collectors are not ready', async () => { + const initializerContext = coreMock.createPluginInitializerContext({}); + const fetcherTask = new FetcherTask(initializerContext); + const getCurrentConfigs = jest.fn().mockResolvedValue({}); + const areAllCollectorsReady = jest.fn().mockResolvedValue(false); + const shouldSendReport = jest.fn().mockReturnValue(true); + const fetchTelemetry = jest.fn(); + const sendTelemetry = jest.fn(); + const updateReportFailure = jest.fn(); + + Object.assign(fetcherTask, { + getCurrentConfigs, + areAllCollectorsReady, + shouldSendReport, + fetchTelemetry, + updateReportFailure, + sendTelemetry, + }); + + await fetcherTask['sendIfDue'](); + + expect(fetchTelemetry).toBeCalledTimes(0); + expect(sendTelemetry).toBeCalledTimes(0); + + expect(areAllCollectorsReady).toBeCalledTimes(1); + expect(updateReportFailure).toBeCalledTimes(0); + expect(fetcherTask['logger'].warn).toBeCalledTimes(1); + expect(fetcherTask['logger'].warn).toHaveBeenCalledWith( + `Error fetching usage. (Error: Not all collectors are ready.)` + ); + }); + + it('fetches usage and send telemetry', async () => { + const initializerContext = coreMock.createPluginInitializerContext({}); + const fetcherTask = new FetcherTask(initializerContext); + const mockTelemetryUrl = 'mock_telemetry_url'; + const mockClusters = ['cluster_1', 'cluster_2']; + const getCurrentConfigs = jest.fn().mockResolvedValue({ + telemetryUrl: mockTelemetryUrl, + }); + const areAllCollectorsReady = jest.fn().mockResolvedValue(true); + const shouldSendReport = jest.fn().mockReturnValue(true); + + const fetchTelemetry = jest.fn().mockResolvedValue(mockClusters); + const sendTelemetry = jest.fn(); + const updateReportFailure = jest.fn(); + + Object.assign(fetcherTask, { + getCurrentConfigs, + areAllCollectorsReady, + shouldSendReport, + fetchTelemetry, + updateReportFailure, + sendTelemetry, + }); + + await fetcherTask['sendIfDue'](); + + expect(areAllCollectorsReady).toBeCalledTimes(1); + expect(fetchTelemetry).toBeCalledTimes(1); + expect(sendTelemetry).toBeCalledTimes(2); + expect(sendTelemetry).toHaveBeenNthCalledWith(1, mockTelemetryUrl, mockClusters[0]); + expect(sendTelemetry).toHaveBeenNthCalledWith(2, mockTelemetryUrl, mockClusters[1]); + expect(updateReportFailure).toBeCalledTimes(0); + }); }); }); diff --git a/src/plugins/telemetry/server/fetcher.ts b/src/plugins/telemetry/server/fetcher.ts index 75cfac721bcd3..fadfc01f628f5 100644 --- a/src/plugins/telemetry/server/fetcher.ts +++ b/src/plugins/telemetry/server/fetcher.ts @@ -18,11 +18,14 @@ */ import moment from 'moment'; -import { Observable } from 'rxjs'; +import { Observable, Subscription, timer } from 'rxjs'; import { take } from 'rxjs/operators'; // @ts-ignore import fetch from 'node-fetch'; -import { TelemetryCollectionManagerPluginStart } from 'src/plugins/telemetry_collection_manager/server'; +import { + TelemetryCollectionManagerPluginStart, + UsageStatsPayload, +} from 'src/plugins/telemetry_collection_manager/server'; import { PluginInitializerContext, Logger, @@ -58,7 +61,7 @@ export class FetcherTask { private readonly config$: Observable; private readonly currentKibanaVersion: string; private readonly logger: Logger; - private intervalId?: NodeJS.Timeout; + private intervalId?: Subscription; private lastReported?: number; private isSending = false; private internalRepository?: SavedObjectsClientContract; @@ -79,21 +82,24 @@ export class FetcherTask { this.telemetryCollectionManager = telemetryCollectionManager; this.elasticsearchClient = elasticsearch.legacy.createClient('telemetry-fetcher'); - setTimeout(() => { - this.sendIfDue(); - this.intervalId = setInterval(() => this.sendIfDue(), this.checkIntervalMs); - }, this.initialCheckDelayMs); + this.intervalId = timer(this.initialCheckDelayMs, this.checkIntervalMs).subscribe(() => + this.sendIfDue() + ); } public stop() { if (this.intervalId) { - clearInterval(this.intervalId); + this.intervalId.unsubscribe(); } if (this.elasticsearchClient) { this.elasticsearchClient.close(); } } + private async areAllCollectorsReady() { + return (await this.telemetryCollectionManager?.areAllCollectorsReady()) ?? false; + } + private async sendIfDue() { if (this.isSending) { return; @@ -103,7 +109,7 @@ export class FetcherTask { try { telemetryConfig = await this.getCurrentConfigs(); } catch (err) { - this.logger.warn(`Error fetching telemetry configs: ${err}`); + this.logger.warn(`Error getting telemetry configs. (${err})`); return; } @@ -111,9 +117,22 @@ export class FetcherTask { return; } + let clusters: Array = []; + this.isSending = true; + + try { + const allCollectorsReady = await this.areAllCollectorsReady(); + if (!allCollectorsReady) { + throw new Error('Not all collectors are ready.'); + } + clusters = await this.fetchTelemetry(); + } catch (err) { + this.logger.warn(`Error fetching usage. (${err})`); + this.isSending = false; + return; + } + try { - this.isSending = true; - const clusters = await this.fetchTelemetry(); const { telemetryUrl } = telemetryConfig; for (const cluster of clusters) { await this.sendTelemetry(telemetryUrl, cluster); @@ -123,7 +142,7 @@ export class FetcherTask { } catch (err) { await this.updateReportFailure(telemetryConfig); - this.logger.warn(`Error sending telemetry usage data: ${err}`); + this.logger.warn(`Error sending telemetry usage data. (${err})`); } this.isSending = false; } diff --git a/src/plugins/telemetry/server/plugin.ts b/src/plugins/telemetry/server/plugin.ts index 005c5f96d98d0..b423cbb07ba32 100644 --- a/src/plugins/telemetry/server/plugin.ts +++ b/src/plugins/telemetry/server/plugin.ts @@ -18,7 +18,7 @@ */ import { URL } from 'url'; -import { Observable } from 'rxjs'; +import { AsyncSubject, Observable } from 'rxjs'; import { UsageCollectionSetup } from 'src/plugins/usage_collection/server'; import { TelemetryCollectionManagerPluginSetup, @@ -30,10 +30,11 @@ import { PluginInitializerContext, ISavedObjectsRepository, CoreStart, - IUiSettingsClient, SavedObjectsClient, Plugin, Logger, + IClusterClient, + UiSettingsServiceStart, } from '../../../core/server'; import { registerRoutes } from './routes'; import { registerCollection } from './telemetry_collection'; @@ -81,8 +82,12 @@ export class TelemetryPlugin implements Plugin; private readonly isDev: boolean; private readonly fetcherTask: FetcherTask; + /** + * @private Used to mark the completion of the old UI Settings migration + */ + private readonly oldUiSettingsHandled$ = new AsyncSubject(); private savedObjectsClient?: ISavedObjectsRepository; - private uiSettingsClient?: IUiSettingsClient; + private elasticsearchClient?: IClusterClient; constructor(initializerContext: PluginInitializerContext) { this.logger = initializerContext.logger.get(); @@ -95,15 +100,18 @@ export class TelemetryPlugin implements Plugin { + ): TelemetryPluginSetup { const currentKibanaVersion = this.currentKibanaVersion; const config$ = this.config$; const isDev = this.isDev; - - registerCollection(telemetryCollectionManager, elasticsearch.legacy.client); + registerCollection( + telemetryCollectionManager, + elasticsearch.legacy.client, + () => this.elasticsearchClient + ); const router = http.createRouter(); registerRoutes({ @@ -126,27 +134,21 @@ export class TelemetryPlugin implements Plugin { - const { savedObjects, uiSettings } = core; - this.savedObjectsClient = savedObjects.createInternalRepository(); - const savedObjectsClient = new SavedObjectsClient(this.savedObjectsClient); - this.uiSettingsClient = uiSettings.asScopedToClient(savedObjectsClient); + public start(core: CoreStart, { telemetryCollectionManager }: TelemetryPluginsDepsStart) { + const { savedObjects, uiSettings, elasticsearch } = core; + const savedObjectsInternalRepository = savedObjects.createInternalRepository(); + this.savedObjectsClient = savedObjectsInternalRepository; + this.elasticsearchClient = elasticsearch.client; - try { - await handleOldSettings(savedObjectsClient, this.uiSettingsClient); - } catch (error) { - this.logger.warn('Unable to update legacy telemetry configs.'); - } - - this.fetcherTask.start(core, { telemetryCollectionManager }); + // Not catching nor awaiting these promises because they should never reject + this.handleOldUiSettings(uiSettings); + this.startFetcherWhenOldSettingsAreHandled(core, telemetryCollectionManager); return { getIsOptedIn: async () => { - const internalRepository = new SavedObjectsClient(savedObjects.createInternalRepository()); - const telemetrySavedObject = await getTelemetrySavedObject(internalRepository!); + await this.oldUiSettingsHandled$.pipe(take(1)).toPromise(); // Wait for the old settings to be handled + const internalRepository = new SavedObjectsClient(savedObjectsInternalRepository); + const telemetrySavedObject = await getTelemetrySavedObject(internalRepository); const config = await this.config$.pipe(take(1)).toPromise(); const allowChangingOptInStatus = config.allowChangingOptInStatus; const configTelemetryOptIn = typeof config.optIn === 'undefined' ? null : config.optIn; @@ -163,6 +165,27 @@ export class TelemetryPlugin implements Plugin { - it('uses callCluster to get info API', () => { - const callCluster = sinon.stub(); - const response = Promise.resolve({}); - - mockGetClusterInfo(callCluster, response); - - expect(getClusterInfo(callCluster)).to.be(response); - }); -}); diff --git a/src/plugins/telemetry/server/telemetry_collection/__tests__/get_cluster_stats.js b/src/plugins/telemetry/server/telemetry_collection/__tests__/get_cluster_stats.js deleted file mode 100644 index d1354608385f6..0000000000000 --- a/src/plugins/telemetry/server/telemetry_collection/__tests__/get_cluster_stats.js +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import expect from '@kbn/expect'; -import sinon from 'sinon'; - -import { TIMEOUT } from '../constants'; -import { getClusterStats } from '../get_cluster_stats'; - -export function mockGetClusterStats(callCluster, clusterStats, req) { - callCluster - .withArgs(req, 'cluster.stats', { - timeout: TIMEOUT, - }) - .returns(clusterStats); - - callCluster - .withArgs('cluster.stats', { - timeout: TIMEOUT, - }) - .returns(clusterStats); -} - -describe.skip('get_cluster_stats', () => { - it('uses callCluster to get cluster.stats API', async () => { - const callCluster = sinon.stub(); - const response = Promise.resolve({}); - - mockGetClusterStats(callCluster, response); - - expect(getClusterStats(callCluster)).to.be(response); - }); -}); diff --git a/src/plugins/telemetry/server/telemetry_collection/__tests__/get_local_stats.js b/src/plugins/telemetry/server/telemetry_collection/__tests__/get_local_stats.js deleted file mode 100644 index 8541745faea3b..0000000000000 --- a/src/plugins/telemetry/server/telemetry_collection/__tests__/get_local_stats.js +++ /dev/null @@ -1,267 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import expect from '@kbn/expect'; -import sinon from 'sinon'; -import { merge, omit } from 'lodash'; - -import { TIMEOUT } from '../constants'; -import { mockGetClusterInfo } from './get_cluster_info'; -import { mockGetClusterStats } from './get_cluster_stats'; - -import { getLocalStats, handleLocalStats } from '../get_local_stats'; - -const mockUsageCollection = (kibanaUsage = {}) => ({ - bulkFetch: () => kibanaUsage, - toObject: (data) => data, -}); - -const getMockServer = (getCluster = sinon.stub()) => ({ - log(tags, message) { - console.log({ tags, message }); - }, - config() { - return { - get(item) { - switch (item) { - case 'pkg.version': - return '8675309-snapshot'; - default: - throw Error(`unexpected config.get('${item}') received.`); - } - }, - }; - }, - plugins: { - elasticsearch: { getCluster }, - }, -}); -function mockGetNodesUsage(callCluster, nodesUsage, req) { - callCluster - .withArgs( - req, - { - method: 'GET', - path: '/_nodes/usage', - query: { - timeout: TIMEOUT, - }, - }, - 'transport.request' - ) - .returns(nodesUsage); -} - -function mockGetLocalStats(callCluster, clusterInfo, clusterStats, nodesUsage, req) { - mockGetClusterInfo(callCluster, clusterInfo, req); - mockGetClusterStats(callCluster, clusterStats, req); - mockGetNodesUsage(callCluster, nodesUsage, req); -} - -describe('get_local_stats', () => { - const clusterUuid = 'abc123'; - const clusterName = 'my-cool-cluster'; - const version = '2.3.4'; - const clusterInfo = { - cluster_uuid: clusterUuid, - cluster_name: clusterName, - version: { - number: version, - }, - }; - const nodesUsage = [ - { - node_id: 'some_node_id', - timestamp: 1588617023177, - since: 1588616945163, - rest_actions: { - nodes_usage_action: 1, - create_index_action: 1, - document_get_action: 1, - search_action: 19, - nodes_info_action: 36, - }, - aggregations: { - terms: { - bytes: 2, - }, - scripted_metric: { - other: 7, - }, - }, - }, - ]; - const clusterStats = { - _nodes: { failed: 123 }, - cluster_name: 'real-cool', - indices: { totally: 456 }, - nodes: { yup: 'abc' }, - random: 123, - }; - - const kibana = { - kibana: { - great: 'googlymoogly', - versions: [{ version: '8675309', count: 1 }], - }, - kibana_stats: { - os: { - platform: 'rocky', - platformRelease: 'iv', - }, - }, - localization: { - locale: 'en', - labelsCount: 0, - integrities: {}, - }, - sun: { chances: 5 }, - clouds: { chances: 95 }, - rain: { chances: 2 }, - snow: { chances: 0 }, - }; - - const clusterStatsWithNodesUsage = { - ...clusterStats, - nodes: merge(clusterStats.nodes, { usage: nodesUsage }), - }; - const combinedStatsResult = { - collection: 'local', - cluster_uuid: clusterUuid, - cluster_name: clusterName, - version, - cluster_stats: omit(clusterStatsWithNodesUsage, '_nodes', 'cluster_name'), - stack_stats: { - kibana: { - great: 'googlymoogly', - count: 1, - indices: 1, - os: { - platforms: [{ platform: 'rocky', count: 1 }], - platformReleases: [{ platformRelease: 'iv', count: 1 }], - }, - versions: [{ version: '8675309', count: 1 }], - plugins: { - localization: { - locale: 'en', - labelsCount: 0, - integrities: {}, - }, - sun: { chances: 5 }, - clouds: { chances: 95 }, - rain: { chances: 2 }, - snow: { chances: 0 }, - }, - }, - }, - }; - - const context = { - logger: console, - version: '8.0.0', - }; - - describe('handleLocalStats', () => { - it('returns expected object without xpack and kibana data', () => { - const result = handleLocalStats( - clusterInfo, - clusterStatsWithNodesUsage, - void 0, - void 0, - context - ); - expect(result.cluster_uuid).to.eql(combinedStatsResult.cluster_uuid); - expect(result.cluster_name).to.eql(combinedStatsResult.cluster_name); - expect(result.cluster_stats).to.eql(combinedStatsResult.cluster_stats); - expect(result.version).to.be('2.3.4'); - expect(result.collection).to.be('local'); - expect(result.license).to.be(undefined); - expect(result.stack_stats).to.eql({ kibana: undefined, data: undefined }); - }); - - it('returns expected object with xpack', () => { - const result = handleLocalStats( - clusterInfo, - clusterStatsWithNodesUsage, - void 0, - void 0, - context - ); - const { stack_stats: stack, ...cluster } = result; - expect(cluster.collection).to.be(combinedStatsResult.collection); - expect(cluster.cluster_uuid).to.be(combinedStatsResult.cluster_uuid); - expect(cluster.cluster_name).to.be(combinedStatsResult.cluster_name); - expect(stack.kibana).to.be(undefined); // not mocked for this test - expect(stack.data).to.be(undefined); // not mocked for this test - - expect(cluster.version).to.eql(combinedStatsResult.version); - expect(cluster.cluster_stats).to.eql(combinedStatsResult.cluster_stats); - expect(cluster.license).to.eql(combinedStatsResult.license); - expect(stack.xpack).to.eql(combinedStatsResult.stack_stats.xpack); - }); - }); - - describe.skip('getLocalStats', () => { - it('returns expected object without xpack data when X-Pack fails to respond', async () => { - const callClusterUsageFailed = sinon.stub(); - const usageCollection = mockUsageCollection(); - mockGetLocalStats( - callClusterUsageFailed, - Promise.resolve(clusterInfo), - Promise.resolve(clusterStats), - Promise.resolve(nodesUsage) - ); - const result = await getLocalStats([], { - server: getMockServer(), - callCluster: callClusterUsageFailed, - usageCollection, - }); - expect(result.cluster_uuid).to.eql(combinedStatsResult.cluster_uuid); - expect(result.cluster_name).to.eql(combinedStatsResult.cluster_name); - expect(result.cluster_stats).to.eql(combinedStatsResult.cluster_stats); - expect(result.cluster_stats.nodes).to.eql(combinedStatsResult.cluster_stats.nodes); - expect(result.version).to.be('2.3.4'); - expect(result.collection).to.be('local'); - - // license and xpack usage info come from the same cluster call - expect(result.license).to.be(undefined); - expect(result.stack_stats.xpack).to.be(undefined); - }); - - it('returns expected object with xpack and kibana data', async () => { - const callCluster = sinon.stub(); - const usageCollection = mockUsageCollection(kibana); - mockGetLocalStats( - callCluster, - Promise.resolve(clusterInfo), - Promise.resolve(clusterStats), - Promise.resolve(nodesUsage) - ); - - const result = await getLocalStats([], { - server: getMockServer(callCluster), - usageCollection, - callCluster, - }); - - expect(result.stack_stats.xpack).to.eql(combinedStatsResult.stack_stats.xpack); - expect(result.stack_stats.kibana).to.eql(combinedStatsResult.stack_stats.kibana); - }); - }); -}); diff --git a/src/plugins/telemetry/server/telemetry_collection/get_cluster_info.test.ts b/src/plugins/telemetry/server/telemetry_collection/get_cluster_info.test.ts new file mode 100644 index 0000000000000..459b18d252e17 --- /dev/null +++ b/src/plugins/telemetry/server/telemetry_collection/get_cluster_info.test.ts @@ -0,0 +1,57 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { elasticsearchServiceMock } from '../../../../../src/core/server/mocks'; +import { getClusterInfo } from './get_cluster_info'; + +export function mockGetClusterInfo(clusterInfo: any) { + const esClient = elasticsearchServiceMock.createClusterClient().asInternalUser; + esClient.info + // @ts-ignore we only care about the response body + .mockResolvedValue( + // @ts-ignore we only care about the response body + { + body: { ...clusterInfo }, + } + ); + return esClient; +} + +describe('get_cluster_info using the elasticsearch client', () => { + it('uses the esClient to get info API', async () => { + const clusterInfo = { + cluster_uuid: '1234', + cluster_name: 'testCluster', + version: { + number: '7.9.2', + build_flavor: 'default', + build_type: 'docker', + build_hash: 'b5ca9c58fb664ca8bf', + build_date: '2020-07-21T16:40:44.668009Z', + build_snapshot: false, + lucene_version: '8.5.1', + minimum_wire_compatibility_version: '6.8.0', + minimum_index_compatibility_version: '6.0.0-beta1', + }, + }; + const esClient = mockGetClusterInfo(clusterInfo); + + expect(await getClusterInfo(esClient)).toStrictEqual(clusterInfo); + }); +}); diff --git a/src/plugins/telemetry/server/telemetry_collection/get_cluster_info.ts b/src/plugins/telemetry/server/telemetry_collection/get_cluster_info.ts index 4a33356ee9761..407f3325c3a9f 100644 --- a/src/plugins/telemetry/server/telemetry_collection/get_cluster_info.ts +++ b/src/plugins/telemetry/server/telemetry_collection/get_cluster_info.ts @@ -17,7 +17,7 @@ * under the License. */ -import { LegacyAPICaller } from 'kibana/server'; +import { ElasticsearchClient } from 'src/core/server'; // This can be removed when the ES client improves the types export interface ESClusterInfo { @@ -25,24 +25,24 @@ export interface ESClusterInfo { cluster_name: string; version: { number: string; - build_flavor: string; - build_type: string; - build_hash: string; - build_date: string; + build_flavor?: string; + build_type?: string; + build_hash?: string; + build_date?: string; build_snapshot?: boolean; - lucene_version: string; - minimum_wire_compatibility_version: string; - minimum_index_compatibility_version: string; + lucene_version?: string; + minimum_wire_compatibility_version?: string; + minimum_index_compatibility_version?: string; }; } - /** * Get the cluster info from the connected cluster. * * This is the equivalent to GET / * - * @param {function} callCluster The callWithInternalUser handler (exposed for testing) + * @param {function} esClient The asInternalUser handler (exposed for testing) */ -export function getClusterInfo(callCluster: LegacyAPICaller) { - return callCluster('info'); +export async function getClusterInfo(esClient: ElasticsearchClient) { + const { body } = await esClient.info(); + return body; } diff --git a/src/plugins/telemetry/server/telemetry_collection/get_cluster_stats.test.ts b/src/plugins/telemetry/server/telemetry_collection/get_cluster_stats.test.ts new file mode 100644 index 0000000000000..81551c0c4d93d --- /dev/null +++ b/src/plugins/telemetry/server/telemetry_collection/get_cluster_stats.test.ts @@ -0,0 +1,44 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { elasticsearchServiceMock } from '../../../../../src/core/server/mocks'; +import { getClusterStats } from './get_cluster_stats'; +import { TIMEOUT } from './constants'; + +export function mockGetClusterStats(clusterStats: any) { + const esClient = elasticsearchServiceMock.createClusterClient().asInternalUser; + esClient.cluster.stats.mockResolvedValue(clusterStats); + return esClient; +} + +describe('get_cluster_stats', () => { + it('uses the esClient to get the response from the `cluster.stats` API', async () => { + const response = Promise.resolve({ body: { cluster_uuid: '1234' } }); + const esClient = elasticsearchServiceMock.createClusterClient().asInternalUser; + esClient.cluster.stats.mockImplementationOnce( + // @ts-ignore the method only cares about the response body + async (_params = { timeout: TIMEOUT }) => { + return response; + } + ); + const result = getClusterStats(esClient); + expect(esClient.cluster.stats).toHaveBeenCalledWith({ timeout: TIMEOUT }); + expect(result).toStrictEqual(response); + }); +}); diff --git a/src/plugins/telemetry/server/telemetry_collection/get_cluster_stats.ts b/src/plugins/telemetry/server/telemetry_collection/get_cluster_stats.ts index d7c0110a99c6f..d2a64e4878679 100644 --- a/src/plugins/telemetry/server/telemetry_collection/get_cluster_stats.ts +++ b/src/plugins/telemetry/server/telemetry_collection/get_cluster_stats.ts @@ -18,23 +18,23 @@ */ import { ClusterDetailsGetter } from 'src/plugins/telemetry_collection_manager/server'; -import { LegacyAPICaller } from 'kibana/server'; +import { ElasticsearchClient } from 'src/core/server'; import { TIMEOUT } from './constants'; /** * Get the cluster stats from the connected cluster. * * This is the equivalent to GET /_cluster/stats?timeout=30s. */ -export async function getClusterStats(callCluster: LegacyAPICaller) { - return await callCluster('cluster.stats', { - timeout: TIMEOUT, - }); +export async function getClusterStats(esClient: ElasticsearchClient) { + const { body } = await esClient.cluster.stats({ timeout: TIMEOUT }); + return body; } /** * Get the cluster uuids from the connected cluster. */ -export const getClusterUuids: ClusterDetailsGetter = async ({ callCluster }) => { - const result = await getClusterStats(callCluster); - return [{ clusterUuid: result.cluster_uuid }]; +export const getClusterUuids: ClusterDetailsGetter = async ({ esClient }) => { + const { body } = await esClient.cluster.stats({ timeout: TIMEOUT }); + + return [{ clusterUuid: body.cluster_uuid }]; }; diff --git a/src/plugins/telemetry/server/telemetry_collection/get_data_telemetry/get_data_telemetry.test.ts b/src/plugins/telemetry/server/telemetry_collection/get_data_telemetry/get_data_telemetry.test.ts index dee718decdc1f..bb5eb7f6b726d 100644 --- a/src/plugins/telemetry/server/telemetry_collection/get_data_telemetry/get_data_telemetry.test.ts +++ b/src/plugins/telemetry/server/telemetry_collection/get_data_telemetry/get_data_telemetry.test.ts @@ -19,6 +19,7 @@ import { buildDataTelemetryPayload, getDataTelemetry } from './get_data_telemetry'; import { DATA_DATASETS_INDEX_PATTERNS, DATA_DATASETS_INDEX_PATTERNS_UNIQUE } from './constants'; +import { elasticsearchServiceMock } from '../../../../../../src/core/server/mocks'; describe('get_data_telemetry', () => { describe('DATA_DATASETS_INDEX_PATTERNS', () => { @@ -195,13 +196,15 @@ describe('get_data_telemetry', () => { describe('getDataTelemetry', () => { test('it returns the base payload (all 0s) because no indices are found', async () => { - const callCluster = mockCallCluster(); - await expect(getDataTelemetry(callCluster)).resolves.toStrictEqual([]); + const esClient = mockEsClient(); + await expect(getDataTelemetry(esClient)).resolves.toStrictEqual([]); + expect(esClient.indices.getMapping).toHaveBeenCalledTimes(1); + expect(esClient.indices.stats).toHaveBeenCalledTimes(1); }); test('can only see the index mappings, but not the stats', async () => { - const callCluster = mockCallCluster(['filebeat-12314']); - await expect(getDataTelemetry(callCluster)).resolves.toStrictEqual([ + const esClient = mockEsClient(['filebeat-12314']); + await expect(getDataTelemetry(esClient)).resolves.toStrictEqual([ { pattern_name: 'filebeat', shipper: 'filebeat', @@ -209,10 +212,12 @@ describe('get_data_telemetry', () => { ecs_index_count: 0, }, ]); + expect(esClient.indices.getMapping).toHaveBeenCalledTimes(1); + expect(esClient.indices.stats).toHaveBeenCalledTimes(1); }); test('can see the mappings and the stats', async () => { - const callCluster = mockCallCluster( + const esClient = mockEsClient( ['filebeat-12314'], { isECS: true }, { @@ -221,7 +226,7 @@ describe('get_data_telemetry', () => { }, } ); - await expect(getDataTelemetry(callCluster)).resolves.toStrictEqual([ + await expect(getDataTelemetry(esClient)).resolves.toStrictEqual([ { pattern_name: 'filebeat', shipper: 'filebeat', @@ -234,7 +239,7 @@ describe('get_data_telemetry', () => { }); test('find an index that does not match any index pattern but has mappings metadata', async () => { - const callCluster = mockCallCluster( + const esClient = mockEsClient( ['cannot_match_anything'], { isECS: true, dataStreamType: 'traces', shipper: 'my-beat' }, { @@ -245,7 +250,7 @@ describe('get_data_telemetry', () => { }, } ); - await expect(getDataTelemetry(callCluster)).resolves.toStrictEqual([ + await expect(getDataTelemetry(esClient)).resolves.toStrictEqual([ { data_stream: { dataset: undefined, type: 'traces' }, shipper: 'my-beat', @@ -258,45 +263,51 @@ describe('get_data_telemetry', () => { }); test('return empty array when there is an error', async () => { - const callCluster = jest.fn().mockRejectedValue(new Error('Something went terribly wrong')); - await expect(getDataTelemetry(callCluster)).resolves.toStrictEqual([]); + const esClient = elasticsearchServiceMock.createClusterClient().asInternalUser; + esClient.indices.getMapping.mockRejectedValue(new Error('Something went terribly wrong')); + esClient.indices.stats.mockRejectedValue(new Error('Something went terribly wrong')); + await expect(getDataTelemetry(esClient)).resolves.toStrictEqual([]); }); }); }); - -function mockCallCluster( - indicesMappings: string[] = [], +function mockEsClient( + indicesMappings: string[] = [], // an array of `indices` to get mappings from. { isECS = false, dataStreamDataset = '', dataStreamType = '', shipper = '' } = {}, indexStats: any = {} ) { - return jest.fn().mockImplementation(async (method: string, opts: any) => { - if (method === 'indices.getMapping') { - return Object.fromEntries( - indicesMappings.map((index) => [ - index, - { - mappings: { - ...(shipper && { _meta: { beat: shipper } }), - properties: { - ...(isECS && { ecs: { properties: { version: { type: 'keyword' } } } }), - ...((dataStreamType || dataStreamDataset) && { - data_stream: { - properties: { - ...(dataStreamDataset && { - dataset: { type: 'constant_keyword', value: dataStreamDataset }, - }), - ...(dataStreamType && { - type: { type: 'constant_keyword', value: dataStreamType }, - }), - }, + const esClient = elasticsearchServiceMock.createClusterClient().asInternalUser; + // @ts-ignore + esClient.indices.getMapping.mockImplementationOnce(async () => { + const body = Object.fromEntries( + indicesMappings.map((index) => [ + index, + { + mappings: { + ...(shipper && { _meta: { beat: shipper } }), + properties: { + ...(isECS && { ecs: { properties: { version: { type: 'keyword' } } } }), + ...((dataStreamType || dataStreamDataset) && { + data_stream: { + properties: { + ...(dataStreamDataset && { + dataset: { type: 'constant_keyword', value: dataStreamDataset }, + }), + ...(dataStreamType && { + type: { type: 'constant_keyword', value: dataStreamType }, + }), }, - }), - }, + }, + }), }, }, - ]) - ); - } - return indexStats; + }, + ]) + ); + return { body }; + }); + // @ts-ignore + esClient.indices.stats.mockImplementationOnce(async () => { + return { body: indexStats }; }); + return esClient; } diff --git a/src/plugins/telemetry/server/telemetry_collection/get_data_telemetry/get_data_telemetry.ts b/src/plugins/telemetry/server/telemetry_collection/get_data_telemetry/get_data_telemetry.ts index f4734dde251cc..67769793cbfdf 100644 --- a/src/plugins/telemetry/server/telemetry_collection/get_data_telemetry/get_data_telemetry.ts +++ b/src/plugins/telemetry/server/telemetry_collection/get_data_telemetry/get_data_telemetry.ts @@ -16,8 +16,8 @@ * specific language governing permissions and limitations * under the License. */ +import { ElasticsearchClient } from 'src/core/server'; -import { LegacyAPICaller } from 'kibana/server'; import { DATA_DATASETS_INDEX_PATTERNS_UNIQUE, DataPatternName, @@ -224,42 +224,50 @@ interface IndexMappings { }; } -export async function getDataTelemetry(callCluster: LegacyAPICaller) { +export async function getDataTelemetry(esClient: ElasticsearchClient) { try { const index = [ ...DATA_DATASETS_INDEX_PATTERNS_UNIQUE.map(({ pattern }) => pattern), '*-*-*', // Include data-streams aliases `{type}-{dataset}-{namespace}` ]; - const [indexMappings, indexStats]: [IndexMappings, IndexStats] = await Promise.all([ + const indexMappingsParams: { index: string; filter_path: string[] } = { // GET */_mapping?filter_path=*.mappings._meta.beat,*.mappings.properties.ecs.properties.version.type,*.mappings.properties.dataset.properties.type.value,*.mappings.properties.dataset.properties.name.value - callCluster('indices.getMapping', { - index: '*', // Request all indices because filter_path already filters out the indices without any of those fields - filterPath: [ - // _meta.beat tells the shipper - '*.mappings._meta.beat', - // _meta.package.name tells the Ingest Manager's package - '*.mappings._meta.package.name', - // _meta.managed_by is usually populated by Ingest Manager for the UI to identify it - '*.mappings._meta.managed_by', - // Does it have `ecs.version` in the mappings? => It follows the ECS conventions - '*.mappings.properties.ecs.properties.version.type', + index: '*', // Request all indices because filter_path already filters out the indices without any of those fields + filter_path: [ + // _meta.beat tells the shipper + '*.mappings._meta.beat', + // _meta.package.name tells the Ingest Manager's package + '*.mappings._meta.package.name', + // _meta.managed_by is usually populated by Ingest Manager for the UI to identify it + '*.mappings._meta.managed_by', + // Does it have `ecs.version` in the mappings? => It follows the ECS conventions + '*.mappings.properties.ecs.properties.version.type', - // If `data_stream.type` is a `constant_keyword`, it can be reported as a type - '*.mappings.properties.data_stream.properties.type.value', - // If `data_stream.dataset` is a `constant_keyword`, it can be reported as the dataset - '*.mappings.properties.data_stream.properties.dataset.value', - ], - }), + // If `data_stream.type` is a `constant_keyword`, it can be reported as a type + '*.mappings.properties.data_stream.properties.type.value', + // If `data_stream.dataset` is a `constant_keyword`, it can be reported as the dataset + '*.mappings.properties.data_stream.properties.dataset.value', + ], + }; + const indicesStatsParams: { + index: string | string[] | undefined; + level: 'cluster' | 'indices' | 'shards' | undefined; + metric: string[]; + filter_path: string[]; + } = { // GET /_stats/docs,store?level=indices&filter_path=indices.*.total - callCluster('indices.stats', { - index, - level: 'indices', - metric: ['docs', 'store'], - filterPath: ['indices.*.total'], - }), + index, + level: 'indices', + metric: ['docs', 'store'], + filter_path: ['indices.*.total'], + }; + const [{ body: indexMappings }, { body: indexStats }] = await Promise.all([ + esClient.indices.getMapping(indexMappingsParams), + esClient.indices.stats(indicesStatsParams), ]); const indexNames = Object.keys({ ...indexMappings, ...indexStats?.indices }); + const indices = indexNames.map((name) => { const baseIndexInfo = { name, diff --git a/src/plugins/telemetry/server/telemetry_collection/get_data_telemetry/index.ts b/src/plugins/telemetry/server/telemetry_collection/get_data_telemetry/index.ts index d056d1c9f299f..0e2ab98a24cba 100644 --- a/src/plugins/telemetry/server/telemetry_collection/get_data_telemetry/index.ts +++ b/src/plugins/telemetry/server/telemetry_collection/get_data_telemetry/index.ts @@ -20,8 +20,8 @@ export { DATA_TELEMETRY_ID } from './constants'; export { - DataTelemetryIndex, - DataTelemetryPayload, getDataTelemetry, buildDataTelemetryPayload, + DataTelemetryPayload, + DataTelemetryIndex, } from './get_data_telemetry'; diff --git a/src/plugins/telemetry/server/telemetry_collection/get_kibana.ts b/src/plugins/telemetry/server/telemetry_collection/get_kibana.ts index 5d27774a630a5..0ef9815a4eadb 100644 --- a/src/plugins/telemetry/server/telemetry_collection/get_kibana.ts +++ b/src/plugins/telemetry/server/telemetry_collection/get_kibana.ts @@ -21,6 +21,7 @@ import { omit } from 'lodash'; import { UsageCollectionSetup } from 'src/plugins/usage_collection/server'; import { LegacyAPICaller } from 'kibana/server'; import { StatsCollectionContext } from 'src/plugins/telemetry_collection_manager/server'; +import { ElasticsearchClient } from 'src/core/server'; export interface KibanaUsageStats { kibana: { @@ -48,7 +49,6 @@ export function handleKibanaStats( logger.warn('No Kibana stats returned from usage collectors'); return; } - const { kibana, kibana_stats: kibanaStats, ...plugins } = response; const os = { @@ -83,8 +83,9 @@ export function handleKibanaStats( export async function getKibana( usageCollection: UsageCollectionSetup, - callWithInternalUser: LegacyAPICaller + callWithInternalUser: LegacyAPICaller, + asInternalUser: ElasticsearchClient ): Promise { - const usage = await usageCollection.bulkFetch(callWithInternalUser); + const usage = await usageCollection.bulkFetch(callWithInternalUser, asInternalUser); return usageCollection.toObject(usage); } diff --git a/src/plugins/telemetry/server/telemetry_collection/get_local_license.ts b/src/plugins/telemetry/server/telemetry_collection/get_local_license.ts index d41904c6d8e0e..879416cda62fc 100644 --- a/src/plugins/telemetry/server/telemetry_collection/get_local_license.ts +++ b/src/plugins/telemetry/server/telemetry_collection/get_local_license.ts @@ -17,44 +17,41 @@ * under the License. */ -import { LegacyAPICaller } from 'kibana/server'; import { ESLicense, LicenseGetter } from 'src/plugins/telemetry_collection_manager/server'; +import { ElasticsearchClient } from 'src/core/server'; let cachedLicense: ESLicense | undefined; -function fetchLicense(callCluster: LegacyAPICaller, local: boolean) { - return callCluster<{ license: ESLicense }>('transport.request', { - method: 'GET', - path: '/_license', - query: { - local, - // For versions >= 7.6 and < 8.0, this flag is needed otherwise 'platinum' is returned for 'enterprise' license. - accept_enterprise: 'true', - }, +async function fetchLicense(esClient: ElasticsearchClient, local: boolean) { + const { body } = await esClient.license.get({ + local, + // For versions >= 7.6 and < 8.0, this flag is needed otherwise 'platinum' is returned for 'enterprise' license. + accept_enterprise: true, }); + return body; } - /** * Get the cluster's license from the connected node. * - * This is the equivalent of GET /_license?local=true . + * This is the equivalent of GET /_license?local=true&accept_enterprise=true. * * Like any X-Pack related API, X-Pack must installed for this to work. + * + * In OSS we'll get a 400 response using the new elasticsearch client. */ -async function getLicenseFromLocalOrMaster(callCluster: LegacyAPICaller) { - // Fetching the local license is cheaper than getting it from the master and good enough - const { license } = await fetchLicense(callCluster, true).catch(async (err) => { +async function getLicenseFromLocalOrMaster(esClient: ElasticsearchClient) { + // Fetching the local license is cheaper than getting it from the master node and good enough + const { license } = await fetchLicense(esClient, true).catch(async (err) => { if (cachedLicense) { try { // Fallback to the master node's license info - const response = await fetchLicense(callCluster, false); + const response = await fetchLicense(esClient, false); return response; } catch (masterError) { - if (masterError.statusCode === 404) { + if ([400, 404].includes(masterError.statusCode)) { // If the master node does not have a license, we can assume there is no license cachedLicense = undefined; } else { - // Any other errors from the master node, throw and do not send any telemetry throw err; } } @@ -68,9 +65,8 @@ async function getLicenseFromLocalOrMaster(callCluster: LegacyAPICaller) { return license; } -export const getLocalLicense: LicenseGetter = async (clustersDetails, { callCluster }) => { - const license = await getLicenseFromLocalOrMaster(callCluster); - +export const getLocalLicense: LicenseGetter = async (clustersDetails, { esClient }) => { + const license = await getLicenseFromLocalOrMaster(esClient); // It should be called only with 1 cluster element in the clustersDetails array, but doing reduce just in case. return clustersDetails.reduce((acc, { clusterUuid }) => ({ ...acc, [clusterUuid]: license }), {}); }; diff --git a/src/plugins/telemetry/server/telemetry_collection/get_local_stats.test.ts b/src/plugins/telemetry/server/telemetry_collection/get_local_stats.test.ts new file mode 100644 index 0000000000000..0c8b0b249f7d1 --- /dev/null +++ b/src/plugins/telemetry/server/telemetry_collection/get_local_stats.test.ts @@ -0,0 +1,259 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { merge, omit } from 'lodash'; + +import { getLocalStats, handleLocalStats } from './get_local_stats'; +import { usageCollectionPluginMock } from '../../../usage_collection/server/mocks'; +import { elasticsearchServiceMock } from '../../../../../src/core/server/mocks'; + +function mockUsageCollection(kibanaUsage = {}) { + const usageCollection = usageCollectionPluginMock.createSetupContract(); + usageCollection.bulkFetch = jest.fn().mockResolvedValue(kibanaUsage); + usageCollection.toObject = jest.fn().mockImplementation((data: any) => data); + return usageCollection; +} +// set up successful call mocks for info, cluster stats, nodes usage and data telemetry +function mockGetLocalStats(clusterInfo: any, clusterStats: any) { + const esClient = elasticsearchServiceMock.createClusterClient().asInternalUser; + esClient.info + // @ts-ignore we only care about the response body + .mockResolvedValue( + // @ts-ignore we only care about the response body + { + body: { ...clusterInfo }, + } + ); + esClient.cluster.stats + // @ts-ignore we only care about the response body + .mockResolvedValue({ body: { ...clusterStats } }); + esClient.nodes.usage.mockResolvedValue( + // @ts-ignore we only care about the response body + { + body: { + cluster_name: 'testCluster', + nodes: { + some_node_id: { + timestamp: 1588617023177, + since: 1588616945163, + rest_actions: { + nodes_usage_action: 1, + create_index_action: 1, + document_get_action: 1, + search_action: 19, + nodes_info_action: 36, + }, + aggregations: { + terms: { + bytes: 2, + }, + scripted_metric: { + other: 7, + }, + }, + }, + }, + }, + } + ); + // @ts-ignore we only care about the response body + esClient.indices.getMapping.mockResolvedValue({ body: { mappings: {} } }); + // @ts-ignore we only care about the response body + esClient.indices.stats.mockResolvedValue({ body: { indices: {} } }); + return esClient; +} + +describe('get_local_stats', () => { + const clusterUuid = 'abc123'; + const clusterName = 'my-cool-cluster'; + const version = '2.3.4'; + const clusterInfo = { + cluster_uuid: clusterUuid, + cluster_name: clusterName, + version: { number: version }, + }; + const nodesUsage = [ + { + node_id: 'some_node_id', + timestamp: 1588617023177, + since: 1588616945163, + rest_actions: { + nodes_usage_action: 1, + create_index_action: 1, + document_get_action: 1, + search_action: 19, + nodes_info_action: 36, + }, + aggregations: { + terms: { + bytes: 2, + }, + scripted_metric: { + other: 7, + }, + }, + }, + ]; + const clusterStats = { + _nodes: { failed: 123 }, + cluster_name: 'real-cool', + indices: { totally: 456 }, + nodes: { yup: 'abc' }, + random: 123, + }; + + const kibana = { + kibana: { + great: 'googlymoogly', + versions: [{ version: '8675309', count: 1 }], + }, + kibana_stats: { + os: { + platform: 'rocky', + platformRelease: 'iv', + }, + }, + localization: { + locale: 'en', + labelsCount: 0, + integrities: {}, + }, + sun: { chances: 5 }, + clouds: { chances: 95 }, + rain: { chances: 2 }, + snow: { chances: 0 }, + }; + + const clusterStatsWithNodesUsage = { + ...clusterStats, + nodes: merge(clusterStats.nodes, { usage: { nodes: nodesUsage } }), + }; + + const combinedStatsResult = { + collection: 'local', + cluster_uuid: clusterUuid, + cluster_name: clusterName, + version, + cluster_stats: omit(clusterStatsWithNodesUsage, '_nodes', 'cluster_name'), + stack_stats: { + kibana: { + great: 'googlymoogly', + count: 1, + indices: 1, + os: { + platforms: [{ platform: 'rocky', count: 1 }], + platformReleases: [{ platformRelease: 'iv', count: 1 }], + }, + versions: [{ version: '8675309', count: 1 }], + plugins: { + localization: { + locale: 'en', + labelsCount: 0, + integrities: {}, + }, + sun: { chances: 5 }, + clouds: { chances: 95 }, + rain: { chances: 2 }, + snow: { chances: 0 }, + }, + }, + }, + }; + + const context = { + logger: console, + version: '8.0.0', + }; + + describe('handleLocalStats', () => { + it('returns expected object without xpack or kibana data', () => { + const result = handleLocalStats( + clusterInfo, + clusterStatsWithNodesUsage, + void 0, + void 0, + context + ); + expect(result.cluster_uuid).toStrictEqual(combinedStatsResult.cluster_uuid); + expect(result.cluster_name).toStrictEqual(combinedStatsResult.cluster_name); + expect(result.cluster_stats).toStrictEqual(combinedStatsResult.cluster_stats); + expect(result.version).toEqual('2.3.4'); + expect(result.collection).toEqual('local'); + expect(Object.keys(result)).not.toContain('license'); + expect(result.stack_stats).toEqual({ kibana: undefined, data: undefined }); + }); + + it('returns expected object with xpack', () => { + const result = handleLocalStats( + clusterInfo, + clusterStatsWithNodesUsage, + void 0, + void 0, + context + ); + + const { stack_stats: stack, ...cluster } = result; + expect(cluster.collection).toBe(combinedStatsResult.collection); + expect(cluster.cluster_uuid).toBe(combinedStatsResult.cluster_uuid); + expect(cluster.cluster_name).toBe(combinedStatsResult.cluster_name); + expect(stack.kibana).toBe(undefined); // not mocked for this test + expect(stack.data).toBe(undefined); // not mocked for this test + + expect(cluster.version).toEqual(combinedStatsResult.version); + expect(cluster.cluster_stats).toEqual(combinedStatsResult.cluster_stats); + expect(Object.keys(cluster).indexOf('license')).toBeLessThan(0); + expect(Object.keys(stack).indexOf('xpack')).toBeLessThan(0); + }); + }); + + describe('getLocalStats', () => { + it('returns expected object with kibana data', async () => { + const callCluster = jest.fn(); + const usageCollection = mockUsageCollection(kibana); + const esClient = mockGetLocalStats(clusterInfo, clusterStats); + const response = await getLocalStats( + [{ clusterUuid: 'abc123' }], + { callCluster, usageCollection, esClient, start: '', end: '' }, + context + ); + const result = response[0]; + expect(result.cluster_uuid).toEqual(combinedStatsResult.cluster_uuid); + expect(result.cluster_name).toEqual(combinedStatsResult.cluster_name); + expect(result.cluster_stats).toEqual(combinedStatsResult.cluster_stats); + expect(result.cluster_stats.nodes).toEqual(combinedStatsResult.cluster_stats.nodes); + expect(result.version).toBe('2.3.4'); + expect(result.collection).toBe('local'); + expect(Object.keys(result).indexOf('license')).toBeLessThan(0); + expect(Object.keys(result.stack_stats).indexOf('xpack')).toBeLessThan(0); + }); + + it('returns an empty array when no cluster uuid is provided', async () => { + const callCluster = jest.fn(); + const usageCollection = mockUsageCollection(kibana); + const esClient = mockGetLocalStats(clusterInfo, clusterStats); + const response = await getLocalStats( + [], + { callCluster, usageCollection, esClient, start: '', end: '' }, + context + ); + expect(response).toBeDefined(); + expect(response.length).toEqual(0); + }); + }); +}); diff --git a/src/plugins/telemetry/server/telemetry_collection/get_local_stats.ts b/src/plugins/telemetry/server/telemetry_collection/get_local_stats.ts index 98c83a3394628..6244c6fac51d3 100644 --- a/src/plugins/telemetry/server/telemetry_collection/get_local_stats.ts +++ b/src/plugins/telemetry/server/telemetry_collection/get_local_stats.ts @@ -40,8 +40,8 @@ export function handleLocalStats( // eslint-disable-next-line @typescript-eslint/naming-convention { cluster_name, cluster_uuid, version }: ESClusterInfo, { _nodes, cluster_name: clusterName, ...clusterStats }: any, - kibana: KibanaUsageStats, - dataTelemetry: DataTelemetryPayload, + kibana: KibanaUsageStats | undefined, + dataTelemetry: DataTelemetryPayload | undefined, context: StatsCollectionContext ) { return { @@ -62,22 +62,25 @@ export type TelemetryLocalStats = ReturnType; /** * Get statistics for all products joined by Elasticsearch cluster. + * @param {Array} cluster uuids + * @param {Object} config contains the new esClient already scoped contains usageCollection, callCluster, esClient, start, end + * @param {Object} StatsCollectionContext contains logger and version (string) */ export const getLocalStats: StatsGetter<{}, TelemetryLocalStats> = async ( - clustersDetails, - config, - context + clustersDetails, // array of cluster uuid's + config, // contains the new esClient already scoped contains usageCollection, callCluster, esClient, start, end + context // StatsCollectionContext contains logger and version (string) ) => { - const { callCluster, usageCollection } = config; + const { callCluster, usageCollection, esClient } = config; return await Promise.all( clustersDetails.map(async (clustersDetail) => { const [clusterInfo, clusterStats, nodesUsage, kibana, dataTelemetry] = await Promise.all([ - getClusterInfo(callCluster), // cluster info - getClusterStats(callCluster), // cluster stats (not to be confused with cluster _state_) - getNodesUsage(callCluster), // nodes_usage info - getKibana(usageCollection, callCluster), - getDataTelemetry(callCluster), + getClusterInfo(esClient), // cluster info + getClusterStats(esClient), // cluster stats (not to be confused with cluster _state_) + getNodesUsage(esClient), // nodes_usage info + getKibana(usageCollection, callCluster, esClient), + getDataTelemetry(esClient), ]); return handleLocalStats( clusterInfo, diff --git a/src/plugins/telemetry/server/telemetry_collection/get_nodes_usage.test.ts b/src/plugins/telemetry/server/telemetry_collection/get_nodes_usage.test.ts index 4e4b0e11b7979..acf403ba25447 100644 --- a/src/plugins/telemetry/server/telemetry_collection/get_nodes_usage.test.ts +++ b/src/plugins/telemetry/server/telemetry_collection/get_nodes_usage.test.ts @@ -19,6 +19,7 @@ import { getNodesUsage } from './get_nodes_usage'; import { TIMEOUT } from './constants'; +import { elasticsearchServiceMock } from '../../../../../src/core/server/mocks'; const mockedNodesFetchResponse = { cluster_name: 'test cluster', @@ -44,37 +45,35 @@ const mockedNodesFetchResponse = { }, }, }; + describe('get_nodes_usage', () => { - it('calls fetchNodesUsage', async () => { - const callCluster = jest.fn(); - callCluster.mockResolvedValueOnce(mockedNodesFetchResponse); - await getNodesUsage(callCluster); - expect(callCluster).toHaveBeenCalledWith('transport.request', { - path: '/_nodes/usage', - method: 'GET', - query: { - timeout: TIMEOUT, - }, - }); - }); - it('returns a modified array of node usage data', async () => { - const callCluster = jest.fn(); - callCluster.mockResolvedValueOnce(mockedNodesFetchResponse); - const result = await getNodesUsage(callCluster); - expect(result.nodes).toEqual([ - { - aggregations: { scripted_metric: { other: 7 }, terms: { bytes: 2 } }, - node_id: 'some_node_id', - rest_actions: { - create_index_action: 1, - document_get_action: 1, - nodes_info_action: 36, - nodes_usage_action: 1, - search_action: 19, + it('returns a modified array of nodes usage data', async () => { + const response = Promise.resolve({ body: mockedNodesFetchResponse }); + const esClient = elasticsearchServiceMock.createClusterClient().asInternalUser; + esClient.nodes.usage.mockImplementationOnce( + // @ts-ignore + async (_params = { timeout: TIMEOUT }) => { + return response; + } + ); + const item = await getNodesUsage(esClient); + expect(esClient.nodes.usage).toHaveBeenCalledWith({ timeout: TIMEOUT }); + expect(item).toStrictEqual({ + nodes: [ + { + aggregations: { scripted_metric: { other: 7 }, terms: { bytes: 2 } }, + node_id: 'some_node_id', + rest_actions: { + create_index_action: 1, + document_get_action: 1, + nodes_info_action: 36, + nodes_usage_action: 1, + search_action: 19, + }, + since: 1588616945163, + timestamp: 1588617023177, }, - since: 1588616945163, - timestamp: 1588617023177, - }, - ]); + ], + }); }); }); diff --git a/src/plugins/telemetry/server/telemetry_collection/get_nodes_usage.ts b/src/plugins/telemetry/server/telemetry_collection/get_nodes_usage.ts index c5c110fbb4149..959840d0020a2 100644 --- a/src/plugins/telemetry/server/telemetry_collection/get_nodes_usage.ts +++ b/src/plugins/telemetry/server/telemetry_collection/get_nodes_usage.ts @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -import { LegacyAPICaller } from 'kibana/server'; +import { ElasticsearchClient } from 'src/core/server'; import { TIMEOUT } from './constants'; export interface NodeAggregation { @@ -44,7 +44,7 @@ export interface NodesFeatureUsageResponse { } export type NodesUsageGetter = ( - callCluster: LegacyAPICaller + esClient: ElasticsearchClient ) => Promise<{ nodes: NodeObj[] | Array<{}> }>; /** * Get the nodes usage data from the connected cluster. @@ -54,16 +54,12 @@ export type NodesUsageGetter = ( * The Nodes usage API was introduced in v6.0.0 */ export async function fetchNodesUsage( - callCluster: LegacyAPICaller + esClient: ElasticsearchClient ): Promise { - const response = await callCluster('transport.request', { - method: 'GET', - path: '/_nodes/usage', - query: { - timeout: TIMEOUT, - }, + const { body } = await esClient.nodes.usage({ + timeout: TIMEOUT, }); - return response; + return body; } /** @@ -71,8 +67,8 @@ export async function fetchNodesUsage( * @param callCluster APICaller * @returns Object containing array of modified usage information with the node_id nested within the data for that node. */ -export const getNodesUsage: NodesUsageGetter = async (callCluster) => { - const result = await fetchNodesUsage(callCluster); +export const getNodesUsage: NodesUsageGetter = async (esClient) => { + const result = await fetchNodesUsage(esClient); const transformedNodes = Object.entries(result?.nodes || {}).map(([key, value]) => ({ ...(value as NodeObj), node_id: key, diff --git a/src/plugins/telemetry/server/telemetry_collection/register_collection.ts b/src/plugins/telemetry/server/telemetry_collection/register_collection.ts index 438fcadad9255..9dac4900f5f10 100644 --- a/src/plugins/telemetry/server/telemetry_collection/register_collection.ts +++ b/src/plugins/telemetry/server/telemetry_collection/register_collection.ts @@ -38,16 +38,19 @@ import { ILegacyClusterClient } from 'kibana/server'; import { TelemetryCollectionManagerPluginSetup } from 'src/plugins/telemetry_collection_manager/server'; +import { IClusterClient } from '../../../../../src/core/server'; import { getLocalStats } from './get_local_stats'; import { getClusterUuids } from './get_cluster_stats'; import { getLocalLicense } from './get_local_license'; export function registerCollection( telemetryCollectionManager: TelemetryCollectionManagerPluginSetup, - esCluster: ILegacyClusterClient + esCluster: ILegacyClusterClient, + esClientGetter: () => IClusterClient | undefined ) { telemetryCollectionManager.setCollection({ esCluster, + esClientGetter, title: 'local', priority: 0, statsGetter: getLocalStats, diff --git a/src/plugins/telemetry_collection_manager/server/index.ts b/src/plugins/telemetry_collection_manager/server/index.ts index 8761c28e14095..36ab64731fe58 100644 --- a/src/plugins/telemetry_collection_manager/server/index.ts +++ b/src/plugins/telemetry_collection_manager/server/index.ts @@ -38,4 +38,5 @@ export { ClusterDetails, ClusterDetailsGetter, LicenseGetter, + UsageStatsPayload, } from './types'; diff --git a/src/plugins/telemetry_collection_manager/server/plugin.ts b/src/plugins/telemetry_collection_manager/server/plugin.ts index 051bb3a11cb16..ff63262004cf5 100644 --- a/src/plugins/telemetry_collection_manager/server/plugin.ts +++ b/src/plugins/telemetry_collection_manager/server/plugin.ts @@ -24,6 +24,7 @@ import { CoreStart, Plugin, Logger, + IClusterClient, } from '../../../core/server'; import { @@ -66,6 +67,7 @@ export class TelemetryCollectionManagerPlugin setCollection: this.setCollection.bind(this), getOptInStats: this.getOptInStats.bind(this), getStats: this.getStats.bind(this), + areAllCollectorsReady: this.areAllCollectorsReady.bind(this), }; } @@ -74,6 +76,7 @@ export class TelemetryCollectionManagerPlugin setCollection: this.setCollection.bind(this), getOptInStats: this.getOptInStats.bind(this), getStats: this.getStats.bind(this), + areAllCollectorsReady: this.areAllCollectorsReady.bind(this), }; } @@ -86,6 +89,7 @@ export class TelemetryCollectionManagerPlugin title, priority, esCluster, + esClientGetter, statsGetter, clusterDetailsGetter, licenseGetter, @@ -105,6 +109,9 @@ export class TelemetryCollectionManagerPlugin if (!esCluster) { throw Error('esCluster name must be set for the getCluster method.'); } + if (!esClientGetter) { + throw Error('esClientGetter method not set.'); + } if (!clusterDetailsGetter) { throw Error('Cluster UUIds method is not set.'); } @@ -118,6 +125,7 @@ export class TelemetryCollectionManagerPlugin clusterDetailsGetter, esCluster, title, + esClientGetter, }); this.usageGetterMethodPriority = priority; } @@ -126,6 +134,7 @@ export class TelemetryCollectionManagerPlugin private getStatsCollectionConfig( config: StatsGetterConfig, collection: Collection, + collectionEsClient: IClusterClient, usageCollection: UsageCollectionSetup ): StatsCollectionConfig { const { start, end, request } = config; @@ -133,8 +142,11 @@ export class TelemetryCollectionManagerPlugin const callCluster = config.unencrypted ? collection.esCluster.asScoped(request).callAsCurrentUser : collection.esCluster.callAsInternalUser; - - return { callCluster, start, end, usageCollection }; + // Scope the new elasticsearch Client appropriately and pass to the stats collection config + const esClient = config.unencrypted + ? collectionEsClient.asScoped(config.request).asCurrentUser + : collectionEsClient.asInternalUser; + return { callCluster, start, end, usageCollection, esClient }; } private async getOptInStats(optInStatus: boolean, config: StatsGetterConfig) { @@ -142,33 +154,43 @@ export class TelemetryCollectionManagerPlugin return []; } for (const collection of this.collections) { - const statsCollectionConfig = this.getStatsCollectionConfig( - config, - collection, - this.usageCollection - ); - try { - const optInStats = await this.getOptInStatsForCollection( + // first fetch the client and make sure it's not undefined. + const collectionEsClient = collection.esClientGetter(); + if (collectionEsClient !== undefined) { + const statsCollectionConfig = this.getStatsCollectionConfig( + config, collection, - optInStatus, - statsCollectionConfig + collectionEsClient, + this.usageCollection ); - if (optInStats && optInStats.length) { - this.logger.debug(`Got Opt In stats using ${collection.title} collection.`); - if (config.unencrypted) { - return optInStats; + + try { + const optInStats = await this.getOptInStatsForCollection( + collection, + optInStatus, + statsCollectionConfig + ); + if (optInStats && optInStats.length) { + this.logger.debug(`Got Opt In stats using ${collection.title} collection.`); + if (config.unencrypted) { + return optInStats; + } + return encryptTelemetry(optInStats, { useProdKey: this.isDistributable }); } - return encryptTelemetry(optInStats, { useProdKey: this.isDistributable }); + } catch (err) { + this.logger.debug(`Failed to collect any opt in stats with registered collections.`); + // swallow error to try next collection; } - } catch (err) { - this.logger.debug(`Failed to collect any opt in stats with registered collections.`); - // swallow error to try next collection; } } return []; } + private areAllCollectorsReady = async () => { + return await this.usageCollection?.areAllCollectorsReady(); + }; + private getOptInStatsForCollection = async ( collection: Collection, optInStatus: boolean, @@ -192,28 +214,32 @@ export class TelemetryCollectionManagerPlugin return []; } for (const collection of this.collections) { - const statsCollectionConfig = this.getStatsCollectionConfig( - config, - collection, - this.usageCollection - ); - try { - const usageData = await this.getUsageForCollection(collection, statsCollectionConfig); - if (usageData.length) { - this.logger.debug(`Got Usage using ${collection.title} collection.`); - if (config.unencrypted) { - return usageData; - } + const collectionEsClient = collection.esClientGetter(); + if (collectionEsClient !== undefined) { + const statsCollectionConfig = this.getStatsCollectionConfig( + config, + collection, + collectionEsClient, + this.usageCollection + ); + try { + const usageData = await this.getUsageForCollection(collection, statsCollectionConfig); + if (usageData.length) { + this.logger.debug(`Got Usage using ${collection.title} collection.`); + if (config.unencrypted) { + return usageData; + } - return encryptTelemetry(usageData.filter(isClusterOptedIn), { - useProdKey: this.isDistributable, - }); + return encryptTelemetry(usageData.filter(isClusterOptedIn), { + useProdKey: this.isDistributable, + }); + } + } catch (err) { + this.logger.debug( + `Failed to collect any usage with registered collection ${collection.title}.` + ); + // swallow error to try next collection; } - } catch (err) { - this.logger.debug( - `Failed to collect any usage with registered collection ${collection.title}.` - ); - // swallow error to try next collection; } } diff --git a/src/plugins/telemetry_collection_manager/server/types.ts b/src/plugins/telemetry_collection_manager/server/types.ts index 16f96c07fd8ea..3b0936fb73a60 100644 --- a/src/plugins/telemetry_collection_manager/server/types.ts +++ b/src/plugins/telemetry_collection_manager/server/types.ts @@ -17,8 +17,15 @@ * under the License. */ -import { LegacyAPICaller, Logger, KibanaRequest, ILegacyClusterClient } from 'kibana/server'; +import { + LegacyAPICaller, + Logger, + KibanaRequest, + ILegacyClusterClient, + IClusterClient, +} from 'kibana/server'; import { UsageCollectionSetup } from 'src/plugins/usage_collection/server'; +import { ElasticsearchClient } from '../../../../src/core/server'; import { TelemetryCollectionManagerPlugin } from './plugin'; export interface TelemetryCollectionManagerPluginSetup { @@ -27,6 +34,7 @@ export interface TelemetryCollectionManagerPluginSetup { ) => void; getOptInStats: TelemetryCollectionManagerPlugin['getOptInStats']; getStats: TelemetryCollectionManagerPlugin['getStats']; + areAllCollectorsReady: TelemetryCollectionManagerPlugin['areAllCollectorsReady']; } export interface TelemetryCollectionManagerPluginStart { @@ -35,6 +43,7 @@ export interface TelemetryCollectionManagerPluginStart { ) => void; getOptInStats: TelemetryCollectionManagerPlugin['getOptInStats']; getStats: TelemetryCollectionManagerPlugin['getStats']; + areAllCollectorsReady: TelemetryCollectionManagerPlugin['areAllCollectorsReady']; } export interface TelemetryOptInStats { @@ -67,6 +76,7 @@ export interface StatsCollectionConfig { callCluster: LegacyAPICaller; start: string | number; end: string | number; + esClient: ElasticsearchClient; } export interface BasicStatsPayload { @@ -100,7 +110,7 @@ export interface ESLicense { } export interface StatsCollectionContext { - logger: Logger; + logger: Logger | Console; version: string; } @@ -130,6 +140,7 @@ export interface CollectionConfig< title: string; priority: number; esCluster: ILegacyClusterClient; + esClientGetter: () => IClusterClient | undefined; // --> by now we know that the client getter will return the IClusterClient but we assure that through a code check statsGetter: StatsGetter; clusterDetailsGetter: ClusterDetailsGetter; licenseGetter: LicenseGetter; @@ -145,5 +156,6 @@ export interface Collection< licenseGetter: LicenseGetter; clusterDetailsGetter: ClusterDetailsGetter; esCluster: ILegacyClusterClient; + esClientGetter: () => IClusterClient | undefined; // the collection could still return undefined for the es client getter. title: string; } diff --git a/src/plugins/telemetry_management_section/README.md b/src/plugins/telemetry_management_section/README.md index 0f795786720c9..c23a8591f6794 100644 --- a/src/plugins/telemetry_management_section/README.md +++ b/src/plugins/telemetry_management_section/README.md @@ -1,5 +1,5 @@ # Telemetry Management Section -This plugin adds the Advanced Settings section for the Usage Data collection (aka Telemetry). +This plugin adds the Advanced Settings section for the Usage and Security Data collection (aka Telemetry). The reason for having it separated from the `telemetry` plugin is to avoid circular dependencies. The plugin `advancedSettings` depends on the `home` app that depends on the `telemetry` plugin because of the telemetry banner in the welcome screen. diff --git a/src/plugins/telemetry_management_section/public/components/__snapshots__/opt_in_security_example_flyout.test.tsx.snap b/src/plugins/telemetry_management_section/public/components/__snapshots__/opt_in_security_example_flyout.test.tsx.snap new file mode 100644 index 0000000000000..0b9d426008ca4 --- /dev/null +++ b/src/plugins/telemetry_management_section/public/components/__snapshots__/opt_in_security_example_flyout.test.tsx.snap @@ -0,0 +1,134 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`security flyout renders as expected renders as expected 1`] = ` + + + + +

+ Endpoint security data +

+
+ + + This is a representative sample of the endpoint security alert event that we collect. Endpoint security data is collected only when the Elastic Endpoint is enabled. It includes information about the endpoint configuration and detection events. + + +
+ + + { + "@timestamp": "2020-09-22T14:34:56.82202300Z", + "agent": { + "build": { + "original": "version: 7.9.1, compiled: Thu Aug 27 14:50:21 2020, branch: 7.9, commit: b594beb958817dee9b9d908191ed766d483df3ea" + }, + "id": "22dd8544-bcac-46cb-b970-5e681bb99e0b", + "type": "endpoint", + "version": "7.9.1" + }, + "Endpoint": { + "policy": { + "applied": { + "artifacts": { + "global": { + "identifiers": [ + { + "sha256": "6a546aade5563d3e8dffc1fe2d93d33edda8f9ca3e17ac3cc9ac707620cb9ecd", + "name": "endpointpe-v4-blocklist" + }, + { + "sha256": "04f9f87accc5d5aea433427bd1bd4ec6908f8528c78ceed26f70df7875a99385", + "name": "endpointpe-v4-exceptionlist" + }, + { + "sha256": "1471838597fcd79a54ea4a3ec9a9beee1a86feaedab6c98e61102559ced822a8", + "name": "endpointpe-v4-model" + }, + { + "sha256": "824859b0c6749cc31951d92a73bbdddfcfe9f38abfe432087934d4dab9766ce8", + "name": "global-exceptionlist-windows" + } + ], + "version": "1.0.0" + }, + "user": { + "identifiers": [ + { + "sha256": "d801aa1fb7ddcc330a5e3173372ea6af4a3d08ec58074478e85aa5603e926658", + "name": "endpoint-exceptionlist-windows-v1" + } + ], + "version": "1.0.0" + } + } + } + } + }, + "ecs": { + "version": "1.5.0" + }, + "elastic": { + "agent": { + "id": "b2e88aea-2671-402a-828a-957526bac315" + } + }, + "file": { + "path": "C:\\\\Windows\\\\Temp\\\\mimikatz.exe", + "size": 1263880, + "created": "2020-05-19T07:50:06.0Z", + "accessed": "2020-09-22T14:29:19.93531400Z", + "mtime": "2020-09-22T14:29:03.6040000Z", + "directory": "C:\\\\Windows\\\\Temp", + "hash": { + "sha1": "c9fb7f8a4c6b7b12b493a99a8dc6901d17867388", + "sha256": "cb1553a3c88817e4cc774a5a93f9158f6785bd3815447d04b6c3f4c2c4b21ed7", + "md5": "465d5d850f54d9cde767bda90743df30" + }, + "Ext": { + "code_signature": { + "trusted": true, + "subject_name": "Open Source Developer, Benjamin Delpy", + "exists": true, + "status": "trusted" + }, + "malware_classification": { + "identifier": "endpointpe-v4-model", + "score": 0.99956864118576, + "threshold": 0.71, + "version": "0.0.0" + } + } + }, + "host": { + "os": { + "Ext": { + "variant": "Windows 10 Enterprise Evaluation" + }, + "kernel": "2004 (10.0.19041.388)", + "name": "Windows", + "family": "windows", + "version": "2004 (10.0.19041.388)", + "platform": "windows", + "full": "Windows 10 Enterprise Evaluation 2004 (10.0.19041.388)" + } + }, + "event": { + "kind": "alert" + }, + "cluster_uuid": "kLbKvSMcRiiFAR0t8LebDA", + "cluster_name": "elasticsearch" +} + + +
+
+`; diff --git a/src/plugins/telemetry_management_section/public/components/__snapshots__/telemetry_management_section.test.tsx.snap b/src/plugins/telemetry_management_section/public/components/__snapshots__/telemetry_management_section.test.tsx.snap index ab29656c557c2..7357598c8495f 100644 --- a/src/plugins/telemetry_management_section/public/components/__snapshots__/telemetry_management_section.test.tsx.snap +++ b/src/plugins/telemetry_management_section/public/components/__snapshots__/telemetry_management_section.test.tsx.snap @@ -49,7 +49,7 @@ exports[`TelemetryManagementSectionComponent renders as expected 1`] = ` -

- - - + + + , + "endpointSecurityData": + + , + } + } + />

, "displayName": "Provide usage statistics", @@ -286,205 +303,4 @@ exports[`TelemetryManagementSectionComponent renders null because allowChangingO /> `; -exports[`TelemetryManagementSectionComponent renders null because query does not match the SEARCH_TERMS 1`] = ` - -`; - exports[`TelemetryManagementSectionComponent test the wrapper (for coverage purposes) 1`] = `null`; diff --git a/src/plugins/telemetry_management_section/public/components/opt_in_security_example_flyout.test.tsx b/src/plugins/telemetry_management_section/public/components/opt_in_security_example_flyout.test.tsx new file mode 100644 index 0000000000000..c80d0daf5a695 --- /dev/null +++ b/src/plugins/telemetry_management_section/public/components/opt_in_security_example_flyout.test.tsx @@ -0,0 +1,27 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +import React from 'react'; +import { shallowWithIntl } from 'test_utils/enzyme_helpers'; +import { OptInSecurityExampleFlyout } from './opt_in_security_example_flyout'; + +describe('security flyout renders as expected', () => { + it('renders as expected', () => { + expect(shallowWithIntl()).toMatchSnapshot(); + }); +}); diff --git a/src/plugins/telemetry_management_section/public/components/opt_in_security_example_flyout.tsx b/src/plugins/telemetry_management_section/public/components/opt_in_security_example_flyout.tsx new file mode 100644 index 0000000000000..af0de5b268ddc --- /dev/null +++ b/src/plugins/telemetry_management_section/public/components/opt_in_security_example_flyout.tsx @@ -0,0 +1,235 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import * as React from 'react'; + +import { + EuiCallOut, + EuiCodeBlock, + EuiFlexGroup, + EuiFlexItem, + EuiFlyout, + EuiFlyoutHeader, + EuiFlyoutBody, + EuiLoadingSpinner, + EuiPortal, // EuiPortal is a temporary requirement to use EuiFlyout with "ownFocus" + EuiText, + EuiTextColor, + EuiTitle, +} from '@elastic/eui'; + +import { FormattedMessage } from '@kbn/i18n/react'; + +interface Props { + onClose: () => void; +} + +interface State { + isLoading: boolean; + hasPrivilegeToRead: boolean; +} + +/** + * React component for displaying the example data associated with the Telemetry opt-in banner. + */ +export class OptInSecurityExampleFlyout extends React.PureComponent { + public readonly state: State = { + isLoading: true, + hasPrivilegeToRead: false, + }; + + async componentDidMount() { + try { + this.setState({ + isLoading: false, + hasPrivilegeToRead: true, + }); + } catch (err) { + this.setState({ + isLoading: false, + hasPrivilegeToRead: err.status !== 403, + }); + } + } + + renderBody({ isLoading, hasPrivilegeToRead }: State) { + if (isLoading) { + return ( + + + + + + ); + } + + if (!hasPrivilegeToRead) { + return ( + + } + color="danger" + iconType="cross" + > + + + ); + } + + return ( + + {JSON.stringify(this.exampleSecurityPayload, null, 2)} + + ); + } + + render() { + return ( + + + + +

Endpoint security data

+
+ + + This is a representative sample of the endpoint security alert event that we + collect. Endpoint security data is collected only when the Elastic Endpoint is + enabled. It includes information about the endpoint configuration and detection + events. + + +
+ {this.renderBody(this.state)} +
+
+ ); + } + + exampleSecurityPayload = { + '@timestamp': '2020-09-22T14:34:56.82202300Z', + agent: { + build: { + original: + 'version: 7.9.1, compiled: Thu Aug 27 14:50:21 2020, branch: 7.9, commit: b594beb958817dee9b9d908191ed766d483df3ea', + }, + id: '22dd8544-bcac-46cb-b970-5e681bb99e0b', + type: 'endpoint', + version: '7.9.1', + }, + Endpoint: { + policy: { + applied: { + artifacts: { + global: { + identifiers: [ + { + sha256: '6a546aade5563d3e8dffc1fe2d93d33edda8f9ca3e17ac3cc9ac707620cb9ecd', + name: 'endpointpe-v4-blocklist', + }, + { + sha256: '04f9f87accc5d5aea433427bd1bd4ec6908f8528c78ceed26f70df7875a99385', + name: 'endpointpe-v4-exceptionlist', + }, + { + sha256: '1471838597fcd79a54ea4a3ec9a9beee1a86feaedab6c98e61102559ced822a8', + name: 'endpointpe-v4-model', + }, + { + sha256: '824859b0c6749cc31951d92a73bbdddfcfe9f38abfe432087934d4dab9766ce8', + name: 'global-exceptionlist-windows', + }, + ], + version: '1.0.0', + }, + user: { + identifiers: [ + { + sha256: 'd801aa1fb7ddcc330a5e3173372ea6af4a3d08ec58074478e85aa5603e926658', + name: 'endpoint-exceptionlist-windows-v1', + }, + ], + version: '1.0.0', + }, + }, + }, + }, + }, + ecs: { + version: '1.5.0', + }, + elastic: { + agent: { + id: 'b2e88aea-2671-402a-828a-957526bac315', + }, + }, + file: { + path: 'C:\\Windows\\Temp\\mimikatz.exe', + size: 1263880, + created: '2020-05-19T07:50:06.0Z', + accessed: '2020-09-22T14:29:19.93531400Z', + mtime: '2020-09-22T14:29:03.6040000Z', + directory: 'C:\\Windows\\Temp', + hash: { + sha1: 'c9fb7f8a4c6b7b12b493a99a8dc6901d17867388', + sha256: 'cb1553a3c88817e4cc774a5a93f9158f6785bd3815447d04b6c3f4c2c4b21ed7', + md5: '465d5d850f54d9cde767bda90743df30', + }, + Ext: { + code_signature: { + trusted: true, + subject_name: 'Open Source Developer, Benjamin Delpy', + exists: true, + status: 'trusted', + }, + malware_classification: { + identifier: 'endpointpe-v4-model', + score: 0.99956864118576, + threshold: 0.71, + version: '0.0.0', + }, + }, + }, + host: { + os: { + Ext: { + variant: 'Windows 10 Enterprise Evaluation', + }, + kernel: '2004 (10.0.19041.388)', + name: 'Windows', + family: 'windows', + version: '2004 (10.0.19041.388)', + platform: 'windows', + full: 'Windows 10 Enterprise Evaluation 2004 (10.0.19041.388)', + }, + }, + event: { + kind: 'alert', + }, + cluster_uuid: 'kLbKvSMcRiiFAR0t8LebDA', + cluster_name: 'elasticsearch', + }; +} diff --git a/src/plugins/telemetry_management_section/public/components/telemetry_management_section.test.tsx b/src/plugins/telemetry_management_section/public/components/telemetry_management_section.test.tsx index c13f639f31447..993295746ea5b 100644 --- a/src/plugins/telemetry_management_section/public/components/telemetry_management_section.test.tsx +++ b/src/plugins/telemetry_management_section/public/components/telemetry_management_section.test.tsx @@ -21,6 +21,7 @@ import { mountWithIntl, shallowWithIntl } from 'test_utils/enzyme_helpers'; import TelemetryManagementSection from './telemetry_management_section'; import { TelemetryService } from '../../../telemetry/public/services'; import { coreMock } from '../../../../core/public/mocks'; +import { render } from '@testing-library/react'; describe('TelemetryManagementSectionComponent', () => { const coreStart = coreMock.createStart(); @@ -73,19 +74,31 @@ describe('TelemetryManagementSectionComponent', () => { http: coreSetup.http, }); - const component = mountWithIntl( - + const component = render( + Fallback}> + + ); + try { - expect( - component.setProps({ ...component.props(), query: { text: 'asssdasdsad' } }) - ).toMatchSnapshot(); + component.rerender( + Fallback}> + + + ); expect(onQueryMatchChange).toHaveBeenCalledWith(false); expect(onQueryMatchChange).toHaveBeenCalledTimes(1); } finally { @@ -199,7 +212,7 @@ describe('TelemetryManagementSectionComponent', () => { /> ); try { - const toggleExampleComponent = component.find('p > EuiLink[onClick]'); + const toggleExampleComponent = component.find('FormattedMessage > EuiLink[onClick]').at(0); const updatedView = toggleExampleComponent.simulate('click'); updatedView.find('OptInExampleFlyout'); updatedView.simulate('close'); @@ -208,6 +221,42 @@ describe('TelemetryManagementSectionComponent', () => { } }); + it('shows the OptInSecurityExampleFlyout', () => { + const onQueryMatchChange = jest.fn(); + const telemetryService = new TelemetryService({ + config: { + enabled: true, + url: '', + banner: true, + allowChangingOptInStatus: true, + optIn: false, + optInStatusUrl: '', + sendUsageFrom: 'browser', + }, + reportOptInStatusChange: false, + notifications: coreStart.notifications, + http: coreSetup.http, + }); + + const component = mountWithIntl( + + ); + try { + const toggleExampleComponent = component.find('FormattedMessage > EuiLink[onClick]').at(1); + const updatedView = toggleExampleComponent.simulate('click'); + updatedView.find('OptInSecurityExampleFlyout'); + updatedView.simulate('close'); + } finally { + component.unmount(); + } + }); + it('toggles the OptIn button', async () => { const onQueryMatchChange = jest.fn(); const telemetryService = new TelemetryService({ diff --git a/src/plugins/telemetry_management_section/public/components/telemetry_management_section.tsx b/src/plugins/telemetry_management_section/public/components/telemetry_management_section.tsx index db104e9c7baab..822d8b49661c1 100644 --- a/src/plugins/telemetry_management_section/public/components/telemetry_management_section.tsx +++ b/src/plugins/telemetry_management_section/public/components/telemetry_management_section.tsx @@ -34,7 +34,8 @@ import { i18n } from '@kbn/i18n'; import { TelemetryPluginSetup } from 'src/plugins/telemetry/public'; import { PRIVACY_STATEMENT_URL } from '../../../telemetry/common/constants'; import { OptInExampleFlyout } from './opt_in_example_flyout'; -import { Field } from '../../../advanced_settings/public'; +import { OptInSecurityExampleFlyout } from './opt_in_security_example_flyout'; +import { LazyField } from '../../../advanced_settings/public'; import { ToastsStart } from '../../../../core/public'; type TelemetryService = TelemetryPluginSetup['telemetryService']; @@ -53,6 +54,7 @@ interface Props { interface State { processing: boolean; showExample: boolean; + showSecurityExample: boolean; queryMatches: boolean | null; enabled: boolean; } @@ -61,6 +63,7 @@ export class TelemetryManagementSection extends Component { state: State = { processing: false, showExample: false, + showSecurityExample: false, queryMatches: null, enabled: this.props.telemetryService.getIsOptedIn() || false, }; @@ -87,7 +90,7 @@ export class TelemetryManagementSection extends Component { render() { const { telemetryService } = this.props; - const { showExample, queryMatches, enabled, processing } = this.state; + const { showExample, showSecurityExample, queryMatches, enabled, processing } = this.state; if (!telemetryService.getCanChangeOptInStatus()) { return null; @@ -105,6 +108,7 @@ export class TelemetryManagementSection extends Component { onClose={this.toggleExample} /> )} + {showSecurityExample && } @@ -119,7 +123,7 @@ export class TelemetryManagementSection extends Component { {this.maybeGetAppliesSettingMessage()} - { />

- - - + + + + ), + endpointSecurityData: ( + + + + ), + }} + />

); @@ -245,6 +262,12 @@ export class TelemetryManagementSection extends Component { showExample: !this.state.showExample, }); }; + + toggleSecurityExample = () => { + this.setState({ + showSecurityExample: !this.state.showSecurityExample, + }); + }; } // required for lazy loading diff --git a/src/plugins/tile_map/kibana.json b/src/plugins/tile_map/kibana.json index 9881a2dd72308..d65cb65fd3042 100644 --- a/src/plugins/tile_map/kibana.json +++ b/src/plugins/tile_map/kibana.json @@ -10,11 +10,12 @@ "expressions", "mapsLegacy", "kibanaLegacy", - "data" + "data", + "share" ], "requiredBundles": [ "kibanaUtils", - "kibanaReact", - "charts" + "charts", + "visDefaultEditor" ] } diff --git a/src/plugins/tile_map/public/components/tile_map_options.tsx b/src/plugins/tile_map/public/components/tile_map_options.tsx index f7fb4daff63f0..1a7b11ccf6e20 100644 --- a/src/plugins/tile_map/public/components/tile_map_options.tsx +++ b/src/plugins/tile_map/public/components/tile_map_options.tsx @@ -76,7 +76,7 @@ function TileMapOptions(props: TileMapOptionsProps) { | undefined; + try { + mapsTileMapUrlGenerator = getShareService().urlGenerators.getUrlGenerator( + 'MAPS_APP_TILE_MAP_URL_GENERATOR' + ); + } catch (error) { + // ignore error thrown when url generator is not available + } + + const title = i18n.translate('tileMap.vis.mapTitle', { + defaultMessage: 'Coordinate Map', + }); + + async function onClick(e: React.MouseEvent) { + e.preventDefault(); + + const query = getQueryService(); + const createUrlParams: { [key: string]: any } = { + label: vis.title ? vis.title : title, + mapType: vis.params.mapType, + colorSchema: vis.params.colorSchema, + indexPatternId: vis.data.indexPattern?.id, + metricAgg: 'count', + filters: query.filterManager.getFilters(), + query: query.queryString.getQuery(), + timeRange: query.timefilter.timefilter.getTime(), + }; + + const bucketAggs = vis.data?.aggs?.byType('buckets'); + if (bucketAggs?.length && bucketAggs[0].type.dslName === 'geohash_grid') { + createUrlParams.geoFieldName = bucketAggs[0].getField()?.name; + } else if (vis.data.indexPattern) { + // attempt to default to first geo point field when geohash is not configured yet + const geoField = vis.data.indexPattern.fields.find((field) => { + return ( + !indexPatterns.isNestedField(field) && field.aggregatable && field.type === 'geo_point' + ); + }); + if (geoField) { + createUrlParams.geoFieldName = geoField.name; + } + } + + const metricAggs = vis.data?.aggs?.byType('metrics'); + if (metricAggs?.length) { + createUrlParams.metricAgg = metricAggs[0].type.dslName; + createUrlParams.metricFieldName = metricAggs[0].getField()?.name; + } + + const url = await mapsTileMapUrlGenerator!.createUrl(createUrlParams); + getCoreService().application.navigateToUrl(url); + } + + return ( + + ); +} diff --git a/src/plugins/tile_map/public/markers/geohash_grid.js b/src/plugins/tile_map/public/markers/geohash_grid.js index 46e7987c601f5..d81e435a6dd5d 100644 --- a/src/plugins/tile_map/public/markers/geohash_grid.js +++ b/src/plugins/tile_map/public/markers/geohash_grid.js @@ -18,11 +18,10 @@ */ import { ScaledCirclesMarkers } from './scaled_circles'; -import { L } from '../../../maps_legacy/public'; export class GeohashGridMarkers extends ScaledCirclesMarkers { getMarkerFunction() { - return function (feature) { + return (feature) => { const geohashRect = feature.properties.geohash_meta.rectangle; // get bounds from northEast[3] and southWest[1] // corners in geohash rectangle @@ -30,7 +29,7 @@ export class GeohashGridMarkers extends ScaledCirclesMarkers { [geohashRect[3][0], geohashRect[3][1]], [geohashRect[1][0], geohashRect[1][1]], ]; - return L.rectangle(corners); + return this._leaflet.rectangle(corners); }; } } diff --git a/src/plugins/tile_map/public/markers/heatmap.js b/src/plugins/tile_map/public/markers/heatmap.js index f2d014797bce0..79bbee16548ac 100644 --- a/src/plugins/tile_map/public/markers/heatmap.js +++ b/src/plugins/tile_map/public/markers/heatmap.js @@ -20,7 +20,6 @@ import _ from 'lodash'; import d3 from 'd3'; import { EventEmitter } from 'events'; -import { L } from '../../../maps_legacy/public'; /** * Map overlay: canvas layer with leaflet.heat plugin @@ -30,17 +29,17 @@ import { L } from '../../../maps_legacy/public'; * @param params {Object} */ export class HeatmapMarkers extends EventEmitter { - constructor(featureCollection, options, zoom, max) { + constructor(featureCollection, options, zoom, max, leaflet) { super(); this._geojsonFeatureCollection = featureCollection; const points = dataToHeatArray(featureCollection, max); - this._leafletLayer = new L.HeatLayer(points, options); + this._leafletLayer = new leaflet.HeatLayer(points, options); this._tooltipFormatter = options.tooltipFormatter; this._zoom = zoom; this._disableTooltips = false; this._getLatLng = _.memoize( function (feature) { - return L.latLng(feature.geometry.coordinates[1], feature.geometry.coordinates[0]); + return leaflet.latLng(feature.geometry.coordinates[1], feature.geometry.coordinates[0]); }, function (feature) { // turn coords into a string for the memoize cache diff --git a/src/plugins/tile_map/public/markers/scaled_circles.js b/src/plugins/tile_map/public/markers/scaled_circles.js index cb111107f6fe3..4a5f1b452580b 100644 --- a/src/plugins/tile_map/public/markers/scaled_circles.js +++ b/src/plugins/tile_map/public/markers/scaled_circles.js @@ -21,7 +21,7 @@ import _ from 'lodash'; import d3 from 'd3'; import $ from 'jquery'; import { EventEmitter } from 'events'; -import { L, colorUtil } from '../../../maps_legacy/public'; +import { colorUtil } from '../../../maps_legacy/public'; import { truncatedColorMaps } from '../../../charts/public'; export class ScaledCirclesMarkers extends EventEmitter { @@ -31,14 +31,13 @@ export class ScaledCirclesMarkers extends EventEmitter { options, targetZoom, kibanaMap, - metricAgg + leaflet ) { super(); this._featureCollection = featureCollection; this._featureCollectionMetaData = featureCollectionMetaData; this._zoom = targetZoom; - this._metricAgg = metricAgg; this._valueFormatter = options.valueFormatter || @@ -55,6 +54,7 @@ export class ScaledCirclesMarkers extends EventEmitter { this._legendColors = null; this._legendQuantizer = null; + this._leaflet = leaflet; this._popups = []; @@ -72,7 +72,7 @@ export class ScaledCirclesMarkers extends EventEmitter { return kibanaMap.isInside(bucketRectBounds); }; } - this._leafletLayer = L.geoJson(null, layerOptions); + this._leafletLayer = this._leaflet.geoJson(null, layerOptions); this._leafletLayer.addData(this._featureCollection); } @@ -143,7 +143,7 @@ export class ScaledCirclesMarkers extends EventEmitter { mouseover: (e) => { const layer = e.target; // bring layer to front if not older browser - if (!L.Browser.ie && !L.Browser.opera) { + if (!this._leaflet.Browser.ie && !this._leaflet.Browser.opera) { layer.bringToFront(); } this._showTooltip(feature); @@ -170,7 +170,10 @@ export class ScaledCirclesMarkers extends EventEmitter { return; } - const latLng = L.latLng(feature.geometry.coordinates[1], feature.geometry.coordinates[0]); + const latLng = this._leaflet.latLng( + feature.geometry.coordinates[1], + feature.geometry.coordinates[0] + ); this.emit('showTooltip', { content: content, position: latLng, @@ -182,7 +185,7 @@ export class ScaledCirclesMarkers extends EventEmitter { return (feature, latlng) => { const value = feature.properties.value; const scaledRadius = this._radiusScale(value) * scaleFactor; - return L.circleMarker(latlng).setRadius(scaledRadius); + return this._leaflet.circleMarker(latlng).setRadius(scaledRadius); }; } diff --git a/src/plugins/tile_map/public/markers/shaded_circles.js b/src/plugins/tile_map/public/markers/shaded_circles.js index 745d0422856c6..3468cab7d8b75 100644 --- a/src/plugins/tile_map/public/markers/shaded_circles.js +++ b/src/plugins/tile_map/public/markers/shaded_circles.js @@ -19,7 +19,6 @@ import _ from 'lodash'; import { ScaledCirclesMarkers } from './scaled_circles'; -import { L } from '../../../maps_legacy/public'; export class ShadedCirclesMarkers extends ScaledCirclesMarkers { getMarkerFunction() { @@ -27,7 +26,7 @@ export class ShadedCirclesMarkers extends ScaledCirclesMarkers { const scaleFactor = 0.8; return (feature, latlng) => { const radius = this._geohashMinDistance(feature) * scaleFactor; - return L.circle(latlng, radius); + return this._leaflet.circle(latlng, radius); }; } @@ -49,12 +48,12 @@ export class ShadedCirclesMarkers extends ScaledCirclesMarkers { // clockwise, each value being an array of [lat, lng] // center lat and southeast lng - const east = L.latLng([centerPoint[0], geohashRect[2][1]]); + const east = this._leaflet.latLng([centerPoint[0], geohashRect[2][1]]); // southwest lat and center lng - const north = L.latLng([geohashRect[3][0], centerPoint[1]]); + const north = this._leaflet.latLng([geohashRect[3][0], centerPoint[1]]); // get latLng of geohash center point - const center = L.latLng([centerPoint[0], centerPoint[1]]); + const center = this._leaflet.latLng([centerPoint[0], centerPoint[1]]); // get smallest radius at center of geohash grid rectangle const eastRadius = Math.floor(center.distanceTo(east)); diff --git a/src/plugins/tile_map/public/plugin.ts b/src/plugins/tile_map/public/plugin.ts index 9a164f8a303f8..dfcafafbe47f7 100644 --- a/src/plugins/tile_map/public/plugin.ts +++ b/src/plugins/tile_map/public/plugin.ts @@ -34,8 +34,15 @@ import { createTileMapFn } from './tile_map_fn'; import { createTileMapTypeDefinition } from './tile_map_type'; import { IServiceSettings, MapsLegacyPluginSetup } from '../../maps_legacy/public'; import { DataPublicPluginStart } from '../../data/public'; -import { setFormatService, setQueryService, setKibanaLegacy } from './services'; +import { + setCoreService, + setFormatService, + setQueryService, + setKibanaLegacy, + setShareService, +} from './services'; import { KibanaLegacyStart } from '../../kibana_legacy/public'; +import { SharePluginStart } from '../../share/public'; export interface TileMapConfigType { tilemap: any; @@ -47,7 +54,7 @@ interface TileMapVisualizationDependencies { getZoomPrecision: any; getPrecision: any; BaseMapsVisualization: any; - serviceSettings: IServiceSettings; + getServiceSettings: () => Promise; } /** @internal */ @@ -61,6 +68,7 @@ export interface TileMapPluginSetupDependencies { export interface TileMapPluginStartDependencies { data: DataPublicPluginStart; kibanaLegacy: KibanaLegacyStart; + share: SharePluginStart; } export interface TileMapPluginSetup { @@ -81,13 +89,13 @@ export class TileMapPlugin implements Plugin = { getZoomPrecision, getPrecision, BaseMapsVisualization: mapsLegacy.getBaseMapsVis(), uiSettings: core.uiSettings, - serviceSettings, + getServiceSettings, }; expressions.registerFunction(() => createTileMapFn(visualizationDependencies)); @@ -100,10 +108,12 @@ export class TileMapPlugin implements Plugin('Core'); export const [getFormatService, setFormatService] = createGetterSetter< DataPublicPluginStart['fieldFormats'] @@ -29,6 +33,8 @@ export const [getQueryService, setQueryService] = createGetterSetter< DataPublicPluginStart['query'] >('Query'); +export const [getShareService, setShareService] = createGetterSetter('Share'); + export const [getKibanaLegacy, setKibanaLegacy] = createGetterSetter( 'KibanaLegacy' ); diff --git a/src/plugins/tile_map/public/tile_map_type.js b/src/plugins/tile_map/public/tile_map_type.js index f76da26022a77..c5e3f0d578e30 100644 --- a/src/plugins/tile_map/public/tile_map_type.js +++ b/src/plugins/tile_map/public/tile_map_type.js @@ -25,13 +25,15 @@ import { createTileMapVisualization } from './tile_map_visualization'; import { TileMapOptions } from './components/tile_map_options'; import { supportsCssFilters } from './css_filters'; import { truncatedColorSchemas } from '../../charts/public'; +import { getDeprecationMessage } from './get_deprecation_message'; export function createTileMapTypeDefinition(dependencies) { const CoordinateMapsVisualization = createTileMapVisualization(dependencies); - const { uiSettings, serviceSettings } = dependencies; + const { uiSettings, getServiceSettings } = dependencies; return { name: 'tile_map', + getInfoMessage: getDeprecationMessage, title: i18n.translate('tileMap.vis.mapTitle', { defaultMessage: 'Coordinate Map', }), @@ -53,7 +55,6 @@ export function createTileMapTypeDefinition(dependencies) { wms: uiSettings.get('visualization:tileMap:WMSdefaults'), }, }, - requiresPartialRows: true, visualization: CoordinateMapsVisualization, responseHandler: convertToGeoJson, editorConfig: { @@ -142,6 +143,7 @@ export function createTileMapTypeDefinition(dependencies) { let tmsLayers; try { + const serviceSettings = await getServiceSettings(); tmsLayers = await serviceSettings.getTMSServices(); } catch (e) { return vis; diff --git a/src/plugins/tile_map/public/tile_map_visualization.js b/src/plugins/tile_map/public/tile_map_visualization.js index 2ebb76d05c219..b09a2f3bac48f 100644 --- a/src/plugins/tile_map/public/tile_map_visualization.js +++ b/src/plugins/tile_map/public/tile_map_visualization.js @@ -17,12 +17,42 @@ * under the License. */ -import { get } from 'lodash'; -import { GeohashLayer } from './geohash_layer'; +import { get, round } from 'lodash'; import { getFormatService, getQueryService, getKibanaLegacy } from './services'; -import { scaleBounds, geoContains, mapTooltipProvider } from '../../maps_legacy/public'; +import { + geoContains, + mapTooltipProvider, + lazyLoadMapsLegacyModules, +} from '../../maps_legacy/public'; import { tooltipFormatter } from './tooltip_formatter'; +function scaleBounds(bounds) { + const scale = 0.5; // scale bounds by 50% + + const topLeft = bounds.top_left; + const bottomRight = bounds.bottom_right; + let latDiff = round(Math.abs(topLeft.lat - bottomRight.lat), 5); + const lonDiff = round(Math.abs(bottomRight.lon - topLeft.lon), 5); + // map height can be zero when vis is first created + if (latDiff === 0) latDiff = lonDiff; + + const latDelta = latDiff * scale; + let topLeftLat = round(topLeft.lat, 5) + latDelta; + if (topLeftLat > 90) topLeftLat = 90; + let bottomRightLat = round(bottomRight.lat, 5) - latDelta; + if (bottomRightLat < -90) bottomRightLat = -90; + const lonDelta = lonDiff * scale; + let topLeftLon = round(topLeft.lon, 5) - lonDelta; + if (topLeftLon < -180) topLeftLon = -180; + let bottomRightLon = round(bottomRight.lon, 5) + lonDelta; + if (bottomRightLon > 180) bottomRightLon = 180; + + return { + top_left: { lat: topLeftLat, lon: topLeftLon }, + bottom_right: { lat: bottomRightLat, lon: bottomRightLon }, + }; +} + export const createTileMapVisualization = (dependencies) => { const { getZoomPrecision, getPrecision, BaseMapsVisualization } = dependencies; @@ -147,7 +177,9 @@ export const createTileMapVisualization = (dependencies) => { this._recreateGeohashLayer(); } - _recreateGeohashLayer() { + async _recreateGeohashLayer() { + const { GeohashLayer } = await import('./geohash_layer'); + if (this._geohashLayer) { this._kibanaMap.removeLayer(this._geohashLayer); this._geohashLayer = null; @@ -158,7 +190,8 @@ export const createTileMapVisualization = (dependencies) => { this._geoJsonFeatureCollectionAndMeta.meta, geohashOptions, this._kibanaMap.getZoomLevel(), - this._kibanaMap + this._kibanaMap, + (await lazyLoadMapsLegacyModules()).L ); this._kibanaMap.addLayer(this._geohashLayer); } diff --git a/src/plugins/timelion/public/index.scss b/src/plugins/timelion/public/index.scss index 6bf7133287c51..f39e0c18a2870 100644 --- a/src/plugins/timelion/public/index.scss +++ b/src/plugins/timelion/public/index.scss @@ -10,3 +10,9 @@ @import './app'; @import './base'; @import './directives/index'; + +// these styles is needed to be loaded here explicitly if the timelion visualization was not opened in browser +// styles for timelion visualization are lazy loaded only while a vis is opened +// this will duplicate styles only if both Timelion app and timelion visualization are loaded +// could be left here as it is since the Timelion app is deprecated +@import '../../vis_type_timelion/public/components/index.scss'; diff --git a/src/plugins/timelion/public/plugin.ts b/src/plugins/timelion/public/plugin.ts index 24d1b9eb3fb65..7656a808dfb00 100644 --- a/src/plugins/timelion/public/plugin.ts +++ b/src/plugins/timelion/public/plugin.ts @@ -28,6 +28,7 @@ import { AppMountParameters, AppUpdater, ScopedHistory, + AppNavLinkStatus, } from '../../../core/public'; import { Panel } from './panels/panel'; import { initAngularBootstrap, KibanaLegacyStart } from '../../kibana_legacy/public'; @@ -35,7 +36,10 @@ import { createKbnUrlTracker } from '../../kibana_utils/public'; import { DataPublicPluginStart, esFilters, DataPublicPluginSetup } from '../../data/public'; import { NavigationPublicPluginStart } from '../../navigation/public'; import { VisualizationsStart } from '../../visualizations/public'; -import { VisTypeTimelionPluginStart } from '../../vis_type_timelion/public'; +import { + VisTypeTimelionPluginStart, + VisTypeTimelionPluginSetup, +} from '../../vis_type_timelion/public'; export interface TimelionPluginDependencies { data: DataPublicPluginStart; @@ -55,7 +59,13 @@ export class TimelionPlugin implements Plugin { this.initializerContext = initializerContext; } - public setup(core: CoreSetup, { data }: { data: DataPublicPluginSetup }) { + public setup( + core: CoreSetup, + { + data, + visTypeTimelion, + }: { data: DataPublicPluginSetup; visTypeTimelion: VisTypeTimelionPluginSetup } + ) { const timelionPanels: Map = new Map(); const { appMounted, appUnMounted, stop: stopUrlTracker } = createKbnUrlTracker({ @@ -93,7 +103,8 @@ export class TimelionPlugin implements Plugin { defaultPath: '#/', euiIconType: 'logoKibana', category: DEFAULT_APP_CATEGORIES.kibana, - updater$: this.appStateUpdater.asObservable(), + navLinkStatus: + visTypeTimelion.isUiEnabled === false ? AppNavLinkStatus.hidden : AppNavLinkStatus.default, mount: async (params: AppMountParameters) => { const [coreStart, pluginsStart] = await core.getStartServices(); this.currentHistory = params.history; diff --git a/src/plugins/ui_actions/README.asciidoc b/src/plugins/ui_actions/README.asciidoc new file mode 100644 index 0000000000000..577aa2eae354b --- /dev/null +++ b/src/plugins/ui_actions/README.asciidoc @@ -0,0 +1,26 @@ +[[uiactions-plugin]] +== UI Actions + +An API for: + +- creating custom functionality (`actions`) +- creating custom user interaction events (`triggers`) +- attaching and detaching `actions` to `triggers`. +- emitting `trigger` events +- executing `actions` attached to a given `trigger`. +- exposing a context menu for the user to choose the appropriate action when there are multiple actions attached to a single trigger. + +=== Examples + +https://github.com/elastic/kibana/blob/master/examples/ui_action_examples/README.md[ui_action examples] + +=== API Docs + +==== Server API +https://github.com/elastic/kibana/blob/master/docs/development/plugins/ui_actions/server/kibana-plugin-plugins-ui_actions-server.uiactionssetup.md[Browser Setup contract] +https://github.com/elastic/kibana/blob/master/docs/development/plugins/ui_actions/server/kibana-plugin-plugins-ui_actions-server.uiactionsstart.md[Browser Start contract] + +==== Browser API +https://github.com/elastic/kibana/blob/master/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionssetup.md[Browser Setup contract] +https://github.com/elastic/kibana/blob/master/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsstart.md[Browser Start contract] + diff --git a/src/plugins/ui_actions/README.md b/src/plugins/ui_actions/README.md deleted file mode 100644 index c4e02b551c884..0000000000000 --- a/src/plugins/ui_actions/README.md +++ /dev/null @@ -1,10 +0,0 @@ -# UI Actions - -An API for: - -- creating custom functionality (`actions`) -- creating custom user interaction events (`triggers`) -- attaching and detaching `actions` to `triggers`. -- emitting `trigger` events -- executing `actions` attached to a given `trigger`. -- exposing a context menu for the user to choose the appropriate action when there are multiple actions attached to a single trigger. diff --git a/src/plugins/ui_actions/public/actions/action_internal.ts b/src/plugins/ui_actions/public/actions/action_internal.ts index a22b3fa5b0367..fe7c986bdb7ef 100644 --- a/src/plugins/ui_actions/public/actions/action_internal.ts +++ b/src/plugins/ui_actions/public/actions/action_internal.ts @@ -20,7 +20,7 @@ // @ts-ignore import React from 'react'; import { Action, ActionContext as Context, ActionDefinition } from './action'; -import { Presentable } from '../util/presentable'; +import { Presentable, PresentableGrouping } from '../util/presentable'; import { uiToReactComponent } from '../../../kibana_react/public'; import { ActionType } from '../types'; @@ -36,6 +36,7 @@ export class ActionInternal public readonly order: number = this.definition.order || 0; public readonly MenuItem? = this.definition.MenuItem; public readonly ReactMenuItem? = this.MenuItem ? uiToReactComponent(this.MenuItem) : undefined; + public readonly grouping?: PresentableGrouping> = this.definition.grouping; public execute(context: Context) { return this.definition.execute(context); diff --git a/src/plugins/ui_actions/public/context_menu/build_eui_context_menu_panels.test.ts b/src/plugins/ui_actions/public/context_menu/build_eui_context_menu_panels.test.ts index a513bb3c95f24..3a598b547e343 100644 --- a/src/plugins/ui_actions/public/context_menu/build_eui_context_menu_panels.test.ts +++ b/src/plugins/ui_actions/public/context_menu/build_eui_context_menu_panels.test.ts @@ -17,6 +17,7 @@ * under the License. */ +import { EuiContextMenuPanelDescriptor } from '@elastic/eui'; import { buildContextMenuForActions } from './build_eui_context_menu_panels'; import { Action, createAction } from '../actions'; @@ -25,9 +26,9 @@ const createTestAction = ({ dispayName, order, }: { - type: string; + type?: string; dispayName: string; - order: number; + order?: number; }) => createAction({ type: type as any, // mapping doesn't matter for this test @@ -36,32 +37,36 @@ const createTestAction = ({ execute: async () => {}, }); -test('contextMenu actions sorting: order, type, displayName', async () => { +const resultMapper = (panel: EuiContextMenuPanelDescriptor) => ({ + items: panel.items ? panel.items.map((item) => ({ name: item.name })) : [], +}); + +test('sorts items in DESC order by "order" field first, then by display name', async () => { const actions: Action[] = [ createTestAction({ - order: 100, - type: '1', - dispayName: 'a', + order: 1, + type: 'foo', + dispayName: 'a-1', }), createTestAction({ - order: 100, - type: '1', - dispayName: 'b', + order: 2, + type: 'foo', + dispayName: 'a-2', }), createTestAction({ - order: 0, - type: '2', - dispayName: 'c', + order: 3, + type: 'foo', + dispayName: 'a-3', }), createTestAction({ - order: 0, - type: '2', - dispayName: 'd', + order: 2, + type: 'foo', + dispayName: 'b-2', }), createTestAction({ - order: 0, - type: '3', - dispayName: 'aa', + order: 2, + type: 'foo', + dispayName: 'c-2', }), ].sort(() => 0.5 - Math.random()); @@ -69,13 +74,166 @@ test('contextMenu actions sorting: order, type, displayName', async () => { actions: actions.map((action) => ({ action, context: {}, trigger: '' as any })), }); - expect(result.items?.map((item) => item.name as string)).toMatchInlineSnapshot(` + expect(result.map(resultMapper)).toMatchInlineSnapshot(` + Array [ + Object { + "items": Array [ + Object { + "name": "a-3", + }, + Object { + "name": "a-2", + }, + Object { + "name": "b-2", + }, + Object { + "name": "More", + }, + ], + }, + Object { + "items": Array [ + Object { + "name": "c-2", + }, + Object { + "name": "a-1", + }, + ], + }, + ] + `); +}); + +test('builds empty menu when no actions provided', async () => { + const menu = await buildContextMenuForActions({ + actions: [], + closeMenu: () => {}, + }); + + expect(menu.map(resultMapper)).toMatchInlineSnapshot(` + Array [ + Object { + "items": Array [], + }, + ] + `); +}); + +test('can build menu with one action', async () => { + const menu = await buildContextMenuForActions({ + actions: [ + { + action: createTestAction({ + dispayName: 'Foo', + }), + context: {}, + trigger: 'TETS_TRIGGER' as any, + }, + ], + closeMenu: () => {}, + }); + + expect(menu.map(resultMapper)).toMatchInlineSnapshot(` + Array [ + Object { + "items": Array [ + Object { + "name": "Foo", + }, + ], + }, + ] + `); +}); + +test('orders items according to "order" field', async () => { + const actions = [ + createTestAction({ + order: 1, + dispayName: 'Foo', + }), + createTestAction({ + order: 2, + dispayName: 'Bar', + }), + ]; + const menu = await buildContextMenuForActions({ + actions: actions.map((action) => ({ action, context: {}, trigger: 'TEST' as any })), + }); + + expect(menu[0].items![0].name).toBe('Bar'); + expect(menu[0].items![1].name).toBe('Foo'); + + const actions2 = [ + createTestAction({ + order: 2, + dispayName: 'Bar', + }), + createTestAction({ + order: 1, + dispayName: 'Foo', + }), + ]; + const menu2 = await buildContextMenuForActions({ + actions: actions2.map((action) => ({ action, context: {}, trigger: 'TEST' as any })), + }); + + expect(menu2[0].items![0].name).toBe('Bar'); + expect(menu2[0].items![1].name).toBe('Foo'); +}); + +test('hides items behind in "More" submenu if there are more than 4 actions', async () => { + const actions = [ + createTestAction({ + dispayName: 'Foo 1', + }), + createTestAction({ + dispayName: 'Foo 2', + }), + createTestAction({ + dispayName: 'Foo 3', + }), + createTestAction({ + dispayName: 'Foo 4', + }), + createTestAction({ + dispayName: 'Foo 5', + }), + ]; + const menu = await buildContextMenuForActions({ + actions: actions.map((action) => ({ action, context: {}, trigger: 'TEST' as any })), + }); + + expect(menu.map(resultMapper)).toMatchInlineSnapshot(` Array [ - "a", - "b", - "c", - "d", - "aa", + Object { + "items": Array [ + Object { + "name": "Foo 1", + }, + Object { + "name": "Foo 2", + }, + Object { + "name": "Foo 3", + }, + Object { + "name": "More", + }, + ], + }, + Object { + "items": Array [ + Object { + "name": "Foo 4", + }, + Object { + "name": "Foo 5", + }, + ], + }, ] `); }); diff --git a/src/plugins/ui_actions/public/context_menu/build_eui_context_menu_panels.tsx b/src/plugins/ui_actions/public/context_menu/build_eui_context_menu_panels.tsx index 3be1ec781cef6..1fdddfc272e94 100644 --- a/src/plugins/ui_actions/public/context_menu/build_eui_context_menu_panels.tsx +++ b/src/plugins/ui_actions/public/context_menu/build_eui_context_menu_panels.tsx @@ -20,10 +20,9 @@ import * as React from 'react'; import { EuiContextMenuPanelDescriptor, EuiContextMenuPanelItemDescriptor } from '@elastic/eui'; import _ from 'lodash'; -import sortBy from 'lodash/sortBy'; import { i18n } from '@kbn/i18n'; import { uiToReactComponent } from '../../../kibana_react/public'; -import { Action } from '../actions'; +import { Action, ActionExecutionContext } from '../actions'; import { Trigger } from '../triggers'; import { BaseContext } from '../types'; @@ -31,6 +30,10 @@ export const defaultTitle = i18n.translate('uiActions.actionPanel.title', { defaultMessage: 'Options', }); +export const txtMore = i18n.translate('uiActions.actionPanel.more', { + defaultMessage: 'More', +}); + interface ActionWithContext { action: Action; context: Context; @@ -41,138 +44,177 @@ interface ActionWithContext { trigger: Trigger; } +type ItemDescriptor = EuiContextMenuPanelItemDescriptor & { + _order: number; + _title?: string; +}; + +type PanelDescriptor = EuiContextMenuPanelDescriptor & { + _level?: number; + _icon?: string; + items: ItemDescriptor[]; +}; + +const onClick = (action: Action, context: ActionExecutionContext, close: () => void) => ( + event: React.MouseEvent +) => { + if (event.currentTarget instanceof HTMLAnchorElement) { + // from react-router's + if ( + !event.defaultPrevented && // onClick prevented default + event.button === 0 && // ignore everything but left clicks + (!event.currentTarget.target || event.currentTarget.target === '_self') && // let browser handle "target=_blank" etc. + !(event.metaKey || event.altKey || event.ctrlKey || event.shiftKey) // ignore clicks with modifier keys + ) { + event.preventDefault(); + action.execute(context); + } + } else action.execute(context); + close(); +}; + /** - * Transforms an array of Actions to the shape EuiContextMenuPanel expects. + * This method adds "More" item to panels, which have more than 4 items; and + * moves all items after the thrird one into that "More" sub-menu. */ -export async function buildContextMenuForActions({ - actions, - title = defaultTitle, - closeMenu = () => {}, -}: { +const wrapMainPanelItemsIntoSubmenu = (panels: Record, id: string) => { + const panel = panels[id]; + if (!panel) return; + const maxItemsBeforeWrapping = 4; + if (!panel.items) return; + if (panel.items.length <= maxItemsBeforeWrapping) return; + const visibleItems = panel.items.slice(0, 3) as ItemDescriptor[]; + const itemsInSubmenu = panel.items.slice(3) as ItemDescriptor[]; + const morePanelId = panel.id + '__more'; + const more: ItemDescriptor = { + name: txtMore, + panel: morePanelId, + icon: 'boxesHorizontal', + 'data-test-subj': `embeddablePanelMore-${id}`, + _order: -1, + }; + panel.items = [...visibleItems, more]; + const subPanel: PanelDescriptor = { + id: morePanelId, + title: panel.title || defaultTitle, + items: itemsInSubmenu, + }; + panels[morePanelId] = subPanel; +}; + +const removeItemMetaFields = (items: ItemDescriptor[]): EuiContextMenuPanelItemDescriptor[] => { + const euiItems: EuiContextMenuPanelItemDescriptor[] = []; + for (const item of items) { + const { _order: omit, _title: omit2, ...rest } = item; + euiItems.push(rest); + } + return euiItems; +}; + +const removePanelMetaFields = (panels: PanelDescriptor[]): EuiContextMenuPanelDescriptor[] => { + const euiPanels: EuiContextMenuPanelDescriptor[] = []; + for (const panel of panels) { + const { _level: omit, _icon: omit2, ...rest } = panel; + euiPanels.push({ ...rest, items: removeItemMetaFields(rest.items) }); + } + return euiPanels; +}; + +export interface BuildContextMenuParams { actions: ActionWithContext[]; title?: string; closeMenu?: () => void; -}): Promise { - const menuItems = await buildEuiContextMenuPanelItems({ - actions, - closeMenu, - }); - - return { - id: 'mainMenu', - title, - items: menuItems, - }; } /** - * Transform an array of Actions into the shape needed to build an EUIContextMenu + * Transforms an array of Actions to the shape EuiContextMenuPanel expects. */ -async function buildEuiContextMenuPanelItems({ +export async function buildContextMenuForActions({ actions, - closeMenu, -}: { - actions: ActionWithContext[]; - closeMenu: () => void; -}) { - actions = sortBy( - actions, - (a) => -1 * (a.action.order ?? 0), - (a) => a.action.type, - (a) => a.action.getDisplayName({ ...a.context, trigger: a.trigger }) - ); - - const items: EuiContextMenuPanelItemDescriptor[] = new Array(actions.length); - const promises = actions.map(async ({ action, context, trigger }, index) => { - const isCompatible = await action.isCompatible({ - ...context, - trigger, - }); - if (!isCompatible) { - return; + title = defaultTitle, + closeMenu = () => {}, +}: BuildContextMenuParams): Promise { + const panels: Record = { + mainMenu: { + id: 'mainMenu', + title, + items: [], + }, + }; + const promises = actions.map(async (item) => { + const { action } = item; + const context: ActionExecutionContext = { ...item.context, trigger: item.trigger }; + const isCompatible = await item.action.isCompatible(context); + if (!isCompatible) return; + let parentPanel = ''; + let currentPanel = ''; + if (action.grouping) { + for (let i = 0; i < action.grouping.length; i++) { + const group = action.grouping[i]; + currentPanel = group.id; + if (!panels[currentPanel]) { + const name = group.getDisplayName ? group.getDisplayName(context) : group.id; + panels[currentPanel] = { + id: currentPanel, + title: name, + items: [], + _level: i, + _icon: group.getIconType ? group.getIconType(context) : 'empty', + }; + if (parentPanel) { + panels[parentPanel].items!.push({ + name, + panel: currentPanel, + icon: group.getIconType ? group.getIconType(context) : 'empty', + _order: group.order || 0, + _title: group.getDisplayName ? group.getDisplayName(context) : '', + }); + } + } + parentPanel = currentPanel; + } } - - items[index] = await convertPanelActionToContextMenuItem({ - action, - actionContext: context, - trigger, - closeMenu, + panels[parentPanel || 'mainMenu'].items!.push({ + name: action.MenuItem + ? React.createElement(uiToReactComponent(action.MenuItem), { context }) + : action.getDisplayName(context), + icon: action.getIconType(context), + 'data-test-subj': `embeddablePanelAction-${action.id}`, + onClick: onClick(action, context, closeMenu), + href: action.getHref ? await action.getHref(context) : undefined, + _order: action.order || 0, + _title: action.getDisplayName(context), }); }); - await Promise.all(promises); - return items.filter(Boolean); -} - -async function convertPanelActionToContextMenuItem({ - action, - actionContext, - trigger, - closeMenu, -}: { - action: Action; - actionContext: Context; - trigger: Trigger; - closeMenu: () => void; -}): Promise { - const menuPanelItem: EuiContextMenuPanelItemDescriptor = { - name: action.MenuItem - ? React.createElement(uiToReactComponent(action.MenuItem), { - context: { - ...actionContext, - trigger, - }, - }) - : action.getDisplayName({ - ...actionContext, - trigger, - }), - icon: action.getIconType({ - ...actionContext, - trigger, - }), - panel: _.get(action, 'childContextMenuPanel.id'), - 'data-test-subj': `embeddablePanelAction-${action.id}`, - }; + for (const panel of Object.values(panels)) { + const items = panel.items.filter(Boolean) as ItemDescriptor[]; + panel.items = _.sortBy( + items, + (a) => -1 * (a._order ?? 0), + (a) => a._title + ); + } - menuPanelItem.onClick = (event) => { - if (event.currentTarget instanceof HTMLAnchorElement) { - // from react-router's - if ( - !event.defaultPrevented && // onClick prevented default - event.button === 0 && // ignore everything but left clicks - (!event.currentTarget.target || event.currentTarget.target === '_self') && // let browser handle "target=_blank" etc. - !(event.metaKey || event.altKey || event.ctrlKey || event.shiftKey) // ignore clicks with modifier keys - ) { - event.preventDefault(); - action.execute({ - ...actionContext, - trigger, + wrapMainPanelItemsIntoSubmenu(panels, 'mainMenu'); + + for (const panel of Object.values(panels)) { + if (panel._level === 0) { + // TODO: Add separator line here once it is available in EUI. + // See https://github.com/elastic/eui/pull/4018 + if (panel.items.length > 3) { + panels.mainMenu.items.push({ + name: panel.title || panel.id, + icon: panel._icon || 'empty', + panel: panel.id, }); } else { - // let browser handle navigation + panels.mainMenu.items.push(...panel.items); } - } else { - // not a link - action.execute({ - ...actionContext, - trigger, - }); - } - - closeMenu(); - }; - - if (action.getHref) { - const href = await action.getHref({ - ...actionContext, - trigger, - }); - if (href) { - menuPanelItem.href = href; } } - return menuPanelItem; + const panelList = Object.values(panels); + return removePanelMetaFields(panelList); } diff --git a/src/plugins/ui_actions/public/index.ts b/src/plugins/ui_actions/public/index.ts index 476ca0ec17066..b9f4a4a0426bf 100644 --- a/src/plugins/ui_actions/public/index.ts +++ b/src/plugins/ui_actions/public/index.ts @@ -33,7 +33,10 @@ export { IncompatibleActionError, } from './actions'; export { buildContextMenuForActions } from './context_menu'; -export { Presentable as UiActionsPresentable } from './util'; +export { + Presentable as UiActionsPresentable, + PresentableGrouping as UiActionsPresentableGrouping, +} from './util'; export { Trigger, TriggerContext, @@ -56,6 +59,7 @@ export { VisualizeFieldContext, ACTION_VISUALIZE_FIELD, ACTION_VISUALIZE_GEO_FIELD, + ACTION_VISUALIZE_LENS_FIELD, } from './types'; export { ActionByType, diff --git a/src/plugins/ui_actions/public/mocks.ts b/src/plugins/ui_actions/public/mocks.ts index 3522ac4941ba0..759430169b613 100644 --- a/src/plugins/ui_actions/public/mocks.ts +++ b/src/plugins/ui_actions/public/mocks.ts @@ -48,6 +48,7 @@ const createStartContract = (): Start => { executeTriggerActions: jest.fn(), fork: jest.fn(), getAction: jest.fn(), + hasAction: jest.fn(), getTrigger: jest.fn(), getTriggerActions: jest.fn((id: TriggerId) => []), getTriggerCompatibleActions: jest.fn(), diff --git a/src/plugins/ui_actions/public/public.api.md b/src/plugins/ui_actions/public/public.api.md new file mode 100644 index 0000000000000..229997281db49 --- /dev/null +++ b/src/plugins/ui_actions/public/public.api.md @@ -0,0 +1,344 @@ +## API Report File for "kibana" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts + +import { CoreSetup } from 'src/core/public'; +import { CoreStart } from 'src/core/public'; +import { EnvironmentMode } from '@kbn/config'; +import { EuiContextMenuPanelDescriptor } from '@elastic/eui'; +import { Observable } from 'rxjs'; +import { PackageInfo } from '@kbn/config'; +import { Plugin } from 'src/core/public'; +import { PluginInitializerContext as PluginInitializerContext_2 } from 'src/core/public'; +import React from 'react'; +import * as Rx from 'rxjs'; +import { UiComponent } from 'src/plugins/kibana_utils/public'; + +// Warning: (ae-forgotten-export) The symbol "BaseContext" needs to be exported by the entry point index.d.ts +// Warning: (ae-missing-release-tag) "Action" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export interface Action extends Partial>> { + execute(context: ActionExecutionContext): Promise; + getDisplayName(context: ActionExecutionContext): string; + getHref?(context: ActionExecutionContext): Promise; + getIconType(context: ActionExecutionContext): string | undefined; + id: string; + isCompatible(context: ActionExecutionContext): Promise; + MenuItem?: UiComponent<{ + context: ActionExecutionContext; + }>; + order?: number; + shouldAutoExecute?(context: ActionExecutionContext): Promise; + readonly type: T; +} + +// Warning: (ae-missing-release-tag) "ACTION_VISUALIZE_FIELD" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export const ACTION_VISUALIZE_FIELD = "ACTION_VISUALIZE_FIELD"; + +// Warning: (ae-missing-release-tag) "ACTION_VISUALIZE_GEO_FIELD" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export const ACTION_VISUALIZE_GEO_FIELD = "ACTION_VISUALIZE_GEO_FIELD"; + +// Warning: (ae-missing-release-tag) "ACTION_VISUALIZE_LENS_FIELD" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export const ACTION_VISUALIZE_LENS_FIELD = "ACTION_VISUALIZE_LENS_FIELD"; + +// Warning: (ae-missing-release-tag) "ActionByType" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type ActionByType = Action; + +// Warning: (ae-missing-release-tag) "ActionContextMapping" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export interface ActionContextMapping { + // Warning: (ae-forgotten-export) The symbol "DEFAULT_ACTION" needs to be exported by the entry point index.d.ts + // + // (undocumented) + [DEFAULT_ACTION]: BaseContext; + // (undocumented) + [ACTION_VISUALIZE_FIELD]: VisualizeFieldContext; + // (undocumented) + [ACTION_VISUALIZE_GEO_FIELD]: VisualizeFieldContext; + // (undocumented) + [ACTION_VISUALIZE_LENS_FIELD]: VisualizeFieldContext; +} + +// Warning: (ae-missing-release-tag) "ActionDefinitionByType" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type ActionDefinitionByType = UiActionsActionDefinition; + +// Warning: (ae-missing-release-tag) "ActionExecutionContext" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export type ActionExecutionContext = Context & ActionExecutionMeta; + +// Warning: (ae-missing-release-tag) "ActionExecutionMeta" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export interface ActionExecutionMeta { + trigger: Trigger; +} + +// Warning: (ae-missing-release-tag) "ActionType" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type ActionType = keyof ActionContextMapping; + +// Warning: (ae-missing-release-tag) "APPLY_FILTER_TRIGGER" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export const APPLY_FILTER_TRIGGER = "FILTER_TRIGGER"; + +// Warning: (ae-missing-release-tag) "applyFilterTrigger" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export const applyFilterTrigger: Trigger<'FILTER_TRIGGER'>; + +// Warning: (ae-forgotten-export) The symbol "BuildContextMenuParams" needs to be exported by the entry point index.d.ts +// Warning: (ae-missing-release-tag) "buildContextMenuForActions" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export function buildContextMenuForActions({ actions, title, closeMenu, }: BuildContextMenuParams): Promise; + +// Warning: (ae-forgotten-export) The symbol "ActionDefinitionByType" needs to be exported by the entry point index.d.ts +// Warning: (ae-missing-release-tag) "createAction" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export function createAction(action: ActionDefinitionByType_2): ActionByType; + +// Warning: (ae-missing-release-tag) "IncompatibleActionError" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export class IncompatibleActionError extends Error { + constructor(); + // (undocumented) + code: string; +} + +// Warning: (ae-forgotten-export) The symbol "PluginInitializerContext" needs to be exported by the entry point index.d.ts +// Warning: (ae-forgotten-export) The symbol "UiActionsPlugin" needs to be exported by the entry point index.d.ts +// Warning: (ae-missing-release-tag) "plugin" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export function plugin(initializerContext: PluginInitializerContext): UiActionsPlugin; + +// Warning: (ae-missing-release-tag) "SELECT_RANGE_TRIGGER" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export const SELECT_RANGE_TRIGGER = "SELECT_RANGE_TRIGGER"; + +// Warning: (ae-missing-release-tag) "selectRangeTrigger" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export const selectRangeTrigger: Trigger<'SELECT_RANGE_TRIGGER'>; + +// Warning: (ae-missing-release-tag) "Trigger" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export interface Trigger { + description?: string; + id: ID; + title?: string; +} + +// Warning: (ae-missing-release-tag) "TriggerContext" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type TriggerContext = T extends TriggerId ? TriggerContextMapping[T] : never; + +// Warning: (ae-missing-release-tag) "TriggerContextMapping" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export interface TriggerContextMapping { + // Warning: (ae-forgotten-export) The symbol "DEFAULT_TRIGGER" needs to be exported by the entry point index.d.ts + // Warning: (ae-forgotten-export) The symbol "TriggerContext" needs to be exported by the entry point index.d.ts + // + // (undocumented) + [DEFAULT_TRIGGER]: TriggerContext_2; + // Warning: (ae-forgotten-export) The symbol "ApplyGlobalFilterActionContext" needs to be exported by the entry point index.d.ts + // + // (undocumented) + [APPLY_FILTER_TRIGGER]: ApplyGlobalFilterActionContext; + // Warning: (ae-forgotten-export) The symbol "RangeSelectContext" needs to be exported by the entry point index.d.ts + // + // (undocumented) + [SELECT_RANGE_TRIGGER]: RangeSelectContext; + // Warning: (ae-forgotten-export) The symbol "ValueClickContext" needs to be exported by the entry point index.d.ts + // + // (undocumented) + [VALUE_CLICK_TRIGGER]: ValueClickContext; + // (undocumented) + [VISUALIZE_FIELD_TRIGGER]: VisualizeFieldContext; + // (undocumented) + [VISUALIZE_GEO_FIELD_TRIGGER]: VisualizeFieldContext; +} + +// Warning: (ae-missing-release-tag) "TriggerId" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type TriggerId = keyof TriggerContextMapping; + +// Warning: (ae-forgotten-export) The symbol "ActionDefinitionContext" needs to be exported by the entry point index.d.ts +// Warning: (ae-missing-release-tag) "ActionDefinition" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export interface UiActionsActionDefinition extends Partial>> { + execute(context: ActionDefinitionContext): Promise; + getHref?(context: ActionDefinitionContext): Promise; + readonly id: string; + isCompatible?(context: ActionDefinitionContext): Promise; + shouldAutoExecute?(context: ActionDefinitionContext): Promise; + readonly type?: ActionType; +} + +// Warning: (ae-missing-release-tag) "Presentable" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export interface UiActionsPresentable { + getDisplayName(context: Context): string; + getDisplayNameTooltip(context: Context): string; + getHref?(context: Context): Promise; + getIconType(context: Context): string | undefined; + readonly grouping?: UiActionsPresentableGrouping; + readonly id: string; + isCompatible(context: Context): Promise; + readonly MenuItem?: UiComponent<{ + context: Context; + }>; + readonly order: number; +} + +// Warning: (ae-forgotten-export) The symbol "PresentableGroup" needs to be exported by the entry point index.d.ts +// Warning: (ae-missing-release-tag) "PresentableGrouping" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type UiActionsPresentableGrouping = Array>; + +// Warning: (ae-missing-release-tag) "UiActionsService" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export class UiActionsService { + constructor({ triggers, actions, triggerToActions, }?: UiActionsServiceParams); + // Warning: (ae-forgotten-export) The symbol "ActionRegistry" needs to be exported by the entry point index.d.ts + // + // (undocumented) + protected readonly actions: ActionRegistry; + readonly addTriggerAction: (triggerId: T, action: UiActionsActionDefinition | Action) => void; + // (undocumented) + readonly attachAction: (triggerId: T, actionId: string) => void; + readonly clear: () => void; + // (undocumented) + readonly detachAction: (triggerId: TriggerId, actionId: string) => void; + // @deprecated (undocumented) + readonly executeTriggerActions: (triggerId: T, context: TriggerContext) => Promise; + // Warning: (ae-forgotten-export) The symbol "UiActionsExecutionService" needs to be exported by the entry point index.d.ts + // + // (undocumented) + readonly executionService: UiActionsExecutionService; + readonly fork: () => UiActionsService; + // (undocumented) + readonly getAction: >(id: string) => Action, "" | "ACTION_VISUALIZE_FIELD" | "ACTION_VISUALIZE_GEO_FIELD" | "ACTION_VISUALIZE_LENS_FIELD" | "ACTION_CUSTOMIZE_PANEL" | "ACTION_ADD_PANEL" | "openInspector" | "deletePanel" | "editPanel" | "togglePanel" | "replacePanel" | "clonePanel" | "addToFromLibrary" | "unlinkFromLibrary" | "ACTION_LIBRARY_NOTIFICATION" | "ACTION_GLOBAL_APPLY_FILTER" | "ACTION_SELECT_RANGE" | "ACTION_VALUE_CLICK">; + // Warning: (ae-forgotten-export) The symbol "TriggerContract" needs to be exported by the entry point index.d.ts + // + // (undocumented) + readonly getTrigger: (triggerId: T) => TriggerContract; + // (undocumented) + readonly getTriggerActions: (triggerId: T) => Action[]; + // (undocumented) + readonly getTriggerCompatibleActions: (triggerId: T, context: TriggerContextMapping[T]) => Promise[]>; + // (undocumented) + readonly hasAction: (actionId: string) => boolean; + // Warning: (ae-forgotten-export) The symbol "ActionContext" needs to be exported by the entry point index.d.ts + // + // (undocumented) + readonly registerAction: >(definition: A) => Action, "" | "ACTION_VISUALIZE_FIELD" | "ACTION_VISUALIZE_GEO_FIELD" | "ACTION_VISUALIZE_LENS_FIELD" | "ACTION_CUSTOMIZE_PANEL" | "ACTION_ADD_PANEL" | "openInspector" | "deletePanel" | "editPanel" | "togglePanel" | "replacePanel" | "clonePanel" | "addToFromLibrary" | "unlinkFromLibrary" | "ACTION_LIBRARY_NOTIFICATION" | "ACTION_GLOBAL_APPLY_FILTER" | "ACTION_SELECT_RANGE" | "ACTION_VALUE_CLICK">; + // (undocumented) + readonly registerTrigger: (trigger: Trigger) => void; + // Warning: (ae-forgotten-export) The symbol "TriggerRegistry" needs to be exported by the entry point index.d.ts + // + // (undocumented) + protected readonly triggers: TriggerRegistry; + // Warning: (ae-forgotten-export) The symbol "TriggerToActionsRegistry" needs to be exported by the entry point index.d.ts + // + // (undocumented) + protected readonly triggerToActions: TriggerToActionsRegistry; + // (undocumented) + readonly unregisterAction: (actionId: string) => void; +} + +// Warning: (ae-missing-release-tag) "UiActionsServiceParams" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export interface UiActionsServiceParams { + // (undocumented) + readonly actions?: ActionRegistry; + // (undocumented) + readonly triggers?: TriggerRegistry; + readonly triggerToActions?: TriggerToActionsRegistry; +} + +// Warning: (ae-missing-release-tag) "UiActionsSetup" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type UiActionsSetup = Pick; + +// Warning: (ae-missing-release-tag) "UiActionsStart" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type UiActionsStart = PublicMethodsOf; + +// Warning: (ae-missing-release-tag) "VALUE_CLICK_TRIGGER" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export const VALUE_CLICK_TRIGGER = "VALUE_CLICK_TRIGGER"; + +// Warning: (ae-missing-release-tag) "valueClickTrigger" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export const valueClickTrigger: Trigger<'VALUE_CLICK_TRIGGER'>; + +// Warning: (ae-missing-release-tag) "VISUALIZE_FIELD_TRIGGER" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export const VISUALIZE_FIELD_TRIGGER = "VISUALIZE_FIELD_TRIGGER"; + +// Warning: (ae-missing-release-tag) "VISUALIZE_GEO_FIELD_TRIGGER" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export const VISUALIZE_GEO_FIELD_TRIGGER = "VISUALIZE_GEO_FIELD_TRIGGER"; + +// Warning: (ae-missing-release-tag) "VisualizeFieldContext" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export interface VisualizeFieldContext { + // (undocumented) + contextualFields?: string[]; + // (undocumented) + fieldName: string; + // (undocumented) + indexPatternId: string; +} + +// Warning: (ae-missing-release-tag) "visualizeFieldTrigger" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export const visualizeFieldTrigger: Trigger<'VISUALIZE_FIELD_TRIGGER'>; + +// Warning: (ae-missing-release-tag) "visualizeGeoFieldTrigger" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export const visualizeGeoFieldTrigger: Trigger<'VISUALIZE_GEO_FIELD_TRIGGER'>; + + +// (No @packageDocumentation comment for this package) + +``` diff --git a/src/plugins/ui_actions/public/service/ui_actions_execution_service.ts b/src/plugins/ui_actions/public/service/ui_actions_execution_service.ts index f65a72f334d07..4f0ab52501a95 100644 --- a/src/plugins/ui_actions/public/service/ui_actions_execution_service.ts +++ b/src/plugins/ui_actions/public/service/ui_actions_execution_service.ts @@ -109,7 +109,7 @@ export class UiActionsExecutionService { } private async executeMultipleActions(tasks: ExecuteActionTask[]) { - const panel = await buildContextMenuForActions({ + const panels = await buildContextMenuForActions({ actions: tasks.map(({ action, context, trigger }) => ({ action, context, @@ -121,7 +121,7 @@ export class UiActionsExecutionService { session.close(); }, }); - const session = openContextMenu([panel], { + const session = openContextMenu(panels, { 'data-test-subj': 'multipleActionsContextMenu', }); } diff --git a/src/plugins/ui_actions/public/service/ui_actions_service.ts b/src/plugins/ui_actions/public/service/ui_actions_service.ts index 6028177964fb7..ec5f3afa19c94 100644 --- a/src/plugins/ui_actions/public/service/ui_actions_service.ts +++ b/src/plugins/ui_actions/public/service/ui_actions_service.ts @@ -99,6 +99,10 @@ export class UiActionsService { this.actions.delete(actionId); }; + public readonly hasAction = (actionId: string): boolean => { + return this.actions.has(actionId); + }; + public readonly attachAction = (triggerId: T, actionId: string): void => { const trigger = this.triggers.get(triggerId); diff --git a/src/plugins/ui_actions/public/tests/execute_trigger_actions.test.ts b/src/plugins/ui_actions/public/tests/execute_trigger_actions.test.ts index 81120990001e3..af2510467ba87 100644 --- a/src/plugins/ui_actions/public/tests/execute_trigger_actions.test.ts +++ b/src/plugins/ui_actions/public/tests/execute_trigger_actions.test.ts @@ -22,7 +22,7 @@ import { openContextMenu } from '../context_menu'; import { uiActionsPluginMock } from '../mocks'; import { Trigger } from '../triggers'; import { TriggerId, ActionType } from '../types'; -import { wait } from '@testing-library/dom'; +import { waitFor } from '@testing-library/dom'; jest.mock('../context_menu'); @@ -85,7 +85,7 @@ test('executes a single action mapped to a trigger', async () => { expect(executeFn).toBeCalledWith(expect.objectContaining(context)); }); -test('throws an error if there are no compatible actions to execute', async () => { +test("doesn't throw an error if there are no compatible actions to execute", async () => { const { setup, doStart } = uiActions; const trigger: Trigger = { id: 'MY-TRIGGER' as TriggerId, @@ -98,9 +98,7 @@ test('throws an error if there are no compatible actions to execute', async () = const start = doStart(); await expect( start.executeTriggerActions('MY-TRIGGER' as TriggerId, context) - ).rejects.toMatchObject( - new Error('No compatible actions found to execute for trigger [triggerId = MY-TRIGGER].') - ); + ).resolves.toBeUndefined(); }); test('does not execute an incompatible action', async () => { @@ -149,7 +147,7 @@ test('shows a context menu when more than one action is mapped to a trigger', as jest.runAllTimers(); - await wait(() => { + await waitFor(() => { expect(executeFn).toBeCalledTimes(0); expect(openContextMenu).toHaveBeenCalledTimes(1); }); @@ -197,7 +195,7 @@ test("doesn't show a context menu for auto executable actions", async () => { jest.runAllTimers(); - await wait(() => { + await waitFor(() => { expect(executeFn).toBeCalledTimes(2); expect(openContextMenu).toHaveBeenCalledTimes(0); }); diff --git a/src/plugins/ui_actions/public/triggers/trigger_internal.ts b/src/plugins/ui_actions/public/triggers/trigger_internal.ts index c91468d31add5..c766b5c798ecb 100644 --- a/src/plugins/ui_actions/public/triggers/trigger_internal.ts +++ b/src/plugins/ui_actions/public/triggers/trigger_internal.ts @@ -35,12 +35,6 @@ export class TriggerInternal { const triggerId = this.trigger.id; const actions = await this.service.getTriggerCompatibleActions!(triggerId, context); - if (!actions.length) { - throw new Error( - `No compatible actions found to execute for trigger [triggerId = ${triggerId}].` - ); - } - await Promise.all([ actions.map((action) => this.service.executionService.execute({ diff --git a/src/plugins/ui_actions/public/types.ts b/src/plugins/ui_actions/public/types.ts index b00f4628ffb96..0be3c19fc1c4d 100644 --- a/src/plugins/ui_actions/public/types.ts +++ b/src/plugins/ui_actions/public/types.ts @@ -57,10 +57,12 @@ export interface TriggerContextMapping { const DEFAULT_ACTION = ''; export const ACTION_VISUALIZE_FIELD = 'ACTION_VISUALIZE_FIELD'; export const ACTION_VISUALIZE_GEO_FIELD = 'ACTION_VISUALIZE_GEO_FIELD'; +export const ACTION_VISUALIZE_LENS_FIELD = 'ACTION_VISUALIZE_LENS_FIELD'; export type ActionType = keyof ActionContextMapping; export interface ActionContextMapping { [DEFAULT_ACTION]: BaseContext; [ACTION_VISUALIZE_FIELD]: VisualizeFieldContext; [ACTION_VISUALIZE_GEO_FIELD]: VisualizeFieldContext; + [ACTION_VISUALIZE_LENS_FIELD]: VisualizeFieldContext; } diff --git a/src/plugins/ui_actions/public/util/presentable.ts b/src/plugins/ui_actions/public/util/presentable.ts index 57070f7673f61..59440d6c75976 100644 --- a/src/plugins/ui_actions/public/util/presentable.ts +++ b/src/plugins/ui_actions/public/util/presentable.ts @@ -68,4 +68,20 @@ export interface Presentable { * the context and should be displayed to user, otherwise resolves to false. */ isCompatible(context: Context): Promise; + + /** + * Grouping where this item should appear as a submenu. Each entry is a new + * sub-menu level. For example, used to show drilldowns and sharing options + * in panel context menu in a sub-menu. + */ + readonly grouping?: PresentableGrouping; } + +export interface PresentableGroup + extends Partial< + Pick, 'getDisplayName' | 'getDisplayNameTooltip' | 'getIconType' | 'order'> + > { + id: string; +} + +export type PresentableGrouping = Array>; diff --git a/src/plugins/url_forwarding/public/forward_app/forward_app.ts b/src/plugins/url_forwarding/public/forward_app/forward_app.ts index 967b18769ebc6..0480317a6b720 100644 --- a/src/plugins/url_forwarding/public/forward_app/forward_app.ts +++ b/src/plugins/url_forwarding/public/forward_app/forward_app.ts @@ -29,6 +29,7 @@ export const createLegacyUrlForwardApp = ( id: 'kibana', chromeless: true, title: 'Legacy URL migration', + appRoute: '/app/kibana#/', navLinkStatus: AppNavLinkStatus.hidden, async mount(params: AppMountParameters) { const hash = params.history.location.hash.substr(1); diff --git a/src/plugins/usage_collection/README.md b/src/plugins/usage_collection/README.md index 0b1cca07de007..aae633a956c48 100644 --- a/src/plugins/usage_collection/README.md +++ b/src/plugins/usage_collection/README.md @@ -63,7 +63,7 @@ All you need to provide is a `type` for organizing your fields, `schema` field t total: 'long', }, }, - fetch: async (callCluster: APICluster) => { + fetch: async (callCluster: APICluster, esClient: IClusterClient) => { // query ES and get some data // summarize the data into a model @@ -86,9 +86,9 @@ Some background: - `MY_USAGE_TYPE` can be any string. It usually matches the plugin name. As a safety mechanism, we double check there are no duplicates at the moment of registering the collector. - The `fetch` method needs to support multiple contexts in which it is called. For example, when stats are pulled from a Kibana Metricbeat module, the Beat calls Kibana's stats API to invoke usage collection. -In this case, the `fetch` method is called as a result of an HTTP API request and `callCluster` wraps `callWithRequest`, where the request headers are expected to have read privilege on the entire `.kibana' index. +In this case, the `fetch` method is called as a result of an HTTP API request and `callCluster` wraps `callWithRequest` or `esClient` wraps `asCurrentUser`, where the request headers are expected to have read privilege on the entire `.kibana' index. -Note: there will be many cases where you won't need to use the `callCluster` function that gets passed in to your `fetch` method at all. Your feature might have an accumulating value in server memory, or read something from the OS, or use other clients like a custom SavedObjects client. In that case it's up to the plugin to initialize those clients like the example below: +Note: there will be many cases where you won't need to use the `callCluster` (or `esClient`) function that gets passed in to your `fetch` method at all. Your feature might have an accumulating value in server memory, or read something from the OS, or use other clients like a custom SavedObjects client. In that case it's up to the plugin to initialize those clients like the example below: ```ts // server/plugin.ts @@ -140,6 +140,14 @@ The `AllowedSchemaTypes` is the list of allowed schema types for the usage field 'keyword', 'text', 'number', 'boolean', 'long', 'date', 'float' ``` +### Arrays + +If any of your properties is an array, the schema definition must follow the convention below: + +``` +{ type: 'array', items: {...mySchemaDefinitionOfTheEntriesInTheArray} } +``` + ### Example ```ts @@ -152,6 +160,8 @@ export const myCollector = makeUsageCollector({ some_obj: { total: 123, }, + some_array: ['value1', 'value2'], + some_array_of_obj: [{total: 123}], }; }, schema: { @@ -163,6 +173,18 @@ export const myCollector = makeUsageCollector({ type: 'number', }, }, + some_array: { + type: 'array', + items: { type: 'keyword' } + }, + some_array_of_obj: { + type: 'array', + items: { + total: { + type: 'number', + }, + }, + }, }, }); ``` @@ -302,4 +324,9 @@ These saved objects are automatically consumed by the stats API and surfaced und By storing these metrics and their counts as key-value pairs, we can add more metrics without having to worry about exceeding the 1000-field soft limit in Elasticsearch. -The only caveat is that it makes it harder to consume in Kibana when analysing each entry in the array separately. In the telemetry team we are working to find a solution to this. We are building a new way of reporting telemetry called [Pulse](../../../rfcs/text/0008_pulse.md) that will help on making these UI-Metrics easier to consume. +The only caveat is that it makes it harder to consume in Kibana when analysing each entry in the array separately. In the telemetry team we are working to find a solution to this. + +# Routes registered by this plugin + +- `/api/ui_metric/report`: Used by `ui_metrics` usage collector instances to report their usage data to the server +- `/api/stats`: Get the metrics and usage ([details](./server/routes/stats/README.md)) diff --git a/src/plugins/usage_collection/server/collector/collector.test.ts b/src/plugins/usage_collection/server/collector/collector.test.ts index a3e2425c1f122..375fe4f7686c0 100644 --- a/src/plugins/usage_collection/server/collector/collector.test.ts +++ b/src/plugins/usage_collection/server/collector/collector.test.ts @@ -153,7 +153,10 @@ describe('collector', () => { isReady: () => false, fetch: () => ({ testPass: [{ name: 'a', value: 100 }] }), schema: { - testPass: { name: { type: 'keyword' }, value: { type: 'long' } }, + testPass: { + type: 'array', + items: { name: { type: 'keyword' }, value: { type: 'long' } }, + }, }, }); expect(collector).toBeDefined(); @@ -166,7 +169,10 @@ describe('collector', () => { fetch: () => ({ testPass: [{ name: 'a', value: 100 }], otherProp: 1 }), // @ts-expect-error schema: { - testPass: { name: { type: 'keyword' }, value: { type: 'long' } }, + testPass: { + type: 'array', + items: { name: { type: 'keyword' }, value: { type: 'long' } }, + }, }, }); expect(collector).toBeDefined(); @@ -185,7 +191,10 @@ describe('collector', () => { }, // @ts-expect-error schema: { - testPass: { name: { type: 'keyword' }, value: { type: 'long' } }, + testPass: { + type: 'array', + items: { name: { type: 'keyword' }, value: { type: 'long' } }, + }, }, }); expect(collector).toBeDefined(); @@ -203,7 +212,10 @@ describe('collector', () => { return { otherProp: 1 }; }, schema: { - testPass: { name: { type: 'keyword' }, value: { type: 'long' } }, + testPass: { + type: 'array', + items: { name: { type: 'keyword' }, value: { type: 'long' } }, + }, otherProp: { type: 'long' }, }, }); diff --git a/src/plugins/usage_collection/server/collector/collector.ts b/src/plugins/usage_collection/server/collector/collector.ts index d57700024c088..8491bdb0c957c 100644 --- a/src/plugins/usage_collection/server/collector/collector.ts +++ b/src/plugins/usage_collection/server/collector/collector.ts @@ -17,7 +17,7 @@ * under the License. */ -import { Logger, LegacyAPICaller } from 'kibana/server'; +import { Logger, LegacyAPICaller, ElasticsearchClient } from 'kibana/server'; export type CollectorFormatForBulkUpload = (result: T) => { type: string; payload: U }; @@ -38,17 +38,18 @@ export type RecursiveMakeSchemaFrom = U extends object ? MakeSchemaFrom : { type: AllowedSchemaTypes }; +// Using Required to enforce all optional keys in the object export type MakeSchemaFrom = { - [Key in keyof Base]: Base[Key] extends Array - ? RecursiveMakeSchemaFrom - : RecursiveMakeSchemaFrom; + [Key in keyof Required]: Required[Key] extends Array + ? { type: 'array'; items: RecursiveMakeSchemaFrom } + : RecursiveMakeSchemaFrom[Key]>; }; export interface CollectorOptions { type: string; init?: Function; - schema?: MakeSchemaFrom>; // Using Required to enforce all optional keys in the object - fetch: (callCluster: LegacyAPICaller) => Promise | T; + schema?: MakeSchemaFrom; + fetch: (callCluster: LegacyAPICaller, esClient?: ElasticsearchClient) => Promise | T; /* * A hook for allowing the fetched data payload to be organized into a typed * data model for internal bulk upload. See defaultFormatterForBulkUpload for diff --git a/src/plugins/usage_collection/server/collector/collector_set.test.ts b/src/plugins/usage_collection/server/collector/collector_set.test.ts index 545642c5dcfa3..3f943ad8bf2ff 100644 --- a/src/plugins/usage_collection/server/collector/collector_set.test.ts +++ b/src/plugins/usage_collection/server/collector/collector_set.test.ts @@ -21,7 +21,7 @@ import { noop } from 'lodash'; import { Collector } from './collector'; import { CollectorSet } from './collector_set'; import { UsageCollector } from './usage_collector'; -import { loggingSystemMock } from '../../../../core/server/mocks'; +import { elasticsearchServiceMock, loggingSystemMock } from '../../../../core/server/mocks'; const logger = loggingSystemMock.createLogger(); @@ -42,6 +42,7 @@ describe('CollectorSet', () => { }); const mockCallCluster = jest.fn().mockResolvedValue({ passTest: 1000 }); + const mockEsClient = elasticsearchServiceMock.createClusterClient().asInternalUser; it('should throw an error if non-Collector type of object is registered', () => { const collectors = new CollectorSet({ logger }); @@ -85,7 +86,7 @@ describe('CollectorSet', () => { }) ); - const result = await collectors.bulkFetch(mockCallCluster); + const result = await collectors.bulkFetch(mockCallCluster, mockEsClient); expect(loggerSpies.debug).toHaveBeenCalledTimes(1); expect(loggerSpies.debug).toHaveBeenCalledWith( 'Fetching data from MY_TEST_COLLECTOR collector' @@ -110,7 +111,7 @@ describe('CollectorSet', () => { let result; try { - result = await collectors.bulkFetch(mockCallCluster); + result = await collectors.bulkFetch(mockCallCluster, mockEsClient); } catch (err) { // Do nothing } @@ -128,7 +129,7 @@ describe('CollectorSet', () => { }) ); - const result = await collectors.bulkFetch(mockCallCluster); + const result = await collectors.bulkFetch(mockCallCluster, mockEsClient); expect(result).toStrictEqual([ { type: 'MY_TEST_COLLECTOR', @@ -146,7 +147,7 @@ describe('CollectorSet', () => { } as any) ); - const result = await collectors.bulkFetch(mockCallCluster); + const result = await collectors.bulkFetch(mockCallCluster, mockEsClient); expect(result).toStrictEqual([ { type: 'MY_TEST_COLLECTOR', @@ -169,7 +170,7 @@ describe('CollectorSet', () => { }) ); - const result = await collectors.bulkFetch(mockCallCluster); + const result = await collectors.bulkFetch(mockCallCluster, mockEsClient); expect(result).toStrictEqual([ { type: 'MY_TEST_COLLECTOR', diff --git a/src/plugins/usage_collection/server/collector/collector_set.ts b/src/plugins/usage_collection/server/collector/collector_set.ts index fce17a46b7168..7bf4e19c72cc0 100644 --- a/src/plugins/usage_collection/server/collector/collector_set.ts +++ b/src/plugins/usage_collection/server/collector/collector_set.ts @@ -18,7 +18,7 @@ */ import { snakeCase } from 'lodash'; -import { Logger, LegacyAPICaller } from 'kibana/server'; +import { Logger, LegacyAPICaller, ElasticsearchClient } from 'kibana/server'; import { Collector, CollectorOptions } from './collector'; import { UsageCollector } from './usage_collector'; @@ -76,23 +76,27 @@ export class CollectorSet { }; public areAllCollectorsReady = async (collectorSet: CollectorSet = this) => { - // Kept this for runtime validation in JS code. if (!(collectorSet instanceof CollectorSet)) { throw new Error( `areAllCollectorsReady method given bad collectorSet parameter: ` + typeof collectorSet ); } - const collectorTypesNotReady = ( - await Promise.all( - [...collectorSet.collectors.values()].map(async (collector) => { - if (!(await collector.isReady())) { - return collector.type; - } - }) - ) - ).filter((collectorType): collectorType is string => !!collectorType); - const allReady = collectorTypesNotReady.length === 0; + const collectors = [...collectorSet.collectors.values()]; + const collectorsWithStatus = await Promise.all( + collectors.map(async (collector) => { + return { + isReady: await collector.isReady(), + collector, + }; + }) + ); + + const collectorsTypesNotReady = collectorsWithStatus + .filter((collectorWithStatus) => collectorWithStatus.isReady === false) + .map((collectorWithStatus) => collectorWithStatus.collector.type); + + const allReady = collectorsTypesNotReady.length === 0; if (!allReady && this.maximumWaitTimeForAllCollectorsInS >= 0) { const nowTimestamp = +new Date(); @@ -102,10 +106,11 @@ export class CollectorSet { const timeLeftInMS = this.maximumWaitTimeForAllCollectorsInS * 1000 - timeWaitedInMS; if (timeLeftInMS <= 0) { this.logger.debug( - `All collectors are not ready (waiting for ${collectorTypesNotReady.join(',')}) ` + + `All collectors are not ready (waiting for ${collectorsTypesNotReady.join(',')}) ` + `but we have waited the required ` + `${this.maximumWaitTimeForAllCollectorsInS}s and will return data from all collectors that are ready.` ); + return true; } else { this.logger.debug(`All collectors are not ready. Waiting for ${timeLeftInMS}ms longer.`); @@ -117,8 +122,12 @@ export class CollectorSet { return allReady; }; + // all collections eventually pass through bulkFetch. + // the shape of the response is different when using the new ES client as is the error handling. + // We'll handle the refactor for using the new client in a follow up PR. public bulkFetch = async ( callCluster: LegacyAPICaller, + esClient: ElasticsearchClient, collectors: Map> = this.collectors ) => { const responses = await Promise.all( @@ -127,7 +136,7 @@ export class CollectorSet { try { return { type: collector.type, - result: await collector.fetch(callCluster), + result: await collector.fetch(callCluster, esClient), // each collector must ensure they handle the response appropriately. }; } catch (err) { this.logger.warn(err); @@ -149,9 +158,9 @@ export class CollectorSet { return this.makeCollectorSetFromArray(filtered); }; - public bulkFetchUsage = async (callCluster: LegacyAPICaller) => { + public bulkFetchUsage = async (callCluster: LegacyAPICaller, esClient: ElasticsearchClient) => { const usageCollectors = this.getFilteredCollectorSet((c) => c instanceof UsageCollector); - return await this.bulkFetch(callCluster, usageCollectors.collectors); + return await this.bulkFetch(callCluster, esClient, usageCollectors.collectors); }; // convert an array of fetched stats results into key/object diff --git a/src/plugins/usage_collection/server/routes/stats/README.md b/src/plugins/usage_collection/server/routes/stats/README.md new file mode 100644 index 0000000000000..09dabefbab44a --- /dev/null +++ b/src/plugins/usage_collection/server/routes/stats/README.md @@ -0,0 +1,20 @@ +# `/api/stats` + +This API returns the metrics for the Kibana server and usage stats. It allows the [Metricbeat Kibana module](https://www.elastic.co/guide/en/beats/metricbeat/current/metricbeat-module-kibana.html) to collect the [stats metricset](https://www.elastic.co/guide/en/beats/metricbeat/current/metricbeat-metricset-kibana-stats.html). + +By default, it returns the simplest level of stats; consisting of the Kibana server's ops metrics, version, status, and basic config like the server name, host, port, and locale. + +However, the information detailed above can be extended, with the combination of the following 3 query parameters: + +| Query Parameter | Default value | Description | +|:----------------|:-------------:|:------------| +|`extended`|`false`|When `true`, it adds `clusterUuid` and `usage`. The latter contains the information reported by all the Usage Collectors registered in the Kibana server. It may throw `503 Stats not ready` if any of the collectors is not fully initialized yet.| +|`legacy`|`false`|By default, when `extended=true`, the key names of the data in `usage` are transformed into API-friendlier `snake_case` format (i.e.: `clusterUuid` is transformed to `cluster_uuid`). When this parameter is `true`, the data is returned as-is.| +|`exclude_usage`|`false`|When `true`, and `extended=true`, it will report `clusterUuid` but no `usage`.| + +## Known use cases + +Metricbeat Kibana' stats metricset ([code](https://github.com/elastic/beats/blob/master/metricbeat/module/kibana/stats/stats.go)) uses this API to collect the metrics (every 10s) and usage (only once every 24h), and then reports them to the Monitoring cluster. They call this API in 2 ways: + +1. Metrics-only collection (every 10 seconds): `GET /api/stats?extended=true&legacy=true&exclude_usage=true` +2. Metrics+usage (every 24 hours): `GET /api/stats?extended=true&legacy=true&exclude_usage=false` diff --git a/src/plugins/usage_collection/server/routes/stats/index.ts b/src/plugins/usage_collection/server/routes/stats/index.ts new file mode 100644 index 0000000000000..8871ee599e56b --- /dev/null +++ b/src/plugins/usage_collection/server/routes/stats/index.ts @@ -0,0 +1,20 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export { registerStatsRoute } from './stats'; diff --git a/src/plugins/usage_collection/server/routes/stats.ts b/src/plugins/usage_collection/server/routes/stats/stats.ts similarity index 87% rename from src/plugins/usage_collection/server/routes/stats.ts rename to src/plugins/usage_collection/server/routes/stats/stats.ts index 7c64c9f180319..bee25fef669f1 100644 --- a/src/plugins/usage_collection/server/routes/stats.ts +++ b/src/plugins/usage_collection/server/routes/stats/stats.ts @@ -24,13 +24,14 @@ import { Observable } from 'rxjs'; import { first } from 'rxjs/operators'; import { + ElasticsearchClient, IRouter, LegacyAPICaller, MetricsServiceSetup, ServiceStatus, ServiceStatusLevels, -} from '../../../../core/server'; -import { CollectorSet } from '../collector'; +} from '../../../../../core/server'; +import { CollectorSet } from '../../collector'; const STATS_NOT_READY_MESSAGE = i18n.translate('usageCollection.stats.notReadyMessage', { defaultMessage: 'Stats are not ready yet. Please try again later.', @@ -61,8 +62,11 @@ export function registerStatsRoute({ metrics: MetricsServiceSetup; overallStatus$: Observable; }) { - const getUsage = async (callCluster: LegacyAPICaller): Promise => { - const usage = await collectorSet.bulkFetchUsage(callCluster); + const getUsage = async ( + callCluster: LegacyAPICaller, + esClient: ElasticsearchClient + ): Promise => { + const usage = await collectorSet.bulkFetchUsage(callCluster, esClient); return collectorSet.toObject(usage); }; @@ -96,13 +100,16 @@ export function registerStatsRoute({ let extended; if (isExtended) { const callCluster = context.core.elasticsearch.legacy.client.callAsCurrentUser; - const collectorsReady = await collectorSet.areAllCollectorsReady(); + const esClient = context.core.elasticsearch.client.asCurrentUser; - if (shouldGetUsage && !collectorsReady) { - return res.customError({ statusCode: 503, body: { message: STATS_NOT_READY_MESSAGE } }); + if (shouldGetUsage) { + const collectorsReady = await collectorSet.areAllCollectorsReady(); + if (!collectorsReady) { + return res.customError({ statusCode: 503, body: { message: STATS_NOT_READY_MESSAGE } }); + } } - const usagePromise = shouldGetUsage ? getUsage(callCluster) : Promise.resolve({}); + const usagePromise = shouldGetUsage ? getUsage(callCluster, esClient) : Promise.resolve({}); const [usage, clusterUuid] = await Promise.all([usagePromise, getClusterUuid(callCluster)]); let modifiedUsage = usage; @@ -147,9 +154,8 @@ export function registerStatsRoute({ } } - // Guranteed to resolve immediately due to replay effect on getOpsMetrics$ - // eslint-disable-next-line @typescript-eslint/naming-convention - const { collected_at, ...lastMetrics } = await metrics + // Guaranteed to resolve immediately due to replay effect on getOpsMetrics$ + const { collected_at: collectedAt, ...lastMetrics } = await metrics .getOpsMetrics$() .pipe(first()) .toPromise(); @@ -168,7 +174,7 @@ export function registerStatsRoute({ snapshot: SNAPSHOT_REGEX.test(config.kibanaVersion), status: ServiceStatusToLegacyState[overallStatus.level.toString()], }, - last_updated: collected_at.toISOString(), + last_updated: collectedAt.toISOString(), collection_interval_in_millis: metrics.collectionInterval, }); diff --git a/src/plugins/vis_default_editor/kibana.json b/src/plugins/vis_default_editor/kibana.json new file mode 100644 index 0000000000000..35ad0a3a8be9a --- /dev/null +++ b/src/plugins/vis_default_editor/kibana.json @@ -0,0 +1,6 @@ +{ + "id": "visDefaultEditor", + "version": "kibana", + "ui": true, + "requiredBundles": ["kibanaUtils", "kibanaReact", "data"] +} diff --git a/src/plugins/vis_default_editor/public/components/controls/components/number_list/number_list.test.tsx b/src/plugins/vis_default_editor/public/components/controls/components/number_list/number_list.test.tsx index 82d4b9142fb76..7964da23d8f50 100644 --- a/src/plugins/vis_default_editor/public/components/controls/components/number_list/number_list.test.tsx +++ b/src/plugins/vis_default_editor/public/components/controls/components/number_list/number_list.test.tsx @@ -33,10 +33,10 @@ jest.mock('@elastic/eui', () => ({ let counter = 1; return () => `12${counter++}`; }), - EuiSpacer: require.requireActual('@elastic/eui').EuiSpacer, - EuiFlexItem: require.requireActual('@elastic/eui').EuiFlexItem, - EuiButtonEmpty: require.requireActual('@elastic/eui').EuiButtonEmpty, - EuiFormErrorText: require.requireActual('@elastic/eui').EuiFormErrorText, + EuiSpacer: jest.requireActual('@elastic/eui').EuiSpacer, + EuiFlexItem: jest.requireActual('@elastic/eui').EuiFlexItem, + EuiButtonEmpty: jest.requireActual('@elastic/eui').EuiButtonEmpty, + EuiFormErrorText: jest.requireActual('@elastic/eui').EuiFormErrorText, })); describe('NumberList', () => { diff --git a/src/plugins/vis_default_editor/public/components/sidebar/index.ts b/src/plugins/vis_default_editor/public/components/sidebar/index.ts index 31228aad85d1e..09b6e229d9fcc 100644 --- a/src/plugins/vis_default_editor/public/components/sidebar/index.ts +++ b/src/plugins/vis_default_editor/public/components/sidebar/index.ts @@ -18,5 +18,3 @@ */ export { DefaultEditorSideBar } from './sidebar'; -export { DefaultEditorDataTab } from './data_tab'; -export { OptionTab } from './navbar'; diff --git a/src/plugins/vis_default_editor/public/components/sidebar/navbar.tsx b/src/plugins/vis_default_editor/public/components/sidebar/navbar.tsx index a1b5003a092f7..33ef5cc2353d7 100644 --- a/src/plugins/vis_default_editor/public/components/sidebar/navbar.tsx +++ b/src/plugins/vis_default_editor/public/components/sidebar/navbar.tsx @@ -20,32 +20,20 @@ import React from 'react'; import { EuiTabs, EuiTab } from '@elastic/eui'; -import { VisOptionsProps } from '../../vis_options_props'; -import { DefaultEditorDataTabProps } from './data_tab'; - -export interface OptionTab { - editor: React.ComponentType; - name: string; - title: string; -} +import { OptionTab } from './use_option_tabs'; interface DefaultEditorNavBarProps { optionTabs: OptionTab[]; - selectedTab: string; setSelectedTab(name: string): void; } -function DefaultEditorNavBar({ - selectedTab, - setSelectedTab, - optionTabs, -}: DefaultEditorNavBarProps) { +function DefaultEditorNavBar({ setSelectedTab, optionTabs }: DefaultEditorNavBarProps) { return ( - {optionTabs.map(({ name, title }) => ( + {optionTabs.map(({ name, title, isSelected = false }) => ( setSelectedTab(name)} > diff --git a/src/plugins/vis_default_editor/public/components/sidebar/sidebar.tsx b/src/plugins/vis_default_editor/public/components/sidebar/sidebar.tsx index bcbc5afec1fdc..d6b69a769e0a3 100644 --- a/src/plugins/vis_default_editor/public/components/sidebar/sidebar.tsx +++ b/src/plugins/vis_default_editor/public/components/sidebar/sidebar.tsx @@ -18,7 +18,7 @@ */ import React, { useMemo, useState, useCallback, KeyboardEventHandler, useEffect } from 'react'; -import { get, isEqual } from 'lodash'; +import { isEqual } from 'lodash'; import { i18n } from '@kbn/i18n'; import { keys, EuiButtonIcon, EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; import { EventEmitter } from 'events'; @@ -30,18 +30,18 @@ import { } from 'src/plugins/visualizations/public'; import { TimeRange } from 'src/plugins/data/public'; import { SavedObject } from 'src/plugins/saved_objects/public'; -import { DefaultEditorNavBar, OptionTab } from './navbar'; +import { DefaultEditorNavBar } from './navbar'; import { DefaultEditorControls } from './controls'; import { setStateParamValue, useEditorReducer, useEditorFormState, discardChanges } from './state'; import { DefaultEditorAggCommonProps } from '../agg_common_props'; import { SidebarTitle } from './sidebar_title'; import { Schema } from '../../schemas'; +import { useOptionTabs } from './use_option_tabs'; interface DefaultEditorSideBarProps { embeddableHandler: VisualizeEmbeddableContract; isCollapsed: boolean; onClickCollapse: () => void; - optionTabs: OptionTab[]; uiState: PersistedState; vis: Vis; isLinkedSearch: boolean; @@ -54,7 +54,6 @@ function DefaultEditorSideBar({ embeddableHandler, isCollapsed, onClickCollapse, - optionTabs, uiState, vis, isLinkedSearch, @@ -62,17 +61,17 @@ function DefaultEditorSideBar({ savedSearch, timeRange, }: DefaultEditorSideBarProps) { - const [selectedTab, setSelectedTab] = useState(optionTabs[0].name); const [isDirty, setDirty] = useState(false); const [state, dispatch] = useEditorReducer(vis, eventEmitter); const { formState, setTouched, setValidity, resetValidity } = useEditorFormState(); + const [optionTabs, setSelectedTab] = useOptionTabs(vis); const responseAggs = useMemo(() => (state.data.aggs ? state.data.aggs.getResponseAggs() : []), [ state.data.aggs, ]); const metricSchemas = (vis.type.schemas.metrics || []).map((s: Schema) => s.name); const metricAggs = useMemo( - () => responseAggs.filter((agg) => metricSchemas.includes(get(agg, 'schema'))), + () => responseAggs.filter((agg) => agg.schema && metricSchemas.includes(agg.schema)), [responseAggs, metricSchemas] ); const hasHistogramAgg = useMemo(() => responseAggs.some((agg) => agg.type.name === 'histogram'), [ @@ -201,31 +200,23 @@ function DefaultEditorSideBar({ )} {optionTabs.length > 1 && ( - + )} - {optionTabs.map(({ editor: Editor, name }) => { - const isTabSelected = selectedTab === name; - - return ( -
- -
- ); - })} + {optionTabs.map(({ editor: Editor, name, isSelected = false }) => ( +
+ +
+ ))} diff --git a/src/plugins/vis_default_editor/public/components/sidebar/use_option_tabs.ts b/src/plugins/vis_default_editor/public/components/sidebar/use_option_tabs.ts new file mode 100644 index 0000000000000..337533df50fad --- /dev/null +++ b/src/plugins/vis_default_editor/public/components/sidebar/use_option_tabs.ts @@ -0,0 +1,72 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { useCallback, useState } from 'react'; +import { i18n } from '@kbn/i18n'; + +import { Vis } from 'src/plugins/visualizations/public'; +import { DefaultEditorDataTab, DefaultEditorDataTabProps } from './data_tab'; +import { VisOptionsProps } from '../../vis_options_props'; + +export interface OptionTab { + editor: React.ComponentType; + name: string; + title: string; + isSelected?: boolean; +} + +export const useOptionTabs = ({ type: visType }: Vis): [OptionTab[], (name: string) => void] => { + const [optionTabs, setOptionTabs] = useState(() => { + const tabs = [ + ...(visType.schemas.buckets || visType.schemas.metrics + ? [ + { + name: 'data', + title: i18n.translate('visDefaultEditor.sidebar.tabs.dataLabel', { + defaultMessage: 'Data', + }), + editor: DefaultEditorDataTab, + }, + ] + : []), + + ...(!visType.editorConfig.optionTabs && visType.editorConfig.optionsTemplate + ? [ + { + name: 'options', + title: i18n.translate('visDefaultEditor.sidebar.tabs.optionsLabel', { + defaultMessage: 'Options', + }), + editor: visType.editorConfig.optionsTemplate, + }, + ] + : visType.editorConfig.optionTabs), + ]; + // set up the first tab as selected + tabs[0].isSelected = true; + + return tabs; + }); + + const setSelectedTab = useCallback((name: string) => { + setOptionTabs((tabs) => tabs.map((tab) => ({ ...tab, isSelected: tab.name === name }))); + }, []); + + return [optionTabs, setSelectedTab]; +}; diff --git a/src/plugins/vis_default_editor/public/default_editor.tsx b/src/plugins/vis_default_editor/public/default_editor.tsx index 60b6ebab5ad8e..ed94e52ee2399 100644 --- a/src/plugins/vis_default_editor/public/default_editor.tsx +++ b/src/plugins/vis_default_editor/public/default_editor.tsx @@ -20,13 +20,14 @@ import './index.scss'; import React, { useEffect, useRef, useState, useCallback } from 'react'; +import { EventEmitter } from 'events'; import { EditorRenderProps } from 'src/plugins/visualize/public'; +import { Vis, VisualizeEmbeddableContract } from 'src/plugins/visualizations/public'; import { KibanaContextProvider, PanelsContainer, Panel } from '../../kibana_react/public'; import { Storage } from '../../kibana_utils/public'; import { DefaultEditorSideBar } from './components/sidebar'; -import { DefaultEditorControllerState } from './default_editor_controller'; import { getInitialWidth } from './editor_size'; const localStorage = new Storage(window.localStorage); @@ -38,13 +39,16 @@ function DefaultEditor({ uiState, timeRange, filters, - optionTabs, query, embeddableHandler, eventEmitter, linked, savedSearch, -}: DefaultEditorControllerState & EditorRenderProps) { +}: EditorRenderProps & { + vis: Vis; + eventEmitter: EventEmitter; + embeddableHandler: VisualizeEmbeddableContract; +}) { const visRef = useRef(null); const [isCollapsed, setIsCollapsed] = useState(false); @@ -105,7 +109,6 @@ function DefaultEditor({ embeddableHandler={embeddableHandler} isCollapsed={isCollapsed} onClickCollapse={onClickCollapse} - optionTabs={optionTabs} vis={vis} uiState={uiState} isLinkedSearch={linked} diff --git a/src/plugins/vis_default_editor/public/default_editor_controller.tsx b/src/plugins/vis_default_editor/public/default_editor_controller.tsx index 56fb15ea8354a..0efd6e7746fd2 100644 --- a/src/plugins/vis_default_editor/public/default_editor_controller.tsx +++ b/src/plugins/vis_default_editor/public/default_editor_controller.tsx @@ -19,63 +19,21 @@ import React, { Suspense, lazy } from 'react'; import { render, unmountComponentAtNode } from 'react-dom'; -import { i18n } from '@kbn/i18n'; import { EventEmitter } from 'events'; import { EuiErrorBoundary, EuiLoadingChart } from '@elastic/eui'; import { EditorRenderProps } from 'src/plugins/visualize/public'; import { Vis, VisualizeEmbeddableContract } from 'src/plugins/visualizations/public'; -import { DefaultEditorDataTab, OptionTab } from './components/sidebar'; const DefaultEditor = lazy(() => import('./default_editor')); -export interface DefaultEditorControllerState { - vis: Vis; - eventEmitter: EventEmitter; - embeddableHandler: VisualizeEmbeddableContract; - optionTabs: OptionTab[]; -} - class DefaultEditorController { - private el: HTMLElement; - private state: DefaultEditorControllerState; - - constructor(el: HTMLElement, vis: Vis, eventEmitter: EventEmitter, embeddableHandler: any) { - this.el = el; - const { type: visType } = vis; - - const optionTabs = [ - ...(visType.schemas.buckets || visType.schemas.metrics - ? [ - { - name: 'data', - title: i18n.translate('visDefaultEditor.sidebar.tabs.dataLabel', { - defaultMessage: 'Data', - }), - editor: DefaultEditorDataTab, - }, - ] - : []), - - ...(!visType.editorConfig.optionTabs && visType.editorConfig.optionsTemplate - ? [ - { - name: 'options', - title: i18n.translate('visDefaultEditor.sidebar.tabs.optionsLabel', { - defaultMessage: 'Options', - }), - editor: visType.editorConfig.optionsTemplate, - }, - ] - : visType.editorConfig.optionTabs), - ]; - this.state = { - vis, - optionTabs, - eventEmitter, - embeddableHandler, - }; - } + constructor( + private el: HTMLElement, + private vis: Vis, + private eventEmitter: EventEmitter, + private embeddableHandler: VisualizeEmbeddableContract + ) {} render(props: EditorRenderProps) { render( @@ -94,7 +52,12 @@ class DefaultEditorController { } > - + , this.el diff --git a/src/plugins/vis_default_editor/public/index.ts b/src/plugins/vis_default_editor/public/index.ts index 156d50f451b57..d7eb5eda7bdfe 100644 --- a/src/plugins/vis_default_editor/public/index.ts +++ b/src/plugins/vis_default_editor/public/index.ts @@ -24,3 +24,11 @@ export * from './editor_size'; export * from './vis_options_props'; export * from './utils'; export { ISchemas, Schemas, Schema } from './schemas'; + +/** dummy plugin, we just want visDefaultEditor to have its own bundle */ +export function plugin() { + return new (class VisDefaultEditor { + setup() {} + start() {} + })(); +} diff --git a/src/plugins/vis_type_markdown/kibana.json b/src/plugins/vis_type_markdown/kibana.json index 4196bd7e85707..c0afcb0e99d13 100644 --- a/src/plugins/vis_type_markdown/kibana.json +++ b/src/plugins/vis_type_markdown/kibana.json @@ -4,5 +4,5 @@ "ui": true, "server": true, "requiredPlugins": ["expressions", "visualizations"], - "requiredBundles": ["kibanaUtils", "kibanaReact", "data", "charts", "visualizations", "expressions"] + "requiredBundles": ["kibanaReact", "charts", "visualizations", "expressions", "visDefaultEditor"] } diff --git a/src/plugins/vis_type_markdown/public/__snapshots__/markdown_fn.test.ts.snap b/src/plugins/vis_type_markdown/public/__snapshots__/markdown_fn.test.ts.snap index 473e2cba742b7..9983f67d4be4d 100644 --- a/src/plugins/vis_type_markdown/public/__snapshots__/markdown_fn.test.ts.snap +++ b/src/plugins/vis_type_markdown/public/__snapshots__/markdown_fn.test.ts.snap @@ -5,7 +5,7 @@ Object { "as": "markdown_vis", "type": "render", "value": Object { - "visConfig": Object { + "visParams": Object { "fontSize": 12, "markdown": "## hello _markdown_", "openLinksInNewTab": true, diff --git a/src/plugins/vis_type_markdown/public/_markdown_vis.scss b/src/plugins/vis_type_markdown/public/_markdown_vis.scss deleted file mode 100644 index fb0a3d05e5e85..0000000000000 --- a/src/plugins/vis_type_markdown/public/_markdown_vis.scss +++ /dev/null @@ -1,15 +0,0 @@ -.mkdVis { - padding: $euiSizeS; - width: 100%; -} - -.visEditor--markdown { - .visEditorSidebar__config > *, - .visEditor--markdown__textarea { - flex-grow: 1; - } - - .mkdEditor { - height: 100%; - } -} diff --git a/src/plugins/vis_type_markdown/public/index.scss b/src/plugins/vis_type_markdown/public/index.scss deleted file mode 100644 index ddb7fe3a6b0d9..0000000000000 --- a/src/plugins/vis_type_markdown/public/index.scss +++ /dev/null @@ -1,8 +0,0 @@ -// Prefix all styles with "mkd" to avoid conflicts. -// Examples -// mkdChart -// mkdChart__legend -// mkdChart__legend--small -// mkdChart__legend-isLoading - -@import './markdown_vis'; diff --git a/src/plugins/vis_type_markdown/public/markdown_fn.ts b/src/plugins/vis_type_markdown/public/markdown_fn.ts index 4b3c9989431f9..eaa2c840f8046 100644 --- a/src/plugins/vis_type_markdown/public/markdown_fn.ts +++ b/src/plugins/vis_type_markdown/public/markdown_fn.ts @@ -21,16 +21,16 @@ import { i18n } from '@kbn/i18n'; import { ExpressionFunctionDefinition, Render } from '../../expressions/public'; import { Arguments, MarkdownVisParams } from './types'; -interface RenderValue { +export interface MarkdownVisRenderValue { visType: 'markdown'; - visConfig: MarkdownVisParams; + visParams: MarkdownVisParams; } export type MarkdownVisExpressionFunctionDefinition = ExpressionFunctionDefinition< 'markdownVis', unknown, Arguments, - Render + Render >; export const createMarkdownVisFn = (): MarkdownVisExpressionFunctionDefinition => ({ @@ -70,7 +70,7 @@ export const createMarkdownVisFn = (): MarkdownVisExpressionFunctionDefinition = as: 'markdown_vis', value: { visType: 'markdown', - visConfig: { + visParams: { markdown: args.markdown, openLinksInNewTab: args.openLinksInNewTab, fontSize: parseInt(args.font.spec.fontSize || '12', 10), diff --git a/src/plugins/vis_type_markdown/public/markdown_renderer.tsx b/src/plugins/vis_type_markdown/public/markdown_renderer.tsx index 5950a762635b2..8071196c6a213 100644 --- a/src/plugins/vis_type_markdown/public/markdown_renderer.tsx +++ b/src/plugins/vis_type_markdown/public/markdown_renderer.tsx @@ -17,41 +17,29 @@ * under the License. */ -import React from 'react'; +import React, { lazy } from 'react'; import { render, unmountComponentAtNode } from 'react-dom'; import { VisualizationContainer } from '../../visualizations/public'; import { ExpressionRenderDefinition } from '../../expressions/common/expression_renderers'; -import { MarkdownVisWrapper } from './markdown_vis_controller'; -import { StartServicesGetter } from '../../kibana_utils/public'; +import { MarkdownVisRenderValue } from './markdown_fn'; -export const getMarkdownRenderer = (start: StartServicesGetter) => { - const markdownVisRenderer: () => ExpressionRenderDefinition = () => ({ - name: 'markdown_vis', - displayName: 'markdown visualization', - reuseDomNode: true, - render: async (domNode: HTMLElement, config: any, handlers: any) => { - const { visConfig } = config; +// @ts-ignore +const MarkdownVisComponent = lazy(() => import('./markdown_vis_controller')); - const I18nContext = await start().core.i18n.Context; +export const markdownVisRenderer: ExpressionRenderDefinition = { + name: 'markdown_vis', + displayName: 'markdown visualization', + reuseDomNode: true, + render: async (domNode, { visParams }, handlers) => { + handlers.onDestroy(() => { + unmountComponentAtNode(domNode); + }); - handlers.onDestroy(() => { - unmountComponentAtNode(domNode); - }); - - render( - - - - - , - domNode - ); - }, - }); - - return markdownVisRenderer; + render( + + + , + domNode + ); + }, }; diff --git a/src/plugins/vis_type_markdown/public/markdown_vis.scss b/src/plugins/vis_type_markdown/public/markdown_vis.scss new file mode 100644 index 0000000000000..2356562a86ed0 --- /dev/null +++ b/src/plugins/vis_type_markdown/public/markdown_vis.scss @@ -0,0 +1,22 @@ +// Prefix all styles with "mkd" to avoid conflicts. +// Examples +// mkdChart +// mkdChart__legend +// mkdChart__legend--small +// mkdChart__legend-isLoading + +.mkdVis { + padding: $euiSizeS; + width: 100%; +} + +.visEditor--markdown { + .visEditorSidebar__config > *, + .visEditor--markdown__textarea { + flex-grow: 1; + } + + .mkdEditor { + height: 100%; + } +} diff --git a/src/plugins/vis_type_markdown/public/markdown_vis_controller.test.tsx b/src/plugins/vis_type_markdown/public/markdown_vis_controller.test.tsx index ff0cc89a5d9c9..7bc8cdbd14170 100644 --- a/src/plugins/vis_type_markdown/public/markdown_vis_controller.test.tsx +++ b/src/plugins/vis_type_markdown/public/markdown_vis_controller.test.tsx @@ -18,11 +18,11 @@ */ import React from 'react'; -import { render, mount } from 'enzyme'; -import { MarkdownVisWrapper } from './markdown_vis_controller'; +import { wait, render } from '@testing-library/react'; +import MarkdownVisComponent from './markdown_vis_controller'; describe('markdown vis controller', () => { - it('should set html from markdown params', () => { + it('should set html from markdown params', async () => { const vis = { params: { openLinksInNewTab: false, @@ -32,13 +32,22 @@ describe('markdown vis controller', () => { }, }; - const wrapper = render( - + const { getByTestId, getByText } = render( + ); - expect(wrapper.find('a').text()).toBe('markdown'); + + await wait(() => getByTestId('markdownBody')); + + expect(getByText('markdown')).toMatchInlineSnapshot(` +
+ markdown + + `); }); - it('should not render the html', () => { + it('should not render the html', async () => { const vis = { params: { openLinksInNewTab: false, @@ -47,13 +56,20 @@ describe('markdown vis controller', () => { }, }; - const wrapper = render( - + const { getByTestId, getByText } = render( + ); - expect(wrapper.text()).toBe('Testing html\n'); + + await wait(() => getByTestId('markdownBody')); + + expect(getByText(/testing/i)).toMatchInlineSnapshot(` +

+ Testing <a>html</a> +

+ `); }); - it('should update the HTML when render again with changed params', () => { + it('should update the HTML when render again with changed params', async () => { const vis = { params: { openLinksInNewTab: false, @@ -62,13 +78,18 @@ describe('markdown vis controller', () => { }, }; - const wrapper = mount( - + const { getByTestId, getByText, rerender } = render( + ); - expect(wrapper.text().trim()).toBe('Initial'); + + await wait(() => getByTestId('markdownBody')); + + expect(getByText(/initial/i)).toBeInTheDocument(); + vis.params.markdown = 'Updated'; - wrapper.setProps({ vis }); - expect(wrapper.text().trim()).toBe('Updated'); + rerender(); + + expect(getByText(/Updated/i)).toBeInTheDocument(); }); describe('renderComplete', () => { @@ -86,56 +107,47 @@ describe('markdown vis controller', () => { renderComplete.mockClear(); }); - it('should be called on initial rendering', () => { - mount( - + it('should be called on initial rendering', async () => { + const { getByTestId } = render( + ); - expect(renderComplete.mock.calls.length).toBe(1); + + await wait(() => getByTestId('markdownBody')); + + expect(renderComplete).toHaveBeenCalledTimes(1); }); - it('should be called on successive render when params change', () => { - mount( - + it('should be called on successive render when params change', async () => { + const { getByTestId, rerender } = render( + ); - expect(renderComplete.mock.calls.length).toBe(1); + + await wait(() => getByTestId('markdownBody')); + + expect(renderComplete).toHaveBeenCalledTimes(1); + renderComplete.mockClear(); vis.params.markdown = 'changed'; - mount( - - ); - expect(renderComplete.mock.calls.length).toBe(1); + + rerender(); + + expect(renderComplete).toHaveBeenCalledTimes(1); }); - it('should be called on successive render even without data change', () => { - mount( - + it('should be called on successive render even without data change', async () => { + const { getByTestId, rerender } = render( + ); - expect(renderComplete.mock.calls.length).toBe(1); + + await wait(() => getByTestId('markdownBody')); + + expect(renderComplete).toHaveBeenCalledTimes(1); + renderComplete.mockClear(); - mount( - - ); - expect(renderComplete.mock.calls.length).toBe(1); + + rerender(); + + expect(renderComplete).toHaveBeenCalledTimes(1); }); }); }); diff --git a/src/plugins/vis_type_markdown/public/markdown_vis_controller.tsx b/src/plugins/vis_type_markdown/public/markdown_vis_controller.tsx index e1155ca42df72..a2387b96eab6d 100644 --- a/src/plugins/vis_type_markdown/public/markdown_vis_controller.tsx +++ b/src/plugins/vis_type_markdown/public/markdown_vis_controller.tsx @@ -17,83 +17,35 @@ * under the License. */ -import React from 'react'; +import React, { useEffect } from 'react'; import { Markdown } from '../../kibana_react/public'; import { MarkdownVisParams } from './types'; +import './markdown_vis.scss'; + interface MarkdownVisComponentProps extends MarkdownVisParams { renderComplete: () => void; } -/** - * The MarkdownVisComponent renders markdown to HTML and presents it. - */ -class MarkdownVisComponent extends React.Component { - /** - * Will be called after the first render when the component is present in the DOM. - * - * We call renderComplete here, to signal, that we are done with rendering. - */ - componentDidMount() { - this.props.renderComplete(); - } - - /** - * Will be called after the component has been updated and the changes has been - * flushed into the DOM. - * - * We will use this to signal that we are done rendering by calling the - * renderComplete property. - */ - componentDidUpdate() { - this.props.renderComplete(); - } +const MarkdownVisComponent = ({ + fontSize, + markdown, + openLinksInNewTab, + renderComplete, +}: MarkdownVisComponentProps) => { + useEffect(renderComplete); // renderComplete will be called after each render to signal, that we are done with rendering. - /** - * Render the actual HTML. - * Note: if only fontSize parameter has changed, this method will be called - * and return the appropriate JSX, but React will detect, that only the - * style argument has been updated, and thus only set this attribute to the DOM. - */ - render() { - return ( -
- -
- ); - } -} - -/** - * This is a wrapper component, that is actually used as the visualization. - * The sole purpose of this component is to extract all required parameters from - * the properties and pass them down as separate properties to the actual component. - * That way the actual (MarkdownVisComponent) will properly trigger it's prop update - * callback (componentWillReceiveProps) if one of these params change. It wouldn't - * trigger otherwise (e.g. it doesn't for this wrapper), since it only triggers - * if the reference to the prop changes (in this case the reference to vis). - * - * The way React works, this wrapper nearly brings no overhead, but allows us - * to use proper lifecycle methods in the actual component. - */ - -export interface MarkdownVisWrapperProps { - visParams: MarkdownVisParams; - fireEvent: (event: any) => void; - renderComplete: () => void; -} - -export function MarkdownVisWrapper(props: MarkdownVisWrapperProps) { return ( - +
+ +
); -} +}; + +// default export required for React.Lazy +// eslint-disable-next-line import/no-default-export +export { MarkdownVisComponent as default }; diff --git a/src/plugins/vis_type_markdown/public/plugin.ts b/src/plugins/vis_type_markdown/public/plugin.ts index c117df7e0fa33..790b19876d366 100644 --- a/src/plugins/vis_type_markdown/public/plugin.ts +++ b/src/plugins/vis_type_markdown/public/plugin.ts @@ -24,10 +24,7 @@ import { VisualizationsSetup } from '../../visualizations/public'; import { markdownVisDefinition } from './markdown_vis'; import { createMarkdownVisFn } from './markdown_fn'; import { ConfigSchema } from '../config'; - -import './index.scss'; -import { getMarkdownRenderer } from './markdown_renderer'; -import { createStartServicesGetter } from '../../kibana_utils/public'; +import { markdownVisRenderer } from './markdown_renderer'; /** @internal */ export interface MarkdownPluginSetupDependencies { @@ -44,9 +41,8 @@ export class MarkdownPlugin implements Plugin { } public setup(core: CoreSetup, { expressions, visualizations }: MarkdownPluginSetupDependencies) { - const start = createStartServicesGetter(core.getStartServices); visualizations.createBaseVisualization(markdownVisDefinition); - expressions.registerRenderer(getMarkdownRenderer(start)); + expressions.registerRenderer(markdownVisRenderer); expressions.registerFunction(createMarkdownVisFn); } diff --git a/src/plugins/vis_type_metric/kibana.json b/src/plugins/vis_type_metric/kibana.json index 26ca09e22f26e..68ab0bf617e30 100644 --- a/src/plugins/vis_type_metric/kibana.json +++ b/src/plugins/vis_type_metric/kibana.json @@ -5,5 +5,5 @@ "server": true, "ui": true, "requiredPlugins": ["data", "visualizations", "charts", "expressions"], - "requiredBundles": ["kibanaUtils", "kibanaReact"] + "requiredBundles": ["kibanaUtils", "visDefaultEditor"] } diff --git a/src/plugins/vis_type_metric/public/_metric_vis.scss b/src/plugins/vis_type_metric/public/_metric_vis.scss deleted file mode 100644 index b1f04cc93c4b7..0000000000000 --- a/src/plugins/vis_type_metric/public/_metric_vis.scss +++ /dev/null @@ -1,33 +0,0 @@ -.mtrVis { - width: 100%; - display: flex; - flex-direction: row; - justify-content: center; - align-items: center; - flex-wrap: wrap; -} - -.mtrVis__value { - @include euiTextTruncate; - font-weight: $euiFontWeightBold; -} - -.mtrVis__container { - text-align: center; - padding: $euiSize; -} - -.mtrVis__container--light { - color: $euiColorEmptyShade; -} - -.mtrVis__container-isFilterable { - cursor: pointer; - transition: transform $euiAnimSpeedNormal $euiAnimSlightResistance; - transform: translate(0, 0); - - &:hover, &:focus { - box-shadow: none; - transform: translate(0, -2px); - } -} diff --git a/src/plugins/vis_type_metric/public/components/metric_vis.scss b/src/plugins/vis_type_metric/public/components/metric_vis.scss new file mode 100644 index 0000000000000..5665ba8e8d099 --- /dev/null +++ b/src/plugins/vis_type_metric/public/components/metric_vis.scss @@ -0,0 +1,40 @@ +// Prefix all styles with "mtr" to avoid conflicts. +// Examples +// mtrChart +// mtrChart__legend +// mtrChart__legend--small +// mtrChart__legend-isLoading + +.mtrVis { + width: 100%; + display: flex; + flex-direction: row; + justify-content: center; + align-items: center; + flex-wrap: wrap; +} + +.mtrVis__value { + @include euiTextTruncate; + font-weight: $euiFontWeightBold; +} + +.mtrVis__container { + text-align: center; + padding: $euiSize; +} + +.mtrVis__container--light { + color: $euiColorEmptyShade; +} + +.mtrVis__container-isFilterable { + cursor: pointer; + transition: transform $euiAnimSpeedNormal $euiAnimSlightResistance; + transform: translate(0, 0); + + &:hover, &:focus { + box-shadow: none; + transform: translate(0, -2px); + } +} diff --git a/src/plugins/vis_type_metric/public/components/metric_vis_component.test.tsx b/src/plugins/vis_type_metric/public/components/metric_vis_component.test.tsx index b56d4e4f62e41..7f82c6adb5694 100644 --- a/src/plugins/vis_type_metric/public/components/metric_vis_component.test.tsx +++ b/src/plugins/vis_type_metric/public/components/metric_vis_component.test.tsx @@ -20,7 +20,7 @@ import React from 'react'; import { shallow } from 'enzyme'; -import { MetricVisComponent, MetricVisComponentProps } from './metric_vis_component'; +import MetricVisComponent, { MetricVisComponentProps } from './metric_vis_component'; jest.mock('../services', () => ({ getFormatService: () => ({ diff --git a/src/plugins/vis_type_metric/public/components/metric_vis_component.tsx b/src/plugins/vis_type_metric/public/components/metric_vis_component.tsx index 9ce3820ee4e23..e5c7db65c09a8 100644 --- a/src/plugins/vis_type_metric/public/components/metric_vis_component.tsx +++ b/src/plugins/vis_type_metric/public/components/metric_vis_component.tsx @@ -30,14 +30,16 @@ import { getFormatService } from '../services'; import { SchemaConfig } from '../../../visualizations/public'; import { Range } from '../../../expressions/public'; +import './metric_vis.scss'; + export interface MetricVisComponentProps { - visParams: VisParams; + visParams: Pick; visData: Input; fireEvent: (event: any) => void; renderComplete: () => void; } -export class MetricVisComponent extends Component { +class MetricVisComponent extends Component { private getLabels() { const config = this.props.visParams.metric; const isPercentageMode = config.percentageMode; @@ -209,3 +211,7 @@ export class MetricVisComponent extends Component { return metricsHtml; } } + +// default export required for React.Lazy +// eslint-disable-next-line import/no-default-export +export { MetricVisComponent as default }; diff --git a/src/plugins/vis_type_metric/public/index.scss b/src/plugins/vis_type_metric/public/index.scss deleted file mode 100644 index 638f9ac1ef93a..0000000000000 --- a/src/plugins/vis_type_metric/public/index.scss +++ /dev/null @@ -1,8 +0,0 @@ -// Prefix all styles with "mtr" to avoid conflicts. -// Examples -// mtrChart -// mtrChart__legend -// mtrChart__legend--small -// mtrChart__legend-isLoading - -@import 'metric_vis'; diff --git a/src/plugins/vis_type_metric/public/index.ts b/src/plugins/vis_type_metric/public/index.ts index 3d3e1879a51d9..ac541a9577cfc 100644 --- a/src/plugins/vis_type_metric/public/index.ts +++ b/src/plugins/vis_type_metric/public/index.ts @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ -import './index.scss'; import { PluginInitializerContext } from 'kibana/public'; import { MetricVisPlugin as Plugin } from './plugin'; diff --git a/src/plugins/vis_type_metric/public/metric_vis_fn.ts b/src/plugins/vis_type_metric/public/metric_vis_fn.ts index b58be63581724..97b1e6822333e 100644 --- a/src/plugins/vis_type_metric/public/metric_vis_fn.ts +++ b/src/plugins/vis_type_metric/public/metric_vis_fn.ts @@ -46,7 +46,7 @@ interface Arguments { bucket: any; // these aren't typed yet } -interface RenderValue { +export interface MetricVisRenderValue { visType: typeof visType; visData: Input; visConfig: Pick; @@ -57,7 +57,7 @@ export type MetricVisExpressionFunctionDefinition = ExpressionFunctionDefinition 'metricVis', Input, Arguments, - Render + Render >; export const createMetricVisFn = (): MetricVisExpressionFunctionDefinition => ({ diff --git a/src/plugins/vis_type_metric/public/metric_vis_renderer.tsx b/src/plugins/vis_type_metric/public/metric_vis_renderer.tsx index 2bae668b080ea..bf0d6da9fba05 100644 --- a/src/plugins/vis_type_metric/public/metric_vis_renderer.tsx +++ b/src/plugins/vis_type_metric/public/metric_vis_renderer.tsx @@ -17,37 +17,33 @@ * under the License. */ -import React from 'react'; +import React, { lazy } from 'react'; import { render, unmountComponentAtNode } from 'react-dom'; -import { MetricVisComponent } from './components/metric_vis_component'; -import { getI18n } from './services'; + import { VisualizationContainer } from '../../visualizations/public'; import { ExpressionRenderDefinition } from '../../expressions/common/expression_renderers'; +import { MetricVisRenderValue } from './metric_vis_fn'; +// @ts-ignore +const MetricVisComponent = lazy(() => import('./components/metric_vis_component')); -export const metricVisRenderer: () => ExpressionRenderDefinition = () => ({ +export const metricVisRenderer: () => ExpressionRenderDefinition = () => ({ name: 'metric_vis', displayName: 'metric visualization', reuseDomNode: true, - render: async (domNode: HTMLElement, config: any, handlers: any) => { - const { visData, visConfig } = config; - - const I18nContext = getI18n().Context; - + render: async (domNode, { visData, visConfig }, handlers) => { handlers.onDestroy(() => { unmountComponentAtNode(domNode); }); render( - - - - - , + + + , domNode ); }, diff --git a/src/plugins/vis_type_metric/public/metric_vis_type.ts b/src/plugins/vis_type_metric/public/metric_vis_type.ts index 6b4d6e151693f..1c5afd396c2c3 100644 --- a/src/plugins/vis_type_metric/public/metric_vis_type.ts +++ b/src/plugins/vis_type_metric/public/metric_vis_type.ts @@ -18,13 +18,14 @@ */ import { i18n } from '@kbn/i18n'; +import { BaseVisTypeOptions } from 'src/plugins/visualizations/public'; import { MetricVisOptions } from './components/metric_vis_options'; import { ColorSchemas, colorSchemas, ColorModes } from '../../charts/public'; import { AggGroupNames } from '../../data/public'; import { Schemas } from '../../vis_default_editor/public'; import { toExpressionAst } from './to_ast'; -export const createMetricVisTypeDefinition = () => ({ +export const createMetricVisTypeDefinition = (): BaseVisTypeOptions => ({ name: 'metric', title: i18n.translate('visTypeMetric.metricTitle', { defaultMessage: 'Metric' }), icon: 'visMetric', diff --git a/src/plugins/vis_type_metric/public/plugin.ts b/src/plugins/vis_type_metric/public/plugin.ts index b9e094aa76889..c653d1bdaf965 100644 --- a/src/plugins/vis_type_metric/public/plugin.ts +++ b/src/plugins/vis_type_metric/public/plugin.ts @@ -25,7 +25,7 @@ import { createMetricVisFn } from './metric_vis_fn'; import { createMetricVisTypeDefinition } from './metric_vis_type'; import { ChartsPluginSetup } from '../../charts/public'; import { DataPublicPluginStart } from '../../data/public'; -import { setFormatService, setI18n } from './services'; +import { setFormatService } from './services'; import { ConfigSchema } from '../config'; import { metricVisRenderer } from './metric_vis_renderer'; @@ -59,7 +59,6 @@ export class MetricVisPlugin implements Plugin { } public start(core: CoreStart, { data }: MetricVisPluginStartDependencies) { - setI18n(core.i18n); setFormatService(data.fieldFormats); } } diff --git a/src/plugins/vis_type_metric/public/services.ts b/src/plugins/vis_type_metric/public/services.ts index 0e19cfdce228d..681afbaf0b268 100644 --- a/src/plugins/vis_type_metric/public/services.ts +++ b/src/plugins/vis_type_metric/public/services.ts @@ -17,12 +17,9 @@ * under the License. */ -import { I18nStart } from 'kibana/public'; import { createGetterSetter } from '../../kibana_utils/common'; import { DataPublicPluginStart } from '../../data/public'; export const [getFormatService, setFormatService] = createGetterSetter< DataPublicPluginStart['fieldFormats'] >('metric data.fieldFormats'); - -export const [getI18n, setI18n] = createGetterSetter('I18n'); diff --git a/src/plugins/vis_type_metric/public/to_ast.ts b/src/plugins/vis_type_metric/public/to_ast.ts index 7eefd8328ab76..23e4664b82414 100644 --- a/src/plugins/vis_type_metric/public/to_ast.ts +++ b/src/plugins/vis_type_metric/public/to_ast.ts @@ -39,7 +39,7 @@ export const toExpressionAst = (vis: Vis, params: any) => { const esaggs = buildExpressionFunction('esaggs', { index: vis.data.indexPattern!.id!, metricsAtAllLevels: vis.isHierarchical(), - partialRows: vis.type.requiresPartialRows || vis.params.showPartialRows || false, + partialRows: vis.params.showPartialRows || false, aggConfigs: JSON.stringify(vis.data.aggs!.aggs), includeFormatHints: false, }); diff --git a/src/plugins/vis_type_table/kibana.json b/src/plugins/vis_type_table/kibana.json index b3c1556429077..b8a68909dc857 100644 --- a/src/plugins/vis_type_table/kibana.json +++ b/src/plugins/vis_type_table/kibana.json @@ -11,8 +11,8 @@ ], "requiredBundles": [ "kibanaUtils", - "kibanaReact", "share", - "charts" + "charts", + "visDefaultEditor" ] } diff --git a/src/plugins/vis_type_table/public/__snapshots__/table_vis_fn.test.ts.snap b/src/plugins/vis_type_table/public/__snapshots__/table_vis_fn.test.ts.snap index dc6571de969f0..a32609c2e3d34 100644 --- a/src/plugins/vis_type_table/public/__snapshots__/table_vis_fn.test.ts.snap +++ b/src/plugins/vis_type_table/public/__snapshots__/table_vis_fn.test.ts.snap @@ -2,12 +2,9 @@ exports[`interpreter/functions#table returns an object with the correct structure 1`] = ` Object { - "as": "visualization", + "as": "table_vis", "type": "render", "value": Object { - "params": Object { - "listenOnChange": true, - }, "visConfig": Object { "dimensions": Object { "buckets": Array [], diff --git a/src/plugins/vis_type_table/public/__snapshots__/to_ast.test.ts.snap b/src/plugins/vis_type_table/public/__snapshots__/to_ast.test.ts.snap new file mode 100644 index 0000000000000..d2298e6fb3eb5 --- /dev/null +++ b/src/plugins/vis_type_table/public/__snapshots__/to_ast.test.ts.snap @@ -0,0 +1,74 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`table vis toExpressionAst function should match snapshot based on params & dimensions 1`] = ` +Object { + "chain": Array [ + Object { + "arguments": Object { + "aggConfigs": Array [ + "[]", + ], + "includeFormatHints": Array [ + false, + ], + "index": Array [ + "123", + ], + "metricsAtAllLevels": Array [ + false, + ], + "partialRows": Array [ + true, + ], + }, + "function": "esaggs", + "type": "function", + }, + Object { + "arguments": Object { + "visConfig": Array [ + "{\\"perPage\\":20,\\"percentageCol\\":\\"Count\\",\\"showMetricsAtAllLevels\\":true,\\"showPartialRows\\":true,\\"showTotal\\":true,\\"sort\\":{\\"columnIndex\\":null,\\"direction\\":null},\\"totalFunc\\":\\"sum\\",\\"dimensions\\":{\\"metrics\\":[{\\"accessor\\":1,\\"format\\":{\\"id\\":\\"number\\"},\\"params\\":{},\\"label\\":\\"Count\\",\\"aggType\\":\\"count\\"}],\\"buckets\\":[{\\"accessor\\":0,\\"format\\":{\\"id\\":\\"date\\",\\"params\\":{\\"pattern\\":\\"YYYY-MM-DD HH:mm\\"}},\\"params\\":{},\\"label\\":\\"order_date per 3 hours\\",\\"aggType\\":\\"date_histogram\\"}]}}", + ], + }, + "function": "kibana_table", + "type": "function", + }, + ], + "type": "expression", +} +`; + +exports[`table vis toExpressionAst function should match snapshot without params 1`] = ` +Object { + "chain": Array [ + Object { + "arguments": Object { + "aggConfigs": Array [ + "[]", + ], + "includeFormatHints": Array [ + false, + ], + "index": Array [ + "123", + ], + "metricsAtAllLevels": Array [ + false, + ], + }, + "function": "esaggs", + "type": "function", + }, + Object { + "arguments": Object { + "visConfig": Array [ + "{\\"showLabel\\":false,\\"dimensions\\":{\\"metrics\\":[{\\"accessor\\":1,\\"format\\":{\\"id\\":\\"number\\"},\\"params\\":{},\\"label\\":\\"Count\\",\\"aggType\\":\\"count\\"}],\\"buckets\\":[{\\"accessor\\":0,\\"format\\":{\\"id\\":\\"date\\",\\"params\\":{\\"pattern\\":\\"YYYY-MM-DD HH:mm\\"}},\\"params\\":{},\\"label\\":\\"order_date per 3 hours\\",\\"aggType\\":\\"date_histogram\\"}]}}", + ], + }, + "function": "kibana_table", + "type": "function", + }, + ], + "type": "expression", +} +`; diff --git a/src/plugins/vis_type_table/public/index.ts b/src/plugins/vis_type_table/public/index.ts index 5621fdb094772..6493c967165db 100644 --- a/src/plugins/vis_type_table/public/index.ts +++ b/src/plugins/vis_type_table/public/index.ts @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ -import './index.scss'; import { PluginInitializerContext } from 'kibana/public'; import { TableVisPlugin as Plugin } from './plugin'; diff --git a/src/plugins/vis_type_table/public/_table_vis.scss b/src/plugins/vis_type_table/public/legacy/_table_vis.scss similarity index 91% rename from src/plugins/vis_type_table/public/_table_vis.scss rename to src/plugins/vis_type_table/public/legacy/_table_vis.scss index 8a36b9818c2a3..fa12ef9a1cf39 100644 --- a/src/plugins/vis_type_table/public/_table_vis.scss +++ b/src/plugins/vis_type_table/public/legacy/_table_vis.scss @@ -4,8 +4,10 @@ .table-vis { display: flex; flex-direction: column; - flex: 1 0 100%; + flex: 1 1 0; overflow: auto; + + @include euiScrollBar; } .table-vis-container { diff --git a/src/plugins/vis_type_table/public/agg_table/_agg_table.scss b/src/plugins/vis_type_table/public/legacy/agg_table/_agg_table.scss similarity index 100% rename from src/plugins/vis_type_table/public/agg_table/_agg_table.scss rename to src/plugins/vis_type_table/public/legacy/agg_table/_agg_table.scss diff --git a/src/plugins/vis_type_table/public/agg_table/_index.scss b/src/plugins/vis_type_table/public/legacy/agg_table/_index.scss similarity index 100% rename from src/plugins/vis_type_table/public/agg_table/_index.scss rename to src/plugins/vis_type_table/public/legacy/agg_table/_index.scss diff --git a/src/plugins/vis_type_table/public/agg_table/agg_table.html b/src/plugins/vis_type_table/public/legacy/agg_table/agg_table.html similarity index 100% rename from src/plugins/vis_type_table/public/agg_table/agg_table.html rename to src/plugins/vis_type_table/public/legacy/agg_table/agg_table.html diff --git a/src/plugins/vis_type_table/public/agg_table/agg_table.js b/src/plugins/vis_type_table/public/legacy/agg_table/agg_table.js similarity index 99% rename from src/plugins/vis_type_table/public/agg_table/agg_table.js rename to src/plugins/vis_type_table/public/legacy/agg_table/agg_table.js index 1e98a06c2a6a9..a9ec431e9d940 100644 --- a/src/plugins/vis_type_table/public/agg_table/agg_table.js +++ b/src/plugins/vis_type_table/public/legacy/agg_table/agg_table.js @@ -17,9 +17,9 @@ * under the License. */ import _ from 'lodash'; -import { CSV_SEPARATOR_SETTING, CSV_QUOTE_VALUES_SETTING } from '../../../share/public'; +import { CSV_SEPARATOR_SETTING, CSV_QUOTE_VALUES_SETTING } from '../../../../share/public'; import aggTableTemplate from './agg_table.html'; -import { getFormatService } from '../services'; +import { getFormatService } from '../../services'; import { i18n } from '@kbn/i18n'; export function KbnAggTable(config, RecursionHelper) { diff --git a/src/plugins/vis_type_table/public/agg_table/agg_table.test.js b/src/plugins/vis_type_table/public/legacy/agg_table/agg_table.test.js similarity index 97% rename from src/plugins/vis_type_table/public/agg_table/agg_table.test.js rename to src/plugins/vis_type_table/public/legacy/agg_table/agg_table.test.js index 29a10151a9418..c93fb4f8bd568 100644 --- a/src/plugins/vis_type_table/public/agg_table/agg_table.test.js +++ b/src/plugins/vis_type_table/public/legacy/agg_table/agg_table.test.js @@ -24,14 +24,14 @@ import 'angular-mocks'; import sinon from 'sinon'; import { round } from 'lodash'; -import { getFieldFormatsRegistry } from '../../../data/public/test_utils'; -import { coreMock } from '../../../../core/public/mocks'; -import { initAngularBootstrap } from '../../../kibana_legacy/public'; -import { setUiSettings } from '../../../data/public/services'; -import { UI_SETTINGS } from '../../../data/public/'; -import { CSV_SEPARATOR_SETTING, CSV_QUOTE_VALUES_SETTING } from '../../../share/public'; - -import { setFormatService } from '../services'; +import { getFieldFormatsRegistry } from '../../../../data/public/test_utils'; +import { coreMock } from '../../../../../core/public/mocks'; +import { initAngularBootstrap } from '../../../../kibana_legacy/public'; +import { setUiSettings } from '../../../../data/public/services'; +import { UI_SETTINGS } from '../../../../data/public/'; +import { CSV_SEPARATOR_SETTING, CSV_QUOTE_VALUES_SETTING } from '../../../../share/public'; + +import { setFormatService } from '../../services'; import { getInnerAngular } from '../get_inner_angular'; import { initTableVisLegacyModule } from '../table_vis_legacy_module'; import { tabifiedData } from './tabified_data'; diff --git a/src/plugins/vis_type_table/public/agg_table/agg_table_group.html b/src/plugins/vis_type_table/public/legacy/agg_table/agg_table_group.html similarity index 100% rename from src/plugins/vis_type_table/public/agg_table/agg_table_group.html rename to src/plugins/vis_type_table/public/legacy/agg_table/agg_table_group.html diff --git a/src/plugins/vis_type_table/public/agg_table/agg_table_group.js b/src/plugins/vis_type_table/public/legacy/agg_table/agg_table_group.js similarity index 100% rename from src/plugins/vis_type_table/public/agg_table/agg_table_group.js rename to src/plugins/vis_type_table/public/legacy/agg_table/agg_table_group.js diff --git a/src/plugins/vis_type_table/public/agg_table/agg_table_group.test.js b/src/plugins/vis_type_table/public/legacy/agg_table/agg_table_group.test.js similarity index 92% rename from src/plugins/vis_type_table/public/agg_table/agg_table_group.test.js rename to src/plugins/vis_type_table/public/legacy/agg_table/agg_table_group.test.js index 04cf624331d81..833f51b446ac1 100644 --- a/src/plugins/vis_type_table/public/agg_table/agg_table_group.test.js +++ b/src/plugins/vis_type_table/public/legacy/agg_table/agg_table_group.test.js @@ -22,11 +22,11 @@ import angular from 'angular'; import 'angular-mocks'; import expect from '@kbn/expect'; -import { getFieldFormatsRegistry } from '../../../data/public/test_utils'; -import { coreMock } from '../../../../core/public/mocks'; -import { initAngularBootstrap } from '../../../kibana_legacy/public'; -import { setUiSettings } from '../../../data/public/services'; -import { setFormatService } from '../services'; +import { getFieldFormatsRegistry } from '../../../../data/public/test_utils'; +import { coreMock } from '../../../../../core/public/mocks'; +import { initAngularBootstrap } from '../../../../kibana_legacy/public'; +import { setUiSettings } from '../../../../data/public/services'; +import { setFormatService } from '../../services'; import { getInnerAngular } from '../get_inner_angular'; import { initTableVisLegacyModule } from '../table_vis_legacy_module'; import { tabifiedData } from './tabified_data'; diff --git a/src/plugins/vis_type_table/public/agg_table/tabified_data.js b/src/plugins/vis_type_table/public/legacy/agg_table/tabified_data.js similarity index 100% rename from src/plugins/vis_type_table/public/agg_table/tabified_data.js rename to src/plugins/vis_type_table/public/legacy/agg_table/tabified_data.js diff --git a/src/plugins/vis_type_table/public/get_inner_angular.ts b/src/plugins/vis_type_table/public/legacy/get_inner_angular.ts similarity index 98% rename from src/plugins/vis_type_table/public/get_inner_angular.ts rename to src/plugins/vis_type_table/public/legacy/get_inner_angular.ts index 4e4269a1f44f4..f3d88a2a217b3 100644 --- a/src/plugins/vis_type_table/public/get_inner_angular.ts +++ b/src/plugins/vis_type_table/public/legacy/get_inner_angular.ts @@ -33,7 +33,7 @@ import { PrivateProvider, watchMultiDecorator, KbnAccessibleClickProvider, -} from '../../kibana_legacy/public'; +} from '../../../kibana_legacy/public'; initAngularBootstrap(); diff --git a/src/plugins/vis_type_table/public/index.scss b/src/plugins/vis_type_table/public/legacy/index.scss similarity index 100% rename from src/plugins/vis_type_table/public/index.scss rename to src/plugins/vis_type_table/public/legacy/index.scss diff --git a/src/plugins/vis_type_table/public/paginated_table/_index.scss b/src/plugins/vis_type_table/public/legacy/paginated_table/_index.scss similarity index 100% rename from src/plugins/vis_type_table/public/paginated_table/_index.scss rename to src/plugins/vis_type_table/public/legacy/paginated_table/_index.scss diff --git a/src/plugins/vis_type_table/public/paginated_table/_table_cell_filter.scss b/src/plugins/vis_type_table/public/legacy/paginated_table/_table_cell_filter.scss similarity index 100% rename from src/plugins/vis_type_table/public/paginated_table/_table_cell_filter.scss rename to src/plugins/vis_type_table/public/legacy/paginated_table/_table_cell_filter.scss diff --git a/src/plugins/vis_type_table/public/paginated_table/paginated_table.html b/src/plugins/vis_type_table/public/legacy/paginated_table/paginated_table.html similarity index 100% rename from src/plugins/vis_type_table/public/paginated_table/paginated_table.html rename to src/plugins/vis_type_table/public/legacy/paginated_table/paginated_table.html diff --git a/src/plugins/vis_type_table/public/paginated_table/paginated_table.js b/src/plugins/vis_type_table/public/legacy/paginated_table/paginated_table.js similarity index 100% rename from src/plugins/vis_type_table/public/paginated_table/paginated_table.js rename to src/plugins/vis_type_table/public/legacy/paginated_table/paginated_table.js diff --git a/src/plugins/vis_type_table/public/paginated_table/paginated_table.test.ts b/src/plugins/vis_type_table/public/legacy/paginated_table/paginated_table.test.ts similarity index 98% rename from src/plugins/vis_type_table/public/paginated_table/paginated_table.test.ts rename to src/plugins/vis_type_table/public/legacy/paginated_table/paginated_table.test.ts index de253f26ff9e7..3bc5f79557041 100644 --- a/src/plugins/vis_type_table/public/paginated_table/paginated_table.test.ts +++ b/src/plugins/vis_type_table/public/legacy/paginated_table/paginated_table.test.ts @@ -25,11 +25,7 @@ import 'angular-mocks'; import { getAngularModule } from '../get_inner_angular'; import { initTableVisLegacyModule } from '../table_vis_legacy_module'; -import { coreMock } from '../../../../core/public/mocks'; - -jest.mock('../../../kibana_legacy/public/angular/angular_config', () => ({ - configureAppAngularModule: () => {}, -})); +import { coreMock } from '../../../../../core/public/mocks'; interface Sort { columnIndex: number; diff --git a/src/plugins/vis_type_table/public/paginated_table/rows.js b/src/plugins/vis_type_table/public/legacy/paginated_table/rows.js similarity index 91% rename from src/plugins/vis_type_table/public/paginated_table/rows.js rename to src/plugins/vis_type_table/public/legacy/paginated_table/rows.js index d8f01a10c63fa..54e754adcc170 100644 --- a/src/plugins/vis_type_table/public/paginated_table/rows.js +++ b/src/plugins/vis_type_table/public/legacy/paginated_table/rows.js @@ -44,15 +44,18 @@ export function KbnRows($compile) { } $scope.filter({ - data: [ - { - table: $scope.table, - row: $scope.rows.findIndex((r) => r === row), - column: $scope.table.columns.findIndex((c) => c.id === column.id), - value, - }, - ], - negate, + name: 'filterBucket', + data: { + data: [ + { + table: $scope.table, + row: $scope.rows.findIndex((r) => r === row), + column: $scope.table.columns.findIndex((c) => c.id === column.id), + value, + }, + ], + negate, + }, }); }; diff --git a/src/plugins/vis_type_table/public/paginated_table/table_cell_filter.html b/src/plugins/vis_type_table/public/legacy/paginated_table/table_cell_filter.html similarity index 100% rename from src/plugins/vis_type_table/public/paginated_table/table_cell_filter.html rename to src/plugins/vis_type_table/public/legacy/paginated_table/table_cell_filter.html diff --git a/src/plugins/vis_type_table/public/table_vis.html b/src/plugins/vis_type_table/public/legacy/table_vis.html similarity index 96% rename from src/plugins/vis_type_table/public/table_vis.html rename to src/plugins/vis_type_table/public/legacy/table_vis.html index f721b670400d6..c469cd250755c 100644 --- a/src/plugins/vis_type_table/public/table_vis.html +++ b/src/plugins/vis_type_table/public/legacy/table_vis.html @@ -15,7 +15,7 @@
({ - configureAppAngularModule: () => {}, -})); - interface TableVisScope extends IScope { [key: string]: any; } @@ -105,7 +99,7 @@ describe('Table Vis - Controller', () => { ); beforeEach(() => { - stubIndexPattern = new StubIndexPattern( + stubIndexPattern = getStubIndexPattern( 'logstash-*', (cfg: any) => cfg, 'time', @@ -113,15 +107,11 @@ describe('Table Vis - Controller', () => { coreMock.createSetup() ); }); - const tableVisTypeDefinition = getTableVisTypeDefinition( - coreMock.createSetup(), - coreMock.createPluginInitializerContext() - ); function getRangeVis(params?: object) { return ({ type: tableVisTypeDefinition, - params: Object.assign({}, tableVisTypeDefinition.visConfig.defaults, params), + params: Object.assign({}, tableVisTypeDefinition.visConfig?.defaults, params), data: { aggs: createAggConfigs(stubIndexPattern, [ { type: 'count', schema: 'metric' }, @@ -250,13 +240,13 @@ describe('Table Vis - Controller', () => { const vis = getRangeVis({ showPartialRows: true }); initController(vis); - expect(vis.type.hierarchicalData(vis)).toEqual(true); + expect((vis.type.hierarchicalData as Function)(vis)).toEqual(true); }); test('passes partialRows:false to tabify based on the vis params', () => { const vis = getRangeVis({ showPartialRows: false }); initController(vis); - expect(vis.type.hierarchicalData(vis)).toEqual(false); + expect((vis.type.hierarchicalData as Function)(vis)).toEqual(false); }); }); diff --git a/src/plugins/vis_type_table/public/table_vis_legacy_module.ts b/src/plugins/vis_type_table/public/legacy/table_vis_legacy_module.ts similarity index 100% rename from src/plugins/vis_type_table/public/table_vis_legacy_module.ts rename to src/plugins/vis_type_table/public/legacy/table_vis_legacy_module.ts diff --git a/src/plugins/vis_type_table/public/legacy/table_vis_legacy_renderer.tsx b/src/plugins/vis_type_table/public/legacy/table_vis_legacy_renderer.tsx new file mode 100644 index 0000000000000..ab633bd5137ba --- /dev/null +++ b/src/plugins/vis_type_table/public/legacy/table_vis_legacy_renderer.tsx @@ -0,0 +1,53 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { CoreSetup, PluginInitializerContext } from 'kibana/public'; +import { ExpressionRenderDefinition } from 'src/plugins/expressions'; +import { TablePluginStartDependencies } from '../plugin'; +import { TableVisRenderValue } from '../table_vis_fn'; +import { TableVisLegacyController } from './vis_controller'; + +const tableVisRegistry = new Map(); + +export const getTableVisLegacyRenderer: ( + core: CoreSetup, + context: PluginInitializerContext +) => ExpressionRenderDefinition = (core, context) => ({ + name: 'table_vis', + reuseDomNode: true, + render: async (domNode, config, handlers) => { + let registeredController = tableVisRegistry.get(domNode); + + if (!registeredController) { + const { getTableVisualizationControllerClass } = await import('./vis_controller'); + + const Controller = getTableVisualizationControllerClass(core, context); + registeredController = new Controller(domNode); + tableVisRegistry.set(domNode, registeredController); + + handlers.onDestroy(() => { + registeredController?.destroy(); + tableVisRegistry.delete(domNode); + }); + } + + await registeredController.render(config.visData, config.visConfig, handlers); + handlers.done(); + }, +}); diff --git a/src/plugins/vis_type_table/public/legacy/vis_controller.ts b/src/plugins/vis_type_table/public/legacy/vis_controller.ts new file mode 100644 index 0000000000000..eff8e34f3e778 --- /dev/null +++ b/src/plugins/vis_type_table/public/legacy/vis_controller.ts @@ -0,0 +1,124 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +import { CoreSetup, PluginInitializerContext } from 'kibana/public'; +import angular, { IModule, auto, IRootScopeService, IScope, ICompileService } from 'angular'; +import $ from 'jquery'; + +import './index.scss'; + +import { IInterpreterRenderHandlers } from 'src/plugins/expressions'; +import { getAngularModule } from './get_inner_angular'; +import { initTableVisLegacyModule } from './table_vis_legacy_module'; +// @ts-ignore +import tableVisTemplate from './table_vis.html'; +import { TablePluginStartDependencies } from '../plugin'; +import { TableVisConfig } from '../types'; +import { TableContext } from '../table_vis_response_handler'; + +const innerAngularName = 'kibana/table_vis'; + +export type TableVisLegacyController = InstanceType< + ReturnType +>; + +export function getTableVisualizationControllerClass( + core: CoreSetup, + context: PluginInitializerContext +) { + return class TableVisualizationController { + private tableVisModule: IModule | undefined; + private injector: auto.IInjectorService | undefined; + el: JQuery; + $rootScope: IRootScopeService | null = null; + $scope: (IScope & { [key: string]: any }) | undefined; + $compile: ICompileService | undefined; + + constructor(domeElement: Element) { + this.el = $(domeElement); + } + + getInjector() { + if (!this.injector) { + const mountpoint = document.createElement('div'); + mountpoint.className = 'visualization'; + this.injector = angular.bootstrap(mountpoint, [innerAngularName]); + this.el.append(mountpoint); + } + + return this.injector; + } + + async initLocalAngular() { + if (!this.tableVisModule) { + const [coreStart, { kibanaLegacy }] = await core.getStartServices(); + this.tableVisModule = getAngularModule(innerAngularName, coreStart, context); + initTableVisLegacyModule(this.tableVisModule); + kibanaLegacy.loadFontAwesome(); + } + } + + async render( + esResponse: TableContext, + visParams: TableVisConfig, + handlers: IInterpreterRenderHandlers + ): Promise { + await this.initLocalAngular(); + + return new Promise(async (resolve, reject) => { + if (!this.$rootScope) { + const $injector = this.getInjector(); + this.$rootScope = $injector.get('$rootScope'); + this.$compile = $injector.get('$compile'); + } + const updateScope = () => { + if (!this.$scope) { + return; + } + + this.$scope.visState = { params: visParams, title: visParams.title }; + this.$scope.esResponse = esResponse; + + this.$scope.visParams = visParams; + this.$scope.renderComplete = resolve; + this.$scope.renderFailed = reject; + this.$scope.resize = Date.now(); + this.$scope.$apply(); + }; + + if (!this.$scope && this.$compile) { + this.$scope = this.$rootScope.$new(); + this.$scope.uiState = handlers.uiState; + this.$scope.filter = handlers.event; + updateScope(); + this.el.find('div').append(this.$compile(tableVisTemplate)(this.$scope)); + this.$scope.$apply(); + } else { + updateScope(); + } + }); + } + + destroy() { + if (this.$rootScope) { + this.$rootScope.$destroy(); + this.$rootScope = null; + } + } + }; +} diff --git a/src/plugins/vis_type_table/public/plugin.ts b/src/plugins/vis_type_table/public/plugin.ts index 28f823df79d91..35ef5fc831cb7 100644 --- a/src/plugins/vis_type_table/public/plugin.ts +++ b/src/plugins/vis_type_table/public/plugin.ts @@ -21,10 +21,11 @@ import { Plugin as ExpressionsPublicPlugin } from '../../expressions/public'; import { VisualizationsSetup } from '../../visualizations/public'; import { createTableVisFn } from './table_vis_fn'; -import { getTableVisTypeDefinition } from './table_vis_type'; +import { tableVisTypeDefinition } from './table_vis_type'; import { DataPublicPluginStart } from '../../data/public'; -import { setFormatService, setKibanaLegacy } from './services'; +import { setFormatService } from './services'; import { KibanaLegacyStart } from '../../kibana_legacy/public'; +import { getTableVisLegacyRenderer } from './legacy/table_vis_legacy_renderer'; /** @internal */ export interface TablePluginSetupDependencies { @@ -39,7 +40,9 @@ export interface TablePluginStartDependencies { } /** @internal */ -export class TableVisPlugin implements Plugin, void> { +export class TableVisPlugin + implements + Plugin, void, TablePluginSetupDependencies, TablePluginStartDependencies> { initializerContext: PluginInitializerContext; createBaseVisualization: any; @@ -48,17 +51,15 @@ export class TableVisPlugin implements Plugin, void> { } public async setup( - core: CoreSetup, + core: CoreSetup, { expressions, visualizations }: TablePluginSetupDependencies ) { expressions.registerFunction(createTableVisFn); - visualizations.createBaseVisualization( - getTableVisTypeDefinition(core, this.initializerContext) - ); + expressions.registerRenderer(getTableVisLegacyRenderer(core, this.initializerContext)); + visualizations.createBaseVisualization(tableVisTypeDefinition); } - public start(core: CoreStart, { data, kibanaLegacy }: TablePluginStartDependencies) { + public start(core: CoreStart, { data }: TablePluginStartDependencies) { setFormatService(data.fieldFormats); - setKibanaLegacy(kibanaLegacy); } } diff --git a/src/plugins/vis_type_table/public/services.ts b/src/plugins/vis_type_table/public/services.ts index b4f996f078f6b..3aaffe75e27f1 100644 --- a/src/plugins/vis_type_table/public/services.ts +++ b/src/plugins/vis_type_table/public/services.ts @@ -19,12 +19,7 @@ import { createGetterSetter } from '../../kibana_utils/public'; import { DataPublicPluginStart } from '../../data/public'; -import { KibanaLegacyStart } from '../../kibana_legacy/public'; export const [getFormatService, setFormatService] = createGetterSetter< DataPublicPluginStart['fieldFormats'] >('table data.fieldFormats'); - -export const [getKibanaLegacy, setKibanaLegacy] = createGetterSetter( - 'table kibanaLegacy' -); diff --git a/src/plugins/vis_type_table/public/table_vis_fn.ts b/src/plugins/vis_type_table/public/table_vis_fn.ts index 9739a7a284e6c..2e446ba4e4fcf 100644 --- a/src/plugins/vis_type_table/public/table_vis_fn.ts +++ b/src/plugins/vis_type_table/public/table_vis_fn.ts @@ -20,6 +20,7 @@ import { i18n } from '@kbn/i18n'; import { tableVisResponseHandler, TableContext } from './table_vis_response_handler'; import { ExpressionFunctionDefinition, KibanaDatatable, Render } from '../../expressions/public'; +import { TableVisConfig } from './types'; export type Input = KibanaDatatable; @@ -27,23 +28,20 @@ interface Arguments { visConfig: string | null; } -type VisParams = Required; - -interface RenderValue { +export interface TableVisRenderValue { visData: TableContext; visType: 'table'; - visConfig: VisParams; - params: { - listenOnChange: boolean; - }; + visConfig: TableVisConfig; } -export const createTableVisFn = (): ExpressionFunctionDefinition< +export type TableExpressionFunctionDefinition = ExpressionFunctionDefinition< 'kibana_table', Input, Arguments, - Render -> => ({ + Render +>; + +export const createTableVisFn = (): TableExpressionFunctionDefinition => ({ name: 'kibana_table', type: 'render', inputTypes: ['kibana_datatable'], @@ -63,14 +61,11 @@ export const createTableVisFn = (): ExpressionFunctionDefinition< return { type: 'render', - as: 'visualization', + as: 'table_vis', value: { visData: convertedData, visType: 'table', visConfig, - params: { - listenOnChange: true, - }, }, }; }, diff --git a/src/plugins/vis_type_table/public/table_vis_type.ts b/src/plugins/vis_type_table/public/table_vis_type.ts index 80d53021b7866..bfc7abac02895 100644 --- a/src/plugins/vis_type_table/public/table_vis_type.ts +++ b/src/plugins/vis_type_table/public/table_vis_type.ts @@ -16,89 +16,82 @@ * specific language governing permissions and limitations * under the License. */ -import { CoreSetup, PluginInitializerContext } from 'kibana/public'; import { i18n } from '@kbn/i18n'; import { AggGroupNames } from '../../data/public'; import { Schemas } from '../../vis_default_editor/public'; -import { Vis } from '../../visualizations/public'; -import { tableVisResponseHandler } from './table_vis_response_handler'; -// @ts-ignore -import tableVisTemplate from './table_vis.html'; +import { BaseVisTypeOptions } from '../../visualizations/public'; + import { TableOptions } from './components/table_vis_options_lazy'; -import { getTableVisualizationControllerClass } from './vis_controller'; import { VIS_EVENT_TO_TRIGGER } from '../../../plugins/visualizations/public'; +import { toExpressionAst } from './to_ast'; +import { TableVisParams } from './types'; -export function getTableVisTypeDefinition(core: CoreSetup, context: PluginInitializerContext) { - return { - type: 'table', - name: 'table', - title: i18n.translate('visTypeTable.tableVisTitle', { - defaultMessage: 'Data Table', - }), - icon: 'visTable', - description: i18n.translate('visTypeTable.tableVisDescription', { - defaultMessage: 'Display values in a table', - }), - visualization: getTableVisualizationControllerClass(core, context), - getSupportedTriggers: () => { - return [VIS_EVENT_TO_TRIGGER.filter]; - }, - visConfig: { - defaults: { - perPage: 10, - showPartialRows: false, - showMetricsAtAllLevels: false, - sort: { - columnIndex: null, - direction: null, - }, - showTotal: false, - totalFunc: 'sum', - percentageCol: '', +export const tableVisTypeDefinition: BaseVisTypeOptions = { + name: 'table', + title: i18n.translate('visTypeTable.tableVisTitle', { + defaultMessage: 'Data Table', + }), + icon: 'visTable', + description: i18n.translate('visTypeTable.tableVisDescription', { + defaultMessage: 'Display values in a table', + }), + getSupportedTriggers: () => { + return [VIS_EVENT_TO_TRIGGER.filter]; + }, + visConfig: { + defaults: { + perPage: 10, + showPartialRows: false, + showMetricsAtAllLevels: false, + sort: { + columnIndex: null, + direction: null, }, - template: tableVisTemplate, + showTotal: false, + totalFunc: 'sum', + percentageCol: '', }, - editorConfig: { - optionsTemplate: TableOptions, - schemas: new Schemas([ - { - group: AggGroupNames.Metrics, - name: 'metric', - title: i18n.translate('visTypeTable.tableVisEditorConfig.schemas.metricTitle', { - defaultMessage: 'Metric', - }), - aggFilter: ['!geo_centroid', '!geo_bounds'], - aggSettings: { - top_hits: { - allowStrings: true, - }, + }, + editorConfig: { + optionsTemplate: TableOptions, + schemas: new Schemas([ + { + group: AggGroupNames.Metrics, + name: 'metric', + title: i18n.translate('visTypeTable.tableVisEditorConfig.schemas.metricTitle', { + defaultMessage: 'Metric', + }), + aggFilter: ['!geo_centroid', '!geo_bounds'], + aggSettings: { + top_hits: { + allowStrings: true, }, - min: 1, - defaults: [{ type: 'count', schema: 'metric' }], - }, - { - group: AggGroupNames.Buckets, - name: 'bucket', - title: i18n.translate('visTypeTable.tableVisEditorConfig.schemas.bucketTitle', { - defaultMessage: 'Split rows', - }), - aggFilter: ['!filter'], - }, - { - group: AggGroupNames.Buckets, - name: 'split', - title: i18n.translate('visTypeTable.tableVisEditorConfig.schemas.splitTitle', { - defaultMessage: 'Split table', - }), - min: 0, - max: 1, - aggFilter: ['!filter'], }, - ]), - }, - responseHandler: tableVisResponseHandler, - hierarchicalData: (vis: Vis) => { - return Boolean(vis.params.showPartialRows || vis.params.showMetricsAtAllLevels); - }, - }; -} + min: 1, + defaults: [{ type: 'count', schema: 'metric' }], + }, + { + group: AggGroupNames.Buckets, + name: 'bucket', + title: i18n.translate('visTypeTable.tableVisEditorConfig.schemas.bucketTitle', { + defaultMessage: 'Split rows', + }), + aggFilter: ['!filter'], + }, + { + group: AggGroupNames.Buckets, + name: 'split', + title: i18n.translate('visTypeTable.tableVisEditorConfig.schemas.splitTitle', { + defaultMessage: 'Split table', + }), + min: 0, + max: 1, + aggFilter: ['!filter'], + }, + ]), + }, + toExpressionAst, + hierarchicalData: (vis) => { + return Boolean(vis.params.showPartialRows || vis.params.showMetricsAtAllLevels); + }, +}; diff --git a/src/plugins/vis_type_table/public/to_ast.test.ts b/src/plugins/vis_type_table/public/to_ast.test.ts new file mode 100644 index 0000000000000..045b5814944b0 --- /dev/null +++ b/src/plugins/vis_type_table/public/to_ast.test.ts @@ -0,0 +1,79 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { Vis } from 'src/plugins/visualizations/public'; +import { toExpressionAst } from './to_ast'; +import { AggTypes, TableVisParams } from './types'; + +const mockSchemas = { + metric: [{ accessor: 1, format: { id: 'number' }, params: {}, label: 'Count', aggType: 'count' }], + bucket: [ + { + accessor: 0, + format: { id: 'date', params: { pattern: 'YYYY-MM-DD HH:mm' } }, + params: {}, + label: 'order_date per 3 hours', + aggType: 'date_histogram', + }, + ], +}; + +jest.mock('../../visualizations/public', () => ({ + getVisSchemas: () => mockSchemas, +})); + +describe('table vis toExpressionAst function', () => { + let vis: Vis; + + beforeEach(() => { + vis = { + isHierarchical: () => false, + type: {}, + params: { + showLabel: false, + }, + data: { + indexPattern: { id: '123' }, + aggs: { + getResponseAggs: () => [], + aggs: [], + }, + }, + } as any; + }); + + it('should match snapshot without params', () => { + const actual = toExpressionAst(vis, {} as any); + expect(actual).toMatchSnapshot(); + }); + + it('should match snapshot based on params & dimensions', () => { + vis.params = { + perPage: 20, + percentageCol: 'Count', + showMetricsAtAllLevels: true, + showPartialRows: true, + showTotal: true, + sort: { columnIndex: null, direction: null }, + totalFunc: AggTypes.SUM, + }; + const actual = toExpressionAst(vis, {} as any); + expect(actual).toMatchSnapshot(); + }); +}); diff --git a/src/plugins/vis_type_table/public/to_ast.ts b/src/plugins/vis_type_table/public/to_ast.ts new file mode 100644 index 0000000000000..449e2dde7f7c9 --- /dev/null +++ b/src/plugins/vis_type_table/public/to_ast.ts @@ -0,0 +1,74 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { EsaggsExpressionFunctionDefinition } from '../../data/common/search/expressions'; +import { buildExpression, buildExpressionFunction } from '../../expressions/public'; +import { getVisSchemas, Vis, BuildPipelineParams } from '../../visualizations/public'; +import { TableExpressionFunctionDefinition } from './table_vis_fn'; +import { TableVisConfig, TableVisParams } from './types'; + +const buildTableVisConfig = ( + schemas: ReturnType, + visParams: TableVisParams +) => { + const visConfig = {} as any; + const metrics = schemas.metric; + const buckets = schemas.bucket || []; + visConfig.dimensions = { + metrics, + buckets, + splitRow: schemas.split_row, + splitColumn: schemas.split_column, + }; + + if (visParams.showPartialRows && !visParams.showMetricsAtAllLevels) { + // Handle case where user wants to see partial rows but not metrics at all levels. + // This requires calculating how many metrics will come back in the tabified response, + // and removing all metrics from the dimensions except the last set. + const metricsPerBucket = metrics.length / buckets.length; + visConfig.dimensions.metrics.splice(0, metricsPerBucket * buckets.length - metricsPerBucket); + } + return visConfig; +}; + +export const toExpressionAst = (vis: Vis, params: BuildPipelineParams) => { + const esaggs = buildExpressionFunction('esaggs', { + index: vis.data.indexPattern!.id!, + metricsAtAllLevels: vis.isHierarchical(), + partialRows: vis.params.showPartialRows, + aggConfigs: JSON.stringify(vis.data.aggs!.aggs), + includeFormatHints: false, + }); + + const schemas = getVisSchemas(vis, params); + + const visConfig: TableVisConfig = { + ...vis.params, + ...buildTableVisConfig(schemas, vis.params), + title: vis.title, + }; + + const table = buildExpressionFunction('kibana_table', { + visConfig: JSON.stringify(visConfig), + }); + + const ast = buildExpression([esaggs, table]); + + return ast.toAst(); +}; diff --git a/src/plugins/vis_type_table/public/types.ts b/src/plugins/vis_type_table/public/types.ts index 39023d1305cb6..c0a995ad5da69 100644 --- a/src/plugins/vis_type_table/public/types.ts +++ b/src/plugins/vis_type_table/public/types.ts @@ -33,7 +33,6 @@ export interface Dimensions { } export interface TableVisParams { - type: 'table'; perPage: number | ''; showPartialRows: boolean; showMetricsAtAllLevels: boolean; @@ -44,5 +43,9 @@ export interface TableVisParams { showTotal: boolean; totalFunc: AggTypes; percentageCol: string; +} + +export interface TableVisConfig extends TableVisParams { + title: string; dimensions: Dimensions; } diff --git a/src/plugins/vis_type_table/public/vis_controller.ts b/src/plugins/vis_type_table/public/vis_controller.ts deleted file mode 100644 index d87812b9f5d69..0000000000000 --- a/src/plugins/vis_type_table/public/vis_controller.ts +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -import { CoreSetup, PluginInitializerContext } from 'kibana/public'; -import angular, { IModule, auto, IRootScopeService, IScope, ICompileService } from 'angular'; -import $ from 'jquery'; - -import { VisParams, ExprVis } from '../../visualizations/public'; -import { getAngularModule } from './get_inner_angular'; -import { getKibanaLegacy } from './services'; -import { initTableVisLegacyModule } from './table_vis_legacy_module'; - -const innerAngularName = 'kibana/table_vis'; - -export function getTableVisualizationControllerClass( - core: CoreSetup, - context: PluginInitializerContext -) { - return class TableVisualizationController { - private tableVisModule: IModule | undefined; - private injector: auto.IInjectorService | undefined; - el: JQuery; - vis: ExprVis; - $rootScope: IRootScopeService | null = null; - $scope: (IScope & { [key: string]: any }) | undefined; - $compile: ICompileService | undefined; - - constructor(domeElement: Element, vis: ExprVis) { - this.el = $(domeElement); - this.vis = vis; - } - - getInjector() { - if (!this.injector) { - const mountpoint = document.createElement('div'); - mountpoint.setAttribute('style', 'height: 100%; width: 100%;'); - this.injector = angular.bootstrap(mountpoint, [innerAngularName]); - this.el.append(mountpoint); - } - - return this.injector; - } - - async initLocalAngular() { - if (!this.tableVisModule) { - const [coreStart] = await core.getStartServices(); - this.tableVisModule = getAngularModule(innerAngularName, coreStart, context); - initTableVisLegacyModule(this.tableVisModule); - } - } - - async render(esResponse: object, visParams: VisParams) { - getKibanaLegacy().loadFontAwesome(); - await this.initLocalAngular(); - - return new Promise(async (resolve, reject) => { - if (!this.$rootScope) { - const $injector = this.getInjector(); - this.$rootScope = $injector.get('$rootScope'); - this.$compile = $injector.get('$compile'); - } - const updateScope = () => { - if (!this.$scope) { - return; - } - - // How things get into this $scope? - // To inject variables into this $scope there's the following pipeline of stuff to check: - // - visualize_embeddable => that's what the editor creates to wrap this Angular component - // - build_pipeline => it serialize all the params into an Angular template compiled on the fly - // - table_vis_fn => unserialize the params and prepare them for the final React/Angular bridge - // - visualization_renderer => creates the wrapper component for this controller and passes the params - // - // In case some prop is missing check into the top of the chain if they are available and check - // the list above that it is passing through - this.$scope.vis = this.vis; - this.$scope.visState = { params: visParams, title: visParams.title }; - this.$scope.esResponse = esResponse; - - this.$scope.visParams = visParams; - this.$scope.renderComplete = resolve; - this.$scope.renderFailed = reject; - this.$scope.resize = Date.now(); - this.$scope.$apply(); - }; - - if (!this.$scope && this.$compile) { - this.$scope = this.$rootScope.$new(); - this.$scope.uiState = this.vis.getUiState(); - updateScope(); - this.el.find('div').append(this.$compile(this.vis.type!.visConfig.template)(this.$scope)); - this.$scope.$apply(); - } else { - updateScope(); - } - }); - } - - destroy() { - if (this.$rootScope) { - this.$rootScope.$destroy(); - this.$rootScope = null; - } - } - }; -} diff --git a/src/plugins/vis_type_tagcloud/kibana.json b/src/plugins/vis_type_tagcloud/kibana.json index 86f72ebfa936d..441a899c3ab53 100644 --- a/src/plugins/vis_type_tagcloud/kibana.json +++ b/src/plugins/vis_type_tagcloud/kibana.json @@ -4,5 +4,5 @@ "ui": true, "server": true, "requiredPlugins": ["data", "expressions", "visualizations", "charts"], - "requiredBundles": ["kibanaUtils", "kibanaReact"] + "requiredBundles": ["kibanaUtils", "kibanaReact", "visDefaultEditor"] } diff --git a/src/plugins/vis_type_tagcloud/public/__snapshots__/tag_cloud_fn.test.ts.snap b/src/plugins/vis_type_tagcloud/public/__snapshots__/tag_cloud_fn.test.ts.snap index 8e28be33515f7..debc7ab27c632 100644 --- a/src/plugins/vis_type_tagcloud/public/__snapshots__/tag_cloud_fn.test.ts.snap +++ b/src/plugins/vis_type_tagcloud/public/__snapshots__/tag_cloud_fn.test.ts.snap @@ -2,25 +2,9 @@ exports[`interpreter/functions#tagcloud returns an object with the correct structure 1`] = ` Object { - "as": "visualization", + "as": "tagloud_vis", "type": "render", "value": Object { - "params": Object { - "listenOnChange": true, - }, - "visConfig": Object { - "maxFontSize": 72, - "metric": Object { - "accessor": 0, - "format": Object { - "id": "number", - }, - }, - "minFontSize": 18, - "orientation": "single", - "scale": "linear", - "showLabel": true, - }, "visData": Object { "columns": Array [ Object { @@ -35,6 +19,19 @@ Object { ], "type": "kibana_datatable", }, + "visParams": Object { + "maxFontSize": 72, + "metric": Object { + "accessor": 0, + "format": Object { + "id": "number", + }, + }, + "minFontSize": 18, + "orientation": "single", + "scale": "linear", + "showLabel": true, + }, "visType": "tagcloud", }, } diff --git a/src/plugins/vis_type_tagcloud/public/__snapshots__/to_ast.test.ts.snap b/src/plugins/vis_type_tagcloud/public/__snapshots__/to_ast.test.ts.snap new file mode 100644 index 0000000000000..d64bdfb1f46f9 --- /dev/null +++ b/src/plugins/vis_type_tagcloud/public/__snapshots__/to_ast.test.ts.snap @@ -0,0 +1,171 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`tagcloud vis toExpressionAst function should match snapshot params fulfilled 1`] = ` +Object { + "chain": Array [ + Object { + "arguments": Object { + "aggConfigs": Array [ + "[]", + ], + "includeFormatHints": Array [ + false, + ], + "index": Array [ + "123", + ], + "metricsAtAllLevels": Array [ + false, + ], + "partialRows": Array [ + false, + ], + }, + "function": "esaggs", + "type": "function", + }, + Object { + "arguments": Object { + "bucket": Array [ + Object { + "chain": Array [ + Object { + "arguments": Object { + "accessor": Array [ + 0, + ], + "format": Array [ + "terms", + ], + "formatParams": Array [ + "{\\"id\\":\\"string\\",\\"otherBucketLabel\\":\\"Other\\",\\"missingBucketLabel\\":\\"Missing\\"}", + ], + }, + "function": "visdimension", + "type": "function", + }, + ], + "type": "expression", + }, + ], + "maxFontSize": Array [ + 15, + ], + "metric": Array [ + Object { + "chain": Array [ + Object { + "arguments": Object { + "accessor": Array [ + 1, + ], + "format": Array [ + "number", + ], + }, + "function": "visdimension", + "type": "function", + }, + ], + "type": "expression", + }, + ], + "minFontSize": Array [ + 5, + ], + "orientation": Array [ + "single", + ], + "scale": Array [ + "linear", + ], + "showLabel": Array [ + true, + ], + }, + "function": "tagcloud", + "type": "function", + }, + ], + "type": "expression", +} +`; + +exports[`tagcloud vis toExpressionAst function should match snapshot without params 1`] = ` +Object { + "chain": Array [ + Object { + "arguments": Object { + "aggConfigs": Array [ + "[]", + ], + "includeFormatHints": Array [ + false, + ], + "index": Array [ + "123", + ], + "metricsAtAllLevels": Array [ + false, + ], + "partialRows": Array [ + false, + ], + }, + "function": "esaggs", + "type": "function", + }, + Object { + "arguments": Object { + "bucket": Array [ + Object { + "chain": Array [ + Object { + "arguments": Object { + "accessor": Array [ + 0, + ], + "format": Array [ + "terms", + ], + "formatParams": Array [ + "{\\"id\\":\\"string\\",\\"otherBucketLabel\\":\\"Other\\",\\"missingBucketLabel\\":\\"Missing\\"}", + ], + }, + "function": "visdimension", + "type": "function", + }, + ], + "type": "expression", + }, + ], + "metric": Array [ + Object { + "chain": Array [ + Object { + "arguments": Object { + "accessor": Array [ + 1, + ], + "format": Array [ + "number", + ], + }, + "function": "visdimension", + "type": "function", + }, + ], + "type": "expression", + }, + ], + "showLabel": Array [ + false, + ], + }, + "function": "tagcloud", + "type": "function", + }, + ], + "type": "expression", +} +`; diff --git a/src/plugins/vis_type_tagcloud/public/_tag_cloud.scss b/src/plugins/vis_type_tagcloud/public/_tag_cloud.scss deleted file mode 100644 index 08901bebc0349..0000000000000 --- a/src/plugins/vis_type_tagcloud/public/_tag_cloud.scss +++ /dev/null @@ -1,14 +0,0 @@ -.tgcVis { - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 100%; - overflow: hidden; -} - -.tgcVisLabel { - width: 100%; - text-align: center; - font-weight: $euiFontWeightBold; -} diff --git a/src/plugins/vis_type_tagcloud/public/components/label.js b/src/plugins/vis_type_tagcloud/public/components/label.js index 168ec4b270fde..88b3c2f851138 100644 --- a/src/plugins/vis_type_tagcloud/public/components/label.js +++ b/src/plugins/vis_type_tagcloud/public/components/label.js @@ -28,7 +28,7 @@ export class Label extends Component { render() { return (
{this.state.label} diff --git a/src/plugins/vis_type_tagcloud/public/components/tag_cloud.scss b/src/plugins/vis_type_tagcloud/public/components/tag_cloud.scss new file mode 100644 index 0000000000000..37867f1ed1c17 --- /dev/null +++ b/src/plugins/vis_type_tagcloud/public/components/tag_cloud.scss @@ -0,0 +1,26 @@ +// Prefix all styles with "tgc" to avoid conflicts. +// Examples +// tgcChart +// tgcChart__legend +// tgcChart__legend--small +// tgcChart__legend-isLoading + +.tgcChart__container, .tgcChart__wrapper { + flex: 1 1 0; + display: flex; +} + +.tgcChart { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + overflow: hidden; +} + +.tgcChart__label { + width: 100%; + text-align: center; + font-weight: $euiFontWeightBold; +} diff --git a/src/plugins/vis_type_tagcloud/public/components/tag_cloud_chart.tsx b/src/plugins/vis_type_tagcloud/public/components/tag_cloud_chart.tsx new file mode 100644 index 0000000000000..18a09ec9f4969 --- /dev/null +++ b/src/plugins/vis_type_tagcloud/public/components/tag_cloud_chart.tsx @@ -0,0 +1,84 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React, { useEffect, useMemo, useRef } from 'react'; +import { EuiResizeObserver } from '@elastic/eui'; +import { throttle } from 'lodash'; + +import { TagCloudVisDependencies } from '../plugin'; +import { TagCloudVisRenderValue } from '../tag_cloud_fn'; +// @ts-ignore +import { TagCloudVisualization } from './tag_cloud_visualization'; + +import './tag_cloud.scss'; + +type TagCloudChartProps = TagCloudVisDependencies & + TagCloudVisRenderValue & { + fireEvent: (event: any) => void; + renderComplete: () => void; + }; + +export const TagCloudChart = ({ + colors, + visData, + visParams, + fireEvent, + renderComplete, +}: TagCloudChartProps) => { + const chartDiv = useRef(null); + const visController = useRef(null); + + useEffect(() => { + visController.current = new TagCloudVisualization(chartDiv.current, colors, fireEvent); + return () => { + visController.current.destroy(); + visController.current = null; + }; + }, [colors, fireEvent]); + + useEffect(() => { + if (visController.current) { + visController.current.render(visData, visParams).then(renderComplete); + } + }, [visData, visParams, renderComplete]); + + const updateChartSize = useMemo( + () => + throttle(() => { + if (visController.current) { + visController.current.render().then(renderComplete); + } + }, 300), + [renderComplete] + ); + + return ( + + {(resizeRef) => ( +
+
+
+ )} + + ); +}; + +// default export required for React.Lazy +// eslint-disable-next-line import/no-default-export +export { TagCloudChart as default }; diff --git a/src/plugins/vis_type_tagcloud/public/components/tag_cloud_visualization.js b/src/plugins/vis_type_tagcloud/public/components/tag_cloud_visualization.js index e43b3bdc747ab..5ec22d2c6a4d9 100644 --- a/src/plugins/vis_type_tagcloud/public/components/tag_cloud_visualization.js +++ b/src/plugins/vis_type_tagcloud/public/components/tag_cloud_visualization.js @@ -32,126 +32,138 @@ import d3 from 'd3'; const MAX_TAG_COUNT = 200; -export function createTagCloudVisualization({ colors }) { - const colorScale = d3.scale.ordinal().range(colors.seedColors); - return class TagCloudVisualization { - constructor(node, vis) { - this._containerNode = node; - - const cloudRelativeContainer = document.createElement('div'); - cloudRelativeContainer.classList.add('tgcVis'); - cloudRelativeContainer.setAttribute('style', 'position: relative'); - const cloudContainer = document.createElement('div'); - cloudContainer.classList.add('tgcVis'); - cloudContainer.setAttribute('data-test-subj', 'tagCloudVisualization'); - this._containerNode.classList.add('visChart--vertical'); - cloudRelativeContainer.appendChild(cloudContainer); - this._containerNode.appendChild(cloudRelativeContainer); - - this._vis = vis; - this._truncated = false; - this._tagCloud = new TagCloud(cloudContainer, colorScale); - this._tagCloud.on('select', (event) => { - if (!this._visParams.bucket) { - return; - } - this._vis.API.events.filter({ - table: event.meta.data, - column: 0, - row: event.meta.rowIndex, - }); - }); - this._renderComplete$ = Rx.fromEvent(this._tagCloud, 'renderComplete'); - - this._feedbackNode = document.createElement('div'); - this._containerNode.appendChild(this._feedbackNode); - this._feedbackMessage = React.createRef(); - render( - - - , - this._feedbackNode - ); - - this._labelNode = document.createElement('div'); - this._containerNode.appendChild(this._labelNode); - this._label = React.createRef(); - render(
@@ -377,7 +427,6 @@ exports[`NewVisModal filter for visualization types should render as expected 1` aria-label="Start creating your visualization by selecting a type for that visualization. Hit escape to close this modal. Hit Tab key to go further." className="visNewVisDialog" onClose={[Function]} - role="menu" >
- 2 types found + 3 types found @@ -627,6 +675,75 @@ exports[`NewVisModal filter for visualization types should render as expected 1` className="euiKeyPadMenu visNewVisDialog__types" data-test-subj="visNewDialogTypes" > +
  • + + Vis alias with promotion + + } + onBlur={[Function]} + onClick={[Function]} + onFocus={[Function]} + onMouseEnter={[Function]} + onMouseLeave={[Function]} + > + + +
  • @@ -649,7 +766,6 @@ exports[`NewVisModal filter for visualization types should render as expected 1` onFocus={[Function]} onMouseEnter={[Function]} onMouseLeave={[Function]} - role="menuitem" > + +
  • @@ -1060,7 +1245,6 @@ exports[`NewVisModal should render as expected 1`] = `
    @@ -1273,7 +1508,6 @@ exports[`NewVisModal should render as expected 1`] = ` aria-label="Start creating your visualization by selecting a type for that visualization. Hit escape to close this modal. Hit Tab key to go further." className="visNewVisDialog" onClose={[Function]} - role="menu" >
    +
  • + + Vis alias with promotion + + } + onBlur={[Function]} + onClick={[Function]} + onFocus={[Function]} + onMouseEnter={[Function]} + onMouseLeave={[Function]} + > + + +
  • @@ -1494,7 +1796,6 @@ exports[`NewVisModal should render as expected 1`] = ` onFocus={[Function]} onMouseEnter={[Function]} onMouseLeave={[Function]} - role="menuitem" > + +
  • diff --git a/src/plugins/visualizations/public/wizard/new_vis_modal.test.tsx b/src/plugins/visualizations/public/wizard/new_vis_modal.test.tsx index f48febfef5b43..51bcfed201687 100644 --- a/src/plugins/visualizations/public/wizard/new_vis_modal.test.tsx +++ b/src/plugins/visualizations/public/wizard/new_vis_modal.test.tsx @@ -51,13 +51,24 @@ describe('NewVisModal', () => { aliasApp: 'otherApp', aliasPath: '#/aliasUrl', }, + { + name: 'visAliasWithPromotion', + title: 'Vis alias with promotion', + stage: 'production', + aliasApp: 'anotherApp', + aliasPath: '#/anotherUrl', + promotion: { + description: 'promotion description', + buttonText: 'another app', + }, + }, ]; const visTypes: TypesStart = { - get: (id: string) => { - return _visTypes.find((vis) => vis.name === id) as VisType; + get(id: string): VisType { + return (_visTypes.find((vis) => vis.name === id) as unknown) as VisType; }, all: () => { - return _visTypes as VisType[]; + return (_visTypes as unknown) as VisType[]; }, getAliases: () => [], }; @@ -107,6 +118,30 @@ describe('NewVisModal', () => { expect(wrapper.find('[data-test-subj="visType-vis"]').exists()).toBe(true); }); + it('should sort promoted visualizations first', () => { + const wrapper = mountWithIntl( + null} + visTypesRegistry={visTypes} + addBasePath={addBasePath} + uiSettings={uiSettings} + application={{} as ApplicationStart} + savedObjects={{} as SavedObjectsStart} + /> + ); + expect( + wrapper + .find('button[data-test-subj^="visType-"]') + .map((button) => button.prop('data-test-subj')) + ).toEqual([ + 'visType-visAliasWithPromotion', + 'visType-vis', + 'visType-visWithAliasUrl', + 'visType-visWithSearch', + ]); + }); + describe('open editor', () => { it('should open the editor for visualizations without search', () => { const wrapper = mountWithIntl( diff --git a/src/plugins/visualizations/public/wizard/new_vis_modal.tsx b/src/plugins/visualizations/public/wizard/new_vis_modal.tsx index 1d01900ceffc2..4bedd3eb1c22a 100644 --- a/src/plugins/visualizations/public/wizard/new_vis_modal.tsx +++ b/src/plugins/visualizations/public/wizard/new_vis_modal.tsx @@ -108,7 +108,6 @@ class NewVisModal extends React.Component void; originatingApp?: string; outsideVisualizeApp?: boolean; + createByValue?: boolean; } /** diff --git a/src/plugins/visualizations/public/wizard/type_selection/new_vis_help.test.tsx b/src/plugins/visualizations/public/wizard/type_selection/new_vis_help.test.tsx index fa15a6c9ba02b..a5b6e8039ba6d 100644 --- a/src/plugins/visualizations/public/wizard/type_selection/new_vis_help.test.tsx +++ b/src/plugins/visualizations/public/wizard/type_selection/new_vis_help.test.tsx @@ -31,7 +31,6 @@ describe('NewVisHelp', () => { aliasApp: 'myApp', aliasPath: '/my/fancy/new/thing', description: 'Some desc', - highlighted: false, icon: 'whatever', name: 'whatever', promotion: { diff --git a/src/plugins/visualizations/public/wizard/type_selection/new_vis_help.tsx b/src/plugins/visualizations/public/wizard/type_selection/new_vis_help.tsx index fc48438904589..5b226a889408f 100644 --- a/src/plugins/visualizations/public/wizard/type_selection/new_vis_help.tsx +++ b/src/plugins/visualizations/public/wizard/type_selection/new_vis_help.tsx @@ -20,11 +20,10 @@ import { FormattedMessage } from '@kbn/i18n/react'; import React, { Fragment } from 'react'; import { EuiText, EuiButton } from '@elastic/eui'; -import { VisTypeAliasListEntry } from './type_selection'; import { VisTypeAlias } from '../../vis_types'; interface Props { - promotedTypes: VisTypeAliasListEntry[]; + promotedTypes: VisTypeAlias[]; onPromotionClicked: (visType: VisTypeAlias) => void; } diff --git a/src/plugins/visualizations/public/wizard/type_selection/type_selection.tsx b/src/plugins/visualizations/public/wizard/type_selection/type_selection.tsx index 0555b95648bc1..8c086ed132ae4 100644 --- a/src/plugins/visualizations/public/wizard/type_selection/type_selection.tsx +++ b/src/plugins/visualizations/public/wizard/type_selection/type_selection.tsx @@ -42,11 +42,8 @@ import { VisHelpText } from './vis_help_text'; import { VisTypeIcon } from './vis_type_icon'; import { VisType, TypesStart } from '../../vis_types'; -export interface VisTypeListEntry extends VisType { - highlighted: boolean; -} - -export interface VisTypeAliasListEntry extends VisTypeAlias { +interface VisTypeListEntry { + type: VisType | VisTypeAlias; highlighted: boolean; } @@ -69,6 +66,10 @@ interface TypeSelectionState { query: string; } +function isVisTypeAlias(type: VisType | VisTypeAlias): type is VisTypeAlias { + return 'aliasPath' in type; +} + class TypeSelection extends React.Component { public state: TypeSelectionState = { highlightedType: null, @@ -155,7 +156,9 @@ class TypeSelection extends React.Component t.promotion)} + promotedTypes={visTypes + .map((t) => t.type) + .filter((t): t is VisTypeAlias => isVisTypeAlias(t) && Boolean(t.promotion))} onPromotionClicked={this.props.onVisTypeSelected} /> @@ -167,10 +170,7 @@ class TypeSelection extends React.Component { + private filteredVisTypes(visTypes: TypesStart, query: string): VisTypeListEntry[] { const types = visTypes.all().filter((type) => { // Filter out all lab visualizations if lab mode is not enabled if (!this.props.showExperimental && type.stage === 'experimental') { @@ -187,9 +187,9 @@ class TypeSelection extends React.Component; + let entries: VisTypeListEntry[]; if (!query) { - entries = allTypes.map((type) => ({ ...type, highlighted: false })); + entries = allTypes.map((type) => ({ type, highlighted: false })); } else { const q = query.toLowerCase(); entries = allTypes.map((type) => { @@ -197,17 +197,21 @@ class TypeSelection extends React.Component { + private renderVisType = (visType: VisTypeListEntry) => { let stage = {}; let highlightMsg; - if (!('aliasPath' in visType) && visType.stage === 'experimental') { + if (!isVisTypeAlias(visType.type) && visType.type.stage === 'experimental') { stage = { betaBadgeLabel: i18n.translate('visualizations.newVisWizard.experimentalTitle', { defaultMessage: 'Experimental', @@ -221,7 +225,7 @@ class TypeSelection extends React.Component this.props.onVisTypeSelected(visType); + const onClick = () => this.props.onVisTypeSelected(visType.type); const highlightedType: HighlightedType = { - title: visType.title, - name: visType.name, - description: visType.description, + title: visType.type.title, + name: visType.type.name, + description: visType.type.description, highlightMsg, }; return ( {visType.title}} + key={visType.type.name} + label={{visType.type.title}} onClick={onClick} onFocus={() => this.setHighlightType(highlightedType)} onMouseEnter={() => this.setHighlightType(highlightedType)} onMouseLeave={() => this.setHighlightType(null)} onBlur={() => this.setHighlightType(null)} className="visNewVisDialog__type" - data-test-subj={`visType-${visType.name}`} - data-vis-stage={!('aliasPath' in visType) ? visType.stage : 'alias'} + data-test-subj={`visType-${visType.type.name}`} + data-vis-stage={!isVisTypeAlias(visType.type) ? visType.type.stage : 'alias'} disabled={isDisabled} - aria-describedby={`visTypeDescription-${visType.name}`} - role="menuitem" + aria-describedby={`visTypeDescription-${visType.type.name}`} {...stage} > ); diff --git a/src/plugins/visualizations/server/saved_objects/visualization.ts b/src/plugins/visualizations/server/saved_objects/visualization.ts index ad7618a8640ba..5261b2cac7dcf 100644 --- a/src/plugins/visualizations/server/saved_objects/visualization.ts +++ b/src/plugins/visualizations/server/saved_objects/visualization.ts @@ -45,13 +45,13 @@ export const visualizationSavedObjectType: SavedObjectsType = { properties: { description: { type: 'text' }, kibanaSavedObjectMeta: { - properties: { searchSourceJSON: { type: 'text', index: false, doc_values: false } }, + properties: { searchSourceJSON: { type: 'text', index: false } }, }, savedSearchRefName: { type: 'keyword', index: false, doc_values: false }, title: { type: 'text' }, - uiStateJSON: { type: 'text', index: false, doc_values: false }, + uiStateJSON: { type: 'text', index: false }, version: { type: 'integer' }, - visState: { type: 'text', index: false, doc_values: false }, + visState: { type: 'text', index: false }, }, }, migrations: visualizationSavedObjectTypeMigrations, diff --git a/src/plugins/visualizations/server/saved_objects/visualization_migrations.test.ts b/src/plugins/visualizations/server/saved_objects/visualization_migrations.test.ts index dc8bae69ca377..c4ee92194ec36 100644 --- a/src/plugins/visualizations/server/saved_objects/visualization_migrations.test.ts +++ b/src/plugins/visualizations/server/saved_objects/visualization_migrations.test.ts @@ -22,6 +22,50 @@ import { SavedObjectMigrationContext, SavedObjectMigrationFn } from 'kibana/serv const savedObjectMigrationContext = (null as unknown) as SavedObjectMigrationContext; +const testMigrateMatchAllQuery = (migrate: Function) => { + it('should migrate obsolete match_all query', () => { + const migratedDoc = migrate({ + type: 'area', + attributes: { + kibanaSavedObjectMeta: { + searchSourceJSON: JSON.stringify({ + query: { + match_all: {}, + }, + }), + }, + }, + }); + + const migratedSearchSource = JSON.parse( + migratedDoc.attributes.kibanaSavedObjectMeta.searchSourceJSON + ); + + expect(migratedSearchSource).toEqual({ + query: { + query: '', + language: 'kuery', + }, + }); + }); + + it('should return original doc if searchSourceJSON cannot be parsed', () => { + const migratedDoc = migrate({ + type: 'area', + attributes: { + kibanaSavedObjectMeta: 'kibanaSavedObjectMeta', + }, + }); + + expect(migratedDoc).toEqual({ + type: 'area', + attributes: { + kibanaSavedObjectMeta: 'kibanaSavedObjectMeta', + }, + }); + }); +}; + describe('migration visualization', () => { describe('6.7.2', () => { const migrate = (doc: any) => @@ -31,6 +75,10 @@ describe('migration visualization', () => { ); let doc: any; + describe('migrateMatchAllQuery', () => { + testMigrateMatchAllQuery(migrate); + }); + describe('date histogram time zone removal', () => { beforeEach(() => { doc = { @@ -150,32 +198,6 @@ describe('migration visualization', () => { expect(aggs[3]).not.toHaveProperty('params.customBucket.params.time_zone'); expect(aggs[2]).not.toHaveProperty('params.time_zone'); }); - - it('should migrate obsolete match_all query', () => { - const migratedDoc = migrate({ - ...doc, - attributes: { - ...doc.attributes, - kibanaSavedObjectMeta: { - searchSourceJSON: JSON.stringify({ - query: { - match_all: {}, - }, - }), - }, - }, - }); - const migratedSearchSource = JSON.parse( - migratedDoc.attributes.kibanaSavedObjectMeta.searchSourceJSON - ); - - expect(migratedSearchSource).toEqual({ - query: { - query: '', - language: 'kuery', - }, - }); - }); }); }); @@ -1487,6 +1509,18 @@ describe('migration visualization', () => { }); }); + describe('7.9.3', () => { + const migrate = (doc: any) => + visualizationSavedObjectTypeMigrations['7.9.3']( + doc as Parameters[0], + savedObjectMigrationContext + ); + + describe('migrateMatchAllQuery', () => { + testMigrateMatchAllQuery(migrate); + }); + }); + describe('7.8.0 tsvb split_color_mode', () => { const migrate = (doc: any) => visualizationSavedObjectTypeMigrations['7.8.0']( diff --git a/src/plugins/visualizations/server/saved_objects/visualization_migrations.ts b/src/plugins/visualizations/server/saved_objects/visualization_migrations.ts index 170d7c460b06a..fbeefacf6035f 100644 --- a/src/plugins/visualizations/server/saved_objects/visualization_migrations.ts +++ b/src/plugins/visualizations/server/saved_objects/visualization_migrations.ts @@ -655,6 +655,12 @@ const migrateTableSplits: SavedObjectMigrationFn = (doc) => { } }; +/** + * This migration script is related to: + * @link https://github.com/elastic/kibana/pull/62194 + * @link https://github.com/elastic/kibana/pull/14644 + * This is only a problem when you import an object from 5.x into 6.x but to be sure that all saved objects migrated we should execute it twice in 6.7.2 and 7.9.3 + */ const migrateMatchAllQuery: SavedObjectMigrationFn = (doc) => { const searchSourceJSON = get(doc, 'attributes.kibanaSavedObjectMeta.searchSourceJSON'); @@ -665,6 +671,7 @@ const migrateMatchAllQuery: SavedObjectMigrationFn = (doc) => { searchSource = JSON.parse(searchSourceJSON); } catch (e) { // Let it go, the data is invalid and we'll leave it as is + return doc; } if (searchSource.query?.match_all) { @@ -781,5 +788,6 @@ export const visualizationSavedObjectTypeMigrations = { '7.4.2': flow(transformSplitFiltersStringToQueryObject), '7.7.0': flow(migrateOperatorKeyTypo, migrateSplitByChartRow), '7.8.0': flow(migrateTsvbDefaultColorPalettes), + '7.9.3': flow(migrateMatchAllQuery), '7.10.0': flow(migrateFilterRatioQuery, removeTSVBSearchSource), }; diff --git a/src/plugins/visualizations/server/usage_collector/get_usage_collector.mock.ts b/src/plugins/visualizations/server/usage_collector/get_usage_collector.mock.ts new file mode 100644 index 0000000000000..70be4c273b77f --- /dev/null +++ b/src/plugins/visualizations/server/usage_collector/get_usage_collector.mock.ts @@ -0,0 +1,24 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export const mockStats = { somestat: 1 }; +export const mockGetStats = jest.fn().mockResolvedValue(mockStats); +jest.doMock('./get_usage_collector', () => ({ + getStats: mockGetStats, +})); diff --git a/src/plugins/visualizations/server/usage_collector/get_usage_collector.test.ts b/src/plugins/visualizations/server/usage_collector/get_usage_collector.test.ts index 108f270bc8eab..fd363b3505186 100644 --- a/src/plugins/visualizations/server/usage_collector/get_usage_collector.test.ts +++ b/src/plugins/visualizations/server/usage_collector/get_usage_collector.test.ts @@ -18,10 +18,8 @@ */ import moment from 'moment'; -import { of } from 'rxjs'; - import { LegacyAPICaller } from 'src/core/server'; -import { getUsageCollector } from './get_usage_collector'; +import { getStats } from './get_usage_collector'; const defaultMockSavedObjects = [ { @@ -121,29 +119,22 @@ const enlargedMockSavedObjects = [ ]; describe('Visualizations usage collector', () => { - const configMock = of({ kibana: { index: '' } }); - const usageCollector = getUsageCollector(configMock); + const mockIndex = ''; const getMockCallCluster = (hits: unknown[]) => (() => Promise.resolve({ hits: { hits } }) as unknown) as LegacyAPICaller; - test('Should fit the shape', () => { - expect(usageCollector.type).toBe('visualization_types'); - expect(usageCollector.isReady()).toBe(true); - expect(usageCollector.fetch).toEqual(expect.any(Function)); - }); - test('Returns undefined when no results found (undefined)', async () => { - const result = await usageCollector.fetch(getMockCallCluster(undefined as any)); - expect(result).toBe(undefined); + const result = await getStats(getMockCallCluster(undefined as any), mockIndex); + expect(result).toBeUndefined(); }); test('Returns undefined when no results found (0 results)', async () => { - const result = await usageCollector.fetch(getMockCallCluster([])); - expect(result).toBe(undefined); + const result = await getStats(getMockCallCluster([]), mockIndex); + expect(result).toBeUndefined(); }); test('Summarizes visualizations response data', async () => { - const result = await usageCollector.fetch(getMockCallCluster(defaultMockSavedObjects)); + const result = await getStats(getMockCallCluster(defaultMockSavedObjects), mockIndex); expect(result).toMatchObject({ shell_beads: { @@ -198,7 +189,7 @@ describe('Visualizations usage collector', () => { }, }; - const result = await usageCollector.fetch(getMockCallCluster(enlargedMockSavedObjects)); + const result = await getStats(getMockCallCluster(enlargedMockSavedObjects), mockIndex); expect(result).toMatchObject(expectedStats); }); diff --git a/src/plugins/visualizations/server/usage_collector/get_usage_collector.ts b/src/plugins/visualizations/server/usage_collector/get_usage_collector.ts index 9ba09a3303b5f..aed9a54dcf01a 100644 --- a/src/plugins/visualizations/server/usage_collector/get_usage_collector.ts +++ b/src/plugins/visualizations/server/usage_collector/get_usage_collector.ts @@ -17,16 +17,12 @@ * under the License. */ -import { Observable } from 'rxjs'; import { countBy, get, groupBy, mapValues, max, min, values } from 'lodash'; -import { first } from 'rxjs/operators'; import { SearchResponse } from 'elasticsearch'; import { LegacyAPICaller } from 'src/core/server'; import { getPastDays } from './get_past_days'; -const VIS_USAGE_TYPE = 'visualization_types'; - type ESResponse = SearchResponse<{ visualization: { visState: string } }>; interface VisSummary { @@ -35,10 +31,25 @@ interface VisSummary { past_days: number; } +export interface VisualizationUsage { + [x: string]: { + total: number; + spaces_min?: number; + spaces_max?: number; + spaces_avg: number; + saved_7_days_total: number; + saved_30_days_total: number; + saved_90_days_total: number; + }; +} + /* * Parse the response data into telemetry payload */ -async function getStats(callCluster: LegacyAPICaller, index: string) { +export async function getStats( + callCluster: LegacyAPICaller, + index: string +): Promise { const searchParams = { size: 10000, // elasticsearch index.max_result_window default value index, @@ -94,14 +105,3 @@ async function getStats(callCluster: LegacyAPICaller, index: string) { }; }); } - -export function getUsageCollector(config: Observable<{ kibana: { index: string } }>) { - return { - type: VIS_USAGE_TYPE, - isReady: () => true, - fetch: async (callCluster: LegacyAPICaller) => { - const index = (await config.pipe(first()).toPromise()).kibana.index; - return await getStats(callCluster, index); - }, - }; -} diff --git a/src/plugins/visualizations/server/usage_collector/index.ts b/src/plugins/visualizations/server/usage_collector/index.ts index 90ee65bb6ad2a..fb7e895d9d64a 100644 --- a/src/plugins/visualizations/server/usage_collector/index.ts +++ b/src/plugins/visualizations/server/usage_collector/index.ts @@ -17,15 +17,4 @@ * under the License. */ -import { Observable } from 'rxjs'; - -import { UsageCollectionSetup } from 'src/plugins/usage_collection/server'; -import { getUsageCollector } from './get_usage_collector'; - -export function registerVisualizationsCollector( - collectorSet: UsageCollectionSetup, - config: Observable<{ kibana: { index: string } }> -): void { - const collector = collectorSet.makeUsageCollector(getUsageCollector(config)); - collectorSet.registerCollector(collector); -} +export { registerVisualizationsCollector } from './register_visualizations_collector'; diff --git a/src/plugins/visualizations/server/usage_collector/register_visualizations_collector.test.ts b/src/plugins/visualizations/server/usage_collector/register_visualizations_collector.test.ts new file mode 100644 index 0000000000000..38d88dd65001b --- /dev/null +++ b/src/plugins/visualizations/server/usage_collector/register_visualizations_collector.test.ts @@ -0,0 +1,67 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { of } from 'rxjs'; +import { mockStats, mockGetStats } from './get_usage_collector.mock'; +import { createUsageCollectionSetupMock } from 'src/plugins/usage_collection/server/usage_collection.mock'; + +import { registerVisualizationsCollector } from './register_visualizations_collector'; + +describe('registerVisualizationsCollector', () => { + const mockIndex = 'mock_index'; + const mockConfig = of({ kibana: { index: mockIndex } }); + + it('makes a usage collector and registers it`', () => { + const mockCollectorSet = createUsageCollectionSetupMock(); + registerVisualizationsCollector(mockCollectorSet, mockConfig); + expect(mockCollectorSet.makeUsageCollector).toBeCalledTimes(1); + expect(mockCollectorSet.registerCollector).toBeCalledTimes(1); + }); + + it('makeUsageCollector configs fit the shape', () => { + const mockCollectorSet = createUsageCollectionSetupMock(); + registerVisualizationsCollector(mockCollectorSet, mockConfig); + expect(mockCollectorSet.makeUsageCollector).toHaveBeenCalledWith({ + type: 'visualization_types', + isReady: expect.any(Function), + fetch: expect.any(Function), + schema: expect.any(Object), + }); + const usageCollectorConfig = mockCollectorSet.makeUsageCollector.mock.calls[0][0]; + expect(usageCollectorConfig.isReady()).toBe(true); + }); + + it('makeUsageCollector config.isReady returns true', () => { + const mockCollectorSet = createUsageCollectionSetupMock(); + registerVisualizationsCollector(mockCollectorSet, mockConfig); + const usageCollectorConfig = mockCollectorSet.makeUsageCollector.mock.calls[0][0]; + expect(usageCollectorConfig.isReady()).toBe(true); + }); + + it('makeUsageCollector config.fetch calls getStats', async () => { + const mockCollectorSet = createUsageCollectionSetupMock(); + registerVisualizationsCollector(mockCollectorSet, mockConfig); + const usageCollectorConfig = mockCollectorSet.makeUsageCollector.mock.calls[0][0]; + const mockCallCluster = jest.fn(); + const fetchResult = await usageCollectorConfig.fetch(mockCallCluster); + expect(mockGetStats).toBeCalledTimes(1); + expect(mockGetStats).toBeCalledWith(mockCallCluster, mockIndex); + expect(fetchResult).toBe(mockStats); + }); +}); diff --git a/src/plugins/visualizations/server/usage_collector/register_visualizations_collector.ts b/src/plugins/visualizations/server/usage_collector/register_visualizations_collector.ts new file mode 100644 index 0000000000000..5919b3d20642f --- /dev/null +++ b/src/plugins/visualizations/server/usage_collector/register_visualizations_collector.ts @@ -0,0 +1,50 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { Observable } from 'rxjs'; +import { first } from 'rxjs/operators'; +import { UsageCollectionSetup } from 'src/plugins/usage_collection/server'; + +import { getStats, VisualizationUsage } from './get_usage_collector'; + +export function registerVisualizationsCollector( + collectorSet: UsageCollectionSetup, + config: Observable<{ kibana: { index: string } }> +) { + const collector = collectorSet.makeUsageCollector({ + type: 'visualization_types', + isReady: () => true, + schema: { + DYNAMIC_KEY: { + total: { type: 'long' }, + spaces_min: { type: 'long' }, + spaces_max: { type: 'long' }, + spaces_avg: { type: 'long' }, + saved_7_days_total: { type: 'long' }, + saved_30_days_total: { type: 'long' }, + saved_90_days_total: { type: 'long' }, + }, + }, + fetch: async (callCluster) => { + const index = (await config.pipe(first()).toPromise()).kibana.index; + return await getStats(callCluster, index); + }, + }); + collectorSet.registerCollector(collector); +} diff --git a/src/plugins/visualize/kibana.json b/src/plugins/visualize/kibana.json index 318a1562efdfe..2e40d29158600 100644 --- a/src/plugins/visualize/kibana.json +++ b/src/plugins/visualize/kibana.json @@ -18,6 +18,7 @@ "kibanaUtils", "kibanaReact", "home", - "discover" + "discover", + "visDefaultEditor" ] } diff --git a/src/plugins/visualize/public/actions/visualize_field_action.ts b/src/plugins/visualize/public/actions/visualize_field_action.ts index 6671d2c981910..e570ed5e49e6a 100644 --- a/src/plugins/visualize/public/actions/visualize_field_action.ts +++ b/src/plugins/visualize/public/actions/visualize_field_action.ts @@ -34,6 +34,7 @@ import { AGGS_TERMS_SIZE_SETTING } from '../../common/constants'; export const visualizeFieldAction = createAction({ type: ACTION_VISUALIZE_FIELD, + id: ACTION_VISUALIZE_FIELD, getDisplayName: () => i18n.translate('visualize.discover.visualizeFieldLabel', { defaultMessage: 'Visualize field', diff --git a/src/plugins/visualize/public/application/app.tsx b/src/plugins/visualize/public/application/app.tsx index 8dd6b2ace8413..bf11cde3115aa 100644 --- a/src/plugins/visualize/public/application/app.tsx +++ b/src/plugins/visualize/public/application/app.tsx @@ -21,6 +21,7 @@ import './app.scss'; import React, { useEffect } from 'react'; import { Route, Switch, useLocation } from 'react-router-dom'; +import { AppMountParameters } from 'kibana/public'; import { syncQueryStateWithUrl } from '../../../data/public'; import { useKibana } from '../../../kibana_react/public'; import { VisualizeServices } from './types'; @@ -32,7 +33,11 @@ import { } from './components'; import { VisualizeConstants } from './visualize_constants'; -export const VisualizeApp = () => { +export interface VisualizeAppProps { + onAppLeave: AppMountParameters['onAppLeave']; +} + +export const VisualizeApp = ({ onAppLeave }: VisualizeAppProps) => { const { services: { data: { query }, @@ -54,10 +59,10 @@ export const VisualizeApp = () => { return ( - + - + { +export const VisualizeByValueEditor = ({ onAppLeave }: VisualizeAppProps) => { const [originatingApp, setOriginatingApp] = useState(); const { services } = useKibana(); const [eventEmitter] = useState(new EventEmitter()); - const [hasUnsavedChanges, setHasUnsavedChanges] = useState(true); + const [hasUnsavedChanges, setHasUnsavedChanges] = useState(false); const [embeddableId, setEmbeddableId] = useState(); const [valueInput, setValueInput] = useState(); @@ -100,6 +101,7 @@ export const VisualizeByValueEditor = () => { setHasUnsavedChanges={setHasUnsavedChanges} visEditorRef={visEditorRef} embeddableId={embeddableId} + onAppLeave={onAppLeave} /> ); }; diff --git a/src/plugins/visualize/public/application/components/visualize_editor.tsx b/src/plugins/visualize/public/application/components/visualize_editor.tsx index 6a0bd26a16faa..7c0fa065c3a71 100644 --- a/src/plugins/visualize/public/application/components/visualize_editor.tsx +++ b/src/plugins/visualize/public/application/components/visualize_editor.tsx @@ -32,8 +32,9 @@ import { } from '../utils'; import { VisualizeServices } from '../types'; import { VisualizeEditorCommon } from './visualize_editor_common'; +import { VisualizeAppProps } from '../app'; -export const VisualizeEditor = () => { +export const VisualizeEditor = ({ onAppLeave }: VisualizeAppProps) => { const { id: visualizationIdFromUrl } = useParams<{ id: string }>(); const [originatingApp, setOriginatingApp] = useState(); const { services } = useKibana(); @@ -91,6 +92,7 @@ export const VisualizeEditor = () => { visualizationIdFromUrl={visualizationIdFromUrl} setHasUnsavedChanges={setHasUnsavedChanges} visEditorRef={visEditorRef} + onAppLeave={onAppLeave} /> ); }; diff --git a/src/plugins/visualize/public/application/components/visualize_editor_common.tsx b/src/plugins/visualize/public/application/components/visualize_editor_common.tsx index b811936c63b14..947385b05d458 100644 --- a/src/plugins/visualize/public/application/components/visualize_editor_common.tsx +++ b/src/plugins/visualize/public/application/components/visualize_editor_common.tsx @@ -20,6 +20,7 @@ import './visualize_editor.scss'; import React, { RefObject } from 'react'; import { FormattedMessage } from '@kbn/i18n/react'; import { EuiScreenReaderOnly } from '@elastic/eui'; +import { AppMountParameters } from 'kibana/public'; import { VisualizeTopNav } from './visualize_top_nav'; import { ExperimentalVisInfo } from './experimental_vis_info'; import { @@ -38,6 +39,7 @@ interface VisualizeEditorCommonProps { setHasUnsavedChanges: (value: boolean) => void; hasUnappliedChanges: boolean; isEmbeddableRendered: boolean; + onAppLeave: AppMountParameters['onAppLeave']; visEditorRef: RefObject; originatingApp?: string; setOriginatingApp?: (originatingApp: string | undefined) => void; @@ -54,6 +56,7 @@ export const VisualizeEditorCommon = ({ setHasUnsavedChanges, hasUnappliedChanges, isEmbeddableRendered, + onAppLeave, originatingApp, setOriginatingApp, visualizationIdFromUrl, @@ -76,9 +79,11 @@ export const VisualizeEditorCommon = ({ stateContainer={appState} visualizationIdFromUrl={visualizationIdFromUrl} embeddableId={embeddableId} + onAppLeave={onAppLeave} /> )} - {visInstance?.vis?.type?.isExperimental && } + {visInstance?.vis?.type?.stage === 'experimental' && } + {visInstance?.vis?.type?.getInfoMessage?.(visInstance.vis)} {visInstance && (

    diff --git a/src/plugins/visualize/public/application/components/visualize_top_nav.tsx b/src/plugins/visualize/public/application/components/visualize_top_nav.tsx index dfd3c09f51ed5..b207529c456a1 100644 --- a/src/plugins/visualize/public/application/components/visualize_top_nav.tsx +++ b/src/plugins/visualize/public/application/components/visualize_top_nav.tsx @@ -19,7 +19,9 @@ import React, { memo, useCallback, useMemo, useState, useEffect } from 'react'; -import { OverlayRef } from 'kibana/public'; +import { AppMountParameters, OverlayRef } from 'kibana/public'; +import _ from 'lodash'; +import { i18n } from '@kbn/i18n'; import { useKibana } from '../../../../kibana_react/public'; import { VisualizeServices, @@ -43,6 +45,7 @@ interface VisualizeTopNavProps { stateContainer: VisualizeAppStateContainer; visualizationIdFromUrl?: string; embeddableId?: string; + onAppLeave: AppMountParameters['onAppLeave']; } const TopNav = ({ @@ -58,10 +61,11 @@ const TopNav = ({ stateContainer, visualizationIdFromUrl, embeddableId, + onAppLeave, }: VisualizeTopNavProps) => { const { services } = useKibana(); const { TopNavMenu } = services.navigation.ui; - const { setHeaderActionMenu } = services; + const { setHeaderActionMenu, visualizeCapabilities } = services; const { embeddableHandler, vis } = visInstance; const [inspectorSession, setInspectorSession] = useState(); const openInspector = useCallback(() => { @@ -93,6 +97,7 @@ const TopNav = ({ visualizationIdFromUrl, stateTransfer, embeddableId, + onAppLeave, }, services ); @@ -111,6 +116,7 @@ const TopNav = ({ services, embeddableId, stateTransfer, + onAppLeave, ]); const [indexPattern, setIndexPattern] = useState(vis.data.indexPattern); const showDatePicker = () => { @@ -131,6 +137,33 @@ const TopNav = ({ }; }, [inspectorSession]); + useEffect(() => { + onAppLeave((actions) => { + // Confirm when the user has made any changes to an existing visualizations + // or when the user has configured something without saving + if ( + ((originatingApp && originatingApp === 'dashboards') || originatingApp === 'canvas') && + (hasUnappliedChanges || hasUnsavedChanges) + ) { + return actions.confirm( + i18n.translate('visualize.confirmModal.confirmTextDescription', { + defaultMessage: 'Leave Visualize editor with unsaved changes?', + }), + i18n.translate('visualize.confirmModal.title', { + defaultMessage: 'Unsaved changes', + }) + ); + } + return actions.default(); + }); + }, [ + onAppLeave, + hasUnappliedChanges, + hasUnsavedChanges, + visualizeCapabilities.save, + originatingApp, + ]); + useEffect(() => { if (!vis.data.indexPattern) { services.data.indexPatterns.getDefault().then((index) => { diff --git a/src/plugins/visualize/public/application/index.tsx b/src/plugins/visualize/public/application/index.tsx index 4bec244e6efc9..1067fe613e466 100644 --- a/src/plugins/visualize/public/application/index.tsx +++ b/src/plugins/visualize/public/application/index.tsx @@ -27,7 +27,10 @@ import { VisualizeApp } from './app'; import { VisualizeServices } from './types'; import { addHelpMenuToAppChrome, addBadgeToAppChrome } from './utils'; -export const renderApp = ({ element }: AppMountParameters, services: VisualizeServices) => { +export const renderApp = ( + { element, onAppLeave }: AppMountParameters, + services: VisualizeServices +) => { // add help link to visualize docs into app chrome menu addHelpMenuToAppChrome(services.chrome, services.docLinks); // add readonly badge if saving restricted @@ -39,7 +42,7 @@ export const renderApp = ({ element }: AppMountParameters, services: VisualizeSe - + diff --git a/src/plugins/visualize/public/application/utils/get_top_nav_config.tsx b/src/plugins/visualize/public/application/utils/get_top_nav_config.tsx index 0423e48bfb41e..eadf404daf918 100644 --- a/src/plugins/visualize/public/application/utils/get_top_nav_config.tsx +++ b/src/plugins/visualize/public/application/utils/get_top_nav_config.tsx @@ -21,8 +21,8 @@ import React from 'react'; import { i18n } from '@kbn/i18n'; import { TopNavMenuData } from 'src/plugins/navigation/public'; -import uuid from 'uuid'; -import { VISUALIZE_EMBEDDABLE_TYPE } from '../../../../visualizations/public'; +import { AppMountParameters } from 'kibana/public'; +import { VISUALIZE_EMBEDDABLE_TYPE, VisualizeInput } from '../../../../visualizations/public'; import { showSaveModal, SavedObjectSaveModalOrigin, @@ -52,6 +52,7 @@ interface TopNavConfigParams { visualizationIdFromUrl?: string; stateTransfer: EmbeddableStateTransfer; embeddableId?: string; + onAppLeave: AppMountParameters['onAppLeave']; } export const getTopNavConfig = ( @@ -67,6 +68,7 @@ export const getTopNavConfig = ( visualizationIdFromUrl, stateTransfer, embeddableId, + onAppLeave, }: TopNavConfigParams, { application, @@ -122,7 +124,7 @@ export const getTopNavConfig = ( if (newlyCreated && stateTransfer) { stateTransfer.navigateToWithEmbeddablePackage(originatingApp, { - state: { id, type: VISUALIZE_EMBEDDABLE_TYPE }, + state: { type: VISUALIZE_EMBEDDABLE_TYPE, input: { savedObjectId: id } }, }); } else { application.navigateToApp(originatingApp); @@ -167,59 +169,92 @@ export const getTopNavConfig = ( } const state = { input: { - ...vis.serialize(), - id: embeddableId ? embeddableId : uuid.v4(), - }, + savedVis: vis.serialize(), + } as VisualizeInput, + embeddableId, type: VISUALIZE_EMBEDDABLE_TYPE, - embeddableId: '', }; - if (embeddableId) { - state.embeddableId = embeddableId; - } stateTransfer.navigateToWithEmbeddablePackage(originatingApp, { state }); }; + const navigateToOriginatingApp = () => { + if (originatingApp) { + application.navigateToApp(originatingApp); + } + }; + const topNavMenu: TopNavMenuData[] = [ - ...(originatingApp && ((savedVis && savedVis.id) || embeddableId) + { + id: 'inspector', + label: i18n.translate('visualize.topNavMenu.openInspectorButtonLabel', { + defaultMessage: 'inspect', + }), + description: i18n.translate('visualize.topNavMenu.openInspectorButtonAriaLabel', { + defaultMessage: 'Open Inspector for visualization', + }), + testId: 'openInspectorButton', + disableButton() { + return !embeddableHandler.hasInspector || !embeddableHandler.hasInspector(); + }, + run: openInspector, + tooltip() { + if (!embeddableHandler.hasInspector || !embeddableHandler.hasInspector()) { + return i18n.translate('visualize.topNavMenu.openInspectorDisabledButtonTooltip', { + defaultMessage: `This visualization doesn't support any inspectors.`, + }); + } + }, + }, + { + id: 'share', + label: i18n.translate('visualize.topNavMenu.shareVisualizationButtonLabel', { + defaultMessage: 'share', + }), + description: i18n.translate('visualize.topNavMenu.shareVisualizationButtonAriaLabel', { + defaultMessage: 'Share Visualization', + }), + testId: 'shareTopNavButton', + run: (anchorElement) => { + if (share && !embeddableId) { + // TODO: support sharing in by-value mode + share.toggleShareContextMenu({ + anchorElement, + allowEmbed: true, + allowShortUrl: visualizeCapabilities.createShortUrl, + shareableUrl: unhashUrl(window.location.href), + objectId: savedVis?.id, + objectType: 'visualization', + sharingData: { + title: savedVis?.title, + }, + isDirty: hasUnappliedChanges || hasUnsavedChanges, + }); + } + }, + // disable the Share button if no action specified + disableButton: !share || !!embeddableId, + }, + ...(originatingApp === 'dashboards' || originatingApp === 'canvas' ? [ { - id: 'saveAndReturn', - label: i18n.translate('visualize.topNavMenu.saveAndReturnVisualizationButtonLabel', { - defaultMessage: 'Save and return', + id: 'cancel', + label: i18n.translate('visualize.topNavMenu.cancelButtonLabel', { + defaultMessage: 'Cancel', }), - emphasize: true, - iconType: 'check', - description: i18n.translate( - 'visualize.topNavMenu.saveAndReturnVisualizationButtonAriaLabel', - { - defaultMessage: 'Finish editing visualization and return to the last app', - } - ), - testId: 'visualizesaveAndReturnButton', - disableButton: hasUnappliedChanges, + emphasize: false, + description: i18n.translate('visualize.topNavMenu.cancelButtonAriaLabel', { + defaultMessage: 'Return to the last app without saving changes', + }), + testId: 'visualizeCancelAndReturnButton', tooltip() { - if (hasUnappliedChanges) { - return i18n.translate( - 'visualize.topNavMenu.saveAndReturnVisualizationDisabledButtonTooltip', - { - defaultMessage: 'Apply or Discard your changes before finishing', - } - ); + if (hasUnappliedChanges || hasUnsavedChanges) { + return i18n.translate('visualize.topNavMenu.cancelAndReturnButtonTooltip', { + defaultMessage: 'Discard your changes before finishing', + }); } }, run: async () => { - const saveOptions = { - confirmOverwrite: false, - returnToOrigin: true, - }; - if ( - originatingApp === 'dashboards' && - dashboard.dashboardFeatureFlagConfig.allowByValueEmbeddables && - !savedVis - ) { - return createVisReference(); - } - return doSave(saveOptions); + return navigateToOriginatingApp(); }, }, ] @@ -228,6 +263,7 @@ export const getTopNavConfig = ( ? [ { id: 'save', + iconType: savedVis?.id && originatingApp ? undefined : 'save', label: savedVis?.id && originatingApp ? i18n.translate('visualize.topNavMenu.saveVisualizationAsButtonLabel', { @@ -267,6 +303,7 @@ export const getTopNavConfig = ( } const currentTitle = savedVis.title; savedVis.title = newTitle; + embeddableHandler.updateInput({ title: newTitle }); savedVis.copyOnSave = newCopyOnSave; savedVis.description = newDescription; const saveOptions = { @@ -282,6 +319,7 @@ export const getTopNavConfig = ( } return response; }; + const saveModal = ( ); const isSaveAsButton = anchorElement.classList.contains('saveAsButton'); + onAppLeave((actions) => { + return actions.default(); + }); if ( originatingApp === 'dashboards' && dashboard.dashboardFeatureFlagConfig.allowByValueEmbeddables && @@ -306,56 +347,53 @@ export const getTopNavConfig = ( }, ] : []), - { - id: 'share', - label: i18n.translate('visualize.topNavMenu.shareVisualizationButtonLabel', { - defaultMessage: 'share', - }), - description: i18n.translate('visualize.topNavMenu.shareVisualizationButtonAriaLabel', { - defaultMessage: 'Share Visualization', - }), - testId: 'shareTopNavButton', - run: (anchorElement) => { - if (share && !embeddableId) { - // TODO: support sharing in by-value mode - share.toggleShareContextMenu({ - anchorElement, - allowEmbed: true, - allowShortUrl: visualizeCapabilities.createShortUrl, - shareableUrl: unhashUrl(window.location.href), - objectId: savedVis?.id, - objectType: 'visualization', - sharingData: { - title: savedVis?.title, + ...(originatingApp && ((savedVis && savedVis.id) || embeddableId) + ? [ + { + id: 'saveAndReturn', + label: i18n.translate('visualize.topNavMenu.saveAndReturnVisualizationButtonLabel', { + defaultMessage: 'Save and return', + }), + emphasize: true, + iconType: 'checkInCircleFilled', + description: i18n.translate( + 'visualize.topNavMenu.saveAndReturnVisualizationButtonAriaLabel', + { + defaultMessage: 'Finish editing visualization and return to the last app', + } + ), + testId: 'visualizesaveAndReturnButton', + disableButton: hasUnappliedChanges, + tooltip() { + if (hasUnappliedChanges) { + return i18n.translate( + 'visualize.topNavMenu.saveAndReturnVisualizationDisabledButtonTooltip', + { + defaultMessage: 'Apply or Discard your changes before finishing', + } + ); + } }, - isDirty: hasUnappliedChanges || hasUnsavedChanges, - }); - } - }, - // disable the Share button if no action specified - disableButton: !share || !!embeddableId, - }, - { - id: 'inspector', - label: i18n.translate('visualize.topNavMenu.openInspectorButtonLabel', { - defaultMessage: 'inspect', - }), - description: i18n.translate('visualize.topNavMenu.openInspectorButtonAriaLabel', { - defaultMessage: 'Open Inspector for visualization', - }), - testId: 'openInspectorButton', - disableButton() { - return !embeddableHandler.hasInspector || !embeddableHandler.hasInspector(); - }, - run: openInspector, - tooltip() { - if (!embeddableHandler.hasInspector || !embeddableHandler.hasInspector()) { - return i18n.translate('visualize.topNavMenu.openInspectorDisabledButtonTooltip', { - defaultMessage: `This visualization doesn't support any inspectors.`, - }); - } - }, - }, + run: async () => { + const saveOptions = { + confirmOverwrite: false, + returnToOrigin: true, + }; + onAppLeave((actions) => { + return actions.default(); + }); + if ( + originatingApp === 'dashboards' && + dashboard.dashboardFeatureFlagConfig.allowByValueEmbeddables && + !savedVis + ) { + return createVisReference(); + } + return doSave(saveOptions); + }, + }, + ] + : []), ]; return topNavMenu; diff --git a/src/plugins/visualize/public/application/utils/get_visualization_instance.test.ts b/src/plugins/visualize/public/application/utils/get_visualization_instance.test.ts index 31f0fc5f94479..bb4fabb189a27 100644 --- a/src/plugins/visualize/public/application/utils/get_visualization_instance.test.ts +++ b/src/plugins/visualize/public/application/utils/get_visualization_instance.test.ts @@ -50,6 +50,8 @@ describe('getVisualizationInstance', () => { }; savedVisMock = {}; // @ts-expect-error + mockServices.data.search.showError.mockImplementation(() => {}); + // @ts-expect-error mockServices.savedVisualizations.get.mockImplementation(() => savedVisMock); // @ts-expect-error mockServices.visualizations.convertToSerializedVis.mockImplementation(() => serializedVisMock); @@ -119,6 +121,6 @@ describe('getVisualizationInstance', () => { error: 'error', }); - expect(mockServices.toastNotifications.addError).toHaveBeenCalled(); + expect(mockServices.data.search.showError).toHaveBeenCalled(); }); }); diff --git a/src/plugins/visualize/public/application/utils/get_visualization_instance.ts b/src/plugins/visualize/public/application/utils/get_visualization_instance.ts index 3ffca578f8052..c5cfa5a4c639b 100644 --- a/src/plugins/visualize/public/application/utils/get_visualization_instance.ts +++ b/src/plugins/visualize/public/application/utils/get_visualization_instance.ts @@ -17,7 +17,6 @@ * under the License. */ -import { i18n } from '@kbn/i18n'; import { SerializedVis, Vis, @@ -28,6 +27,7 @@ import { import { SearchSourceFields } from 'src/plugins/data/public'; import { SavedObject } from 'src/plugins/saved_objects/public'; import { cloneDeep } from 'lodash'; +import { ExpressionValueError } from 'src/plugins/expressions/public'; import { createSavedSearchesLoader } from '../../../../discover/public'; import { VisualizeServices } from '../types'; @@ -35,14 +35,7 @@ const createVisualizeEmbeddableAndLinkSavedSearch = async ( vis: Vis, visualizeServices: VisualizeServices ) => { - const { - chrome, - data, - overlays, - createVisEmbeddableFromObject, - savedObjects, - toastNotifications, - } = visualizeServices; + const { chrome, data, overlays, createVisEmbeddableFromObject, savedObjects } = visualizeServices; const embeddableHandler = (await createVisEmbeddableFromObject(vis, { timeRange: data.query.timefilter.timefilter.getTime(), filters: data.query.filterManager.getFilters(), @@ -51,11 +44,9 @@ const createVisualizeEmbeddableAndLinkSavedSearch = async ( embeddableHandler.getOutput$().subscribe((output) => { if (output.error) { - toastNotifications.addError(output.error, { - title: i18n.translate('visualize.error.title', { - defaultMessage: 'Visualization error', - }), - }); + data.search.showError( + ((output.error as unknown) as ExpressionValueError['error']).original || output.error + ); } }); diff --git a/src/setup_node_env/babel_register/index.js b/src/setup_node_env/babel_register/index.js deleted file mode 100644 index 1574be8937a29..0000000000000 --- a/src/setup_node_env/babel_register/index.js +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -// register and polyfill need to happen in this -// order and in separate files. Checkout each file -// for a much more detailed explanation -require('./register'); -require('./polyfill'); diff --git a/src/setup_node_env/babel_register/polyfill.js b/src/setup_node_env/babel_register/polyfill.js deleted file mode 100644 index b6928f6cb8caf..0000000000000 --- a/src/setup_node_env/babel_register/polyfill.js +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -// `@babel/preset-env` looks for and rewrites the following import -// statement into a list of import statements based on the polyfills -// necessary for our target environment (the current version of node) -// but since it does that during compilation, `import 'core-js/stable'` -// must be in a file that is loaded with `require()` AFTER `@babel/register` -// is configured. -// -// This is why we have this single statement in it's own file and require -// it from ./index.js -require('core-js/stable'); diff --git a/src/setup_node_env/babel_register/register.js b/src/setup_node_env/babel_register/register.js deleted file mode 100644 index 6d573d8922244..0000000000000 --- a/src/setup_node_env/babel_register/register.js +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -var resolve = require('path').resolve; - -// this must happen before `require('@babel/register')` and can't be changed -// once the module has been loaded -if (!process.env.BABEL_CACHE_PATH) { - process.env.BABEL_CACHE_PATH = resolve( - __dirname, - '../../../data/optimize/.babel_register_cache.json' - ); -} - -// paths that @babel/register should ignore -var ignore = [ - /[\/\\]bower_components[\/\\]/, - /[\/\\]kbn-pm[\/\\]dist[\/\\]/, - - // TODO: remove this and just transpile plugins at build time, but - // has tricky edge cases that will probably require better eslint - // restrictions to make sure that code destined for the server/browser - // follows respects the limitations of each environment. - // - // https://github.com/elastic/kibana/issues/14800#issuecomment-366130268 - - // ignore paths matching `/node_modules/{a}/{b}`, unless `a` - // is `x-pack` and `b` is not `node_modules` - /[\/\\]node_modules[\/\\](?!x-pack[\/\\](?!node_modules)([^\/\\]+))([^\/\\]+[\/\\][^\/\\]+)/, - - // ignore paths matching `/canvas/canvas_plugin/` - /[\/\\]canvas[\/\\]canvas_plugin[\/\\]/, -]; - -if (global.__BUILT_WITH_BABEL__) { - // when building the Kibana source we replace the statement - // `global.__BUILT_WITH_BABEL__` with the value `true` so that - // when @babel/register is required for the first time by users - // it will exclude kibana's `src` directory. - // - // We still need @babel/register for plugins though, we've been - // building their server code at require-time since version 4.2 - // TODO: the plugin install process could transpile plugin server code... - ignore.push(resolve(__dirname, '../../../src')); -} else { - ignore.push( - // ignore any path in the packages, unless it is in the package's - // root `src` directory, in any test or __tests__ directory, or it - // ends with .test.js, .test.ts, or .test.tsx - /[\/\\]packages[\/\\](eslint-|kbn-)[^\/\\]+[\/\\](?!src[\/\\].*|(.+[\/\\])?(test|__tests__)[\/\\].+|.+\.test\.(js|ts|tsx)$)(.+$)/ - ); -} - -// modifies all future calls to require() to automatically -// compile the required source with babel -require('@babel/register')({ - ignore, - babelrc: false, - presets: [require.resolve('@kbn/babel-preset/node_preset')], - extensions: ['.js', '.ts', '.tsx'], -}); diff --git a/src/setup_node_env/dist.js b/src/setup_node_env/dist.js new file mode 100644 index 0000000000000..dd3af8c48a30a --- /dev/null +++ b/src/setup_node_env/dist.js @@ -0,0 +1,21 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +require('./no_transpilation'); +require('./polyfill'); diff --git a/src/setup_node_env/index.js b/src/setup_node_env/index.js index d84249df7fd8f..55539c56a364e 100644 --- a/src/setup_node_env/index.js +++ b/src/setup_node_env/index.js @@ -17,5 +17,5 @@ * under the License. */ -require('./prebuilt_dev_only_entry'); -require('./babel_register'); +require('./no_transpilation'); +require('@kbn/optimizer').registerNodeAutoTranspilation(); diff --git a/src/setup_node_env/prebuilt_dev_only_entry.js b/src/setup_node_env/no_transpilation.js similarity index 100% rename from src/setup_node_env/prebuilt_dev_only_entry.js rename to src/setup_node_env/no_transpilation.js diff --git a/src/setup_node_env/polyfill.js b/src/setup_node_env/polyfill.js new file mode 100644 index 0000000000000..ad87354c83429 --- /dev/null +++ b/src/setup_node_env/polyfill.js @@ -0,0 +1,20 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +require('core-js/stable'); diff --git a/src/test_utils/public/enzyme_helpers.tsx b/src/test_utils/public/enzyme_helpers.tsx index a7bed2ad84956..ce4e7c7298734 100644 --- a/src/test_utils/public/enzyme_helpers.tsx +++ b/src/test_utils/public/enzyme_helpers.tsx @@ -18,13 +18,13 @@ */ /** - * Components using the react-intl module require access to the intl context. + * Components using the @kbn/i18n module require access to the intl context. * This is not available when mounting single components in Enzyme. * These helper functions aim to address that and wrap a valid, * intl context around them. */ -import { I18nProvider, InjectedIntl, intlShape } from '@kbn/i18n/react'; +import { I18nProvider, InjectedIntl, intlShape, __IntlProvider } from '@kbn/i18n/react'; import { mount, ReactWrapper, render, shallow } from 'enzyme'; import React, { ReactElement, ValidationMap } from 'react'; @@ -33,7 +33,7 @@ const { intl } = (mount(
    -).find('IntlProvider') as ReactWrapper<{}, {}, import('react-intl').IntlProvider>) +).find('IntlProvider') as ReactWrapper<{}, {}, __IntlProvider>) .instance() .getChildContext(); @@ -52,7 +52,7 @@ function getOptions(context = {}, childContextTypes: ValidationMap = {}, pr } /** - * When using React-Intl `injectIntl` on components, props.intl is required. + * When using @kbn/i18n `injectI18n` on components, props.intl is required. */ function nodeWithIntlProp(node: ReactElement): ReactElement { return React.cloneElement(node, { intl }); diff --git a/src/test_utils/public/stub_index_pattern.js b/src/test_utils/public/stub_index_pattern.js deleted file mode 100644 index 6130a7f9f9e87..0000000000000 --- a/src/test_utils/public/stub_index_pattern.js +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import sinon from 'sinon'; -// TODO: We should not be importing from the data plugin directly here; this is only necessary -// because it is one of the few places that we need to access the IndexPattern class itself, rather -// than just the type. Doing this as a temporary measure; it will be left behind when migrating to NP. - -import { getFieldFormatsRegistry } from '../../plugins/data/public/test_utils'; -import { IndexPattern, indexPatterns, KBN_FIELD_TYPES, fieldList } from '../../plugins/data/public'; - -import { setFieldFormats } from '../../plugins/data/public/services'; - -setFieldFormats({ - getDefaultInstance: () => ({ - getConverterFor: () => (value) => value, - convert: (value) => JSON.stringify(value), - }), -}); - -export default function StubIndexPattern(pattern, getConfig, timeField, fields, core) { - const registeredFieldFormats = getFieldFormatsRegistry(core); - - this.id = pattern; - this.title = pattern; - this.popularizeField = sinon.stub(); - this.timeFieldName = timeField; - this.isTimeBased = () => Boolean(this.timeFieldName); - this.getConfig = getConfig; - this.getNonScriptedFields = sinon.spy(IndexPattern.prototype.getNonScriptedFields); - this.getScriptedFields = sinon.spy(IndexPattern.prototype.getScriptedFields); - this.getFieldByName = sinon.spy(IndexPattern.prototype.getFieldByName); - this.getSourceFiltering = sinon.stub(); - this.metaFields = ['_id', '_type', '_source']; - this.fieldFormatMap = {}; - - this.getComputedFields = IndexPattern.prototype.getComputedFields.bind(this); - this.flattenHit = indexPatterns.flattenHitWrapper(this, this.metaFields); - this.formatHit = indexPatterns.formatHitProvider( - this, - registeredFieldFormats.getDefaultInstance(KBN_FIELD_TYPES.STRING) - ); - this.fieldsFetcher = { apiClient: { baseUrl: '' } }; - this.formatField = this.formatHit.formatField; - this.getFormatterForField = () => ({ - convert: () => '', - }); - - this._reindexFields = function () { - this.fields = fieldList(this.fields || fields, false); - }; - - this.stubSetFieldFormat = function (fieldName, id, params) { - const FieldFormat = registeredFieldFormats.getType(id); - this.fieldFormatMap[fieldName] = new FieldFormat(params); - this._reindexFields(); - }; - - this._reindexFields(); -} diff --git a/tasks/config/run.js b/tasks/config/run.js index 148be6ea8afaa..eddcb0bdd59d0 100644 --- a/tasks/config/run.js +++ b/tasks/config/run.js @@ -240,10 +240,6 @@ module.exports = function () { args: ['scripts/check_licenses', '--dev'], }), - verifyDependencyVersions: gruntTaskWithGithubChecks( - 'Verify dependency versions', - 'verifyDependencyVersions' - ), test_jest: gruntTaskWithGithubChecks('Jest tests', 'test:jest'), test_jest_integration: gruntTaskWithGithubChecks( 'Jest integration tests', diff --git a/tasks/function_test_groups.js b/tasks/function_test_groups.js index d60f3ae53eecc..ac41b3f36be0f 100644 --- a/tasks/function_test_groups.js +++ b/tasks/function_test_groups.js @@ -43,6 +43,8 @@ const getDefaultArgs = (tag) => { '--debug', '--config', 'test/new_visualize_flow/config.js', + '--config', + 'test/security_functional/config.ts', ]; }; diff --git a/tasks/jenkins.js b/tasks/jenkins.js index 90efadf41c435..4e3358ce81bbd 100644 --- a/tasks/jenkins.js +++ b/tasks/jenkins.js @@ -31,7 +31,6 @@ module.exports = function (grunt) { 'run:checkFileCasing', 'run:checkLockfileSymlinks', 'run:licenses', - 'run:verifyDependencyVersions', 'run:verifyNotice', 'run:mocha', 'run:test_jest', diff --git a/tasks/licenses_csv_report.js b/tasks/licenses_csv_report.js index 746195038379e..f504cbcaa5fc8 100644 --- a/tasks/licenses_csv_report.js +++ b/tasks/licenses_csv_report.js @@ -20,6 +20,7 @@ import { writeFileSync } from 'fs'; import { resolve } from 'path'; import { getInstalledPackages } from '../src/dev/npm'; +import { engines } from '../package'; import { LICENSE_OVERRIDES } from '../src/dev/license_checker'; import { isNull, isUndefined } from 'lodash'; @@ -51,7 +52,7 @@ function formatCsvValues(fields, values) { export default function licensesCSVReport(grunt) { grunt.registerTask('licenses:csv_report', 'Report of 3rd party dependencies', async function () { - const fields = ['name', 'version', 'url', 'license']; + const fields = ['name', 'version', 'url', 'license', 'sourceURL']; const done = this.async(); try { @@ -65,6 +66,25 @@ export default function licensesCSVReport(grunt) { dev, }); + packages.unshift( + { + name: 'Node.js', + version: engines.node, + repository: 'https://nodejs.org', + licenses: ['MIT'], + }, + { + name: 'Red Hat Universal Base Image minimal', + version: '8', + repository: + 'https://catalog.redhat.com/software/containers/ubi8/ubi-minimal/5c359a62bed8bd75a2c3fba8', + licenses: [ + 'Custom;https://www.redhat.com/licenses/EULA_Red_Hat_Universal_Base_Image_English_20190422.pdf', + ], + sourceURL: 'https://oss-dependencies.elastic.co/redhat/ubi/ubi-minimal-8-source.tar.gz', + } + ); + const csv = packages .map((pkg) => { const data = { @@ -72,6 +92,7 @@ export default function licensesCSVReport(grunt) { version: pkg.version, url: pkg.repository || `https://www.npmjs.com/package/${pkg.name}`, license: pkg.licenses.join(','), + sourceURL: pkg.sourceURL, }; return formatCsvValues(fields, data); diff --git a/tasks/verify_dependency_versions.js b/tasks/verify_dependency_versions.js deleted file mode 100644 index 14ecbb9ba8603..0000000000000 --- a/tasks/verify_dependency_versions.js +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { size } from 'lodash'; -import kibana from '../package.json'; -import xpack from '../x-pack/package.json'; - -function getMismatches(depType) { - return Object.keys(kibana[depType]) - .map((key) => { - const xpackValue = xpack[depType][key]; - const kibanaValue = kibana[depType][key]; - if (xpackValue && kibanaValue && xpackValue !== kibanaValue && !key.includes('@kbn/')) { - return { - key, - xpack: xpackValue, - kibana: kibanaValue, - }; - } - }) - .filter((key) => !!key); -} - -export default function verifyDependencyVersions(grunt) { - grunt.registerTask('verifyDependencyVersions', 'Checks dependency versions', () => { - const devDependenciesMismatches = getMismatches('devDependencies'); - if (size(devDependenciesMismatches) > 0) { - grunt.log.error( - 'The following devDependencies do not match:', - JSON.stringify(devDependenciesMismatches, null, 4) - ); - return false; - } else { - grunt.log.writeln('devDependencies match!'); - } - }); -} diff --git a/test/accessibility/apps/dashboard_panel.ts b/test/accessibility/apps/dashboard_panel.ts index 03fa76387da1f..1a817ce6b7a1c 100644 --- a/test/accessibility/apps/dashboard_panel.ts +++ b/test/accessibility/apps/dashboard_panel.ts @@ -18,7 +18,6 @@ */ import { FtrProviderContext } from '../ftr_provider_context'; - export default function ({ getService, getPageObjects }: FtrProviderContext) { const PageObjects = getPageObjects(['common', 'dashboard', 'header', 'home', 'settings']); const a11y = getService('a11y'); @@ -31,6 +30,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await PageObjects.common.navigateToUrl('home', '/tutorial_directory/sampleData', { useActualUrl: true, }); + await PageObjects.home.addSampleDataSet('flights'); await PageObjects.common.navigateToApp('dashboard'); await testSubjects.click('dashboardListingTitleLink-[Flights]-Global-Flight-Dashboard'); diff --git a/test/accessibility/apps/discover.ts b/test/accessibility/apps/discover.ts index 44639af9da9f8..64e78b57c5a1b 100644 --- a/test/accessibility/apps/discover.ts +++ b/test/accessibility/apps/discover.ts @@ -21,21 +21,14 @@ import { FtrProviderContext } from '../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { const PageObjects = getPageObjects(['common', 'discover', 'header', 'share', 'timePicker']); - const retry = getService('retry'); const a11y = getService('a11y'); const esArchiver = getService('esArchiver'); const kibanaServer = getService('kibanaServer'); const inspector = getService('inspector'); - const docTable = getService('docTable'); - const filterBar = getService('filterBar'); - const TEST_COLUMN_NAMES = ['@message']; - const TEST_FILTER_COLUMN_NAMES = [ - ['extension', 'jpg'], - ['geo.src', 'IN'], - ]; - - // Failing: See https://github.com/elastic/kibana/issues/59975 - describe.skip('Discover', () => { + const testSubjects = getService('testSubjects'); + const TEST_COLUMN_NAMES = ['extension', 'geo.src']; + + describe('Discover a11y tests', () => { before(async () => { await esArchiver.load('discover'); await esArchiver.loadIfNeeded('logstash_functional'); @@ -46,105 +39,89 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await PageObjects.timePicker.setDefaultAbsoluteRange(); }); - it('main view', async () => { + after(async () => { + await esArchiver.unload('logstash_functional'); + }); + + it('Discover main page', async () => { await a11y.testAppSnapshot(); }); - it('Click save button', async () => { + it('a11y test on save button', async () => { await PageObjects.discover.clickSaveSearchButton(); await a11y.testAppSnapshot(); }); - it('Save search panel', async () => { + it('a11y test on save search panel', async () => { await PageObjects.discover.inputSavedSearchTitle('a11ySearch'); await a11y.testAppSnapshot(); }); - it('Confirm saved search', async () => { + it('a11y test on clicking on confirm save', async () => { await PageObjects.discover.clickConfirmSavedSearch(); await a11y.testAppSnapshot(); }); - it('Click on new to clear the search', async () => { + it('a11y test on click new to reload discover', async () => { await PageObjects.discover.clickNewSearchButton(); await a11y.testAppSnapshot(); }); - it('Open load saved search panel', async () => { + it('a11y test on load saved search panel', async () => { await PageObjects.discover.openLoadSavedSearchPanel(); await a11y.testAppSnapshot(); await PageObjects.discover.closeLoadSavedSearchPanel(); }); - it('Open inspector panel', async () => { + it('a11y test on inspector panel', async () => { await inspector.open(); await a11y.testAppSnapshot(); await inspector.close(); }); - it('Open add filter', async () => { - await PageObjects.discover.openAddFilterPanel(); - await a11y.testAppSnapshot(); - }); - - it('Select values for a filter', async () => { - await filterBar.addFilter('extension.raw', 'is one of', 'jpg'); - await a11y.testAppSnapshot(); - }); - - it('Load a new search from the panel', async () => { - await PageObjects.discover.clickSaveSearchButton(); - await PageObjects.discover.inputSavedSearchTitle('filterSearch'); - await PageObjects.discover.clickConfirmSavedSearch(); - await PageObjects.discover.openLoadSavedSearchPanel(); - await PageObjects.discover.loadSavedSearch('filterSearch'); - await a11y.testAppSnapshot(); - }); - - it('click share button', async () => { + it('a11y test on share panel', async () => { await PageObjects.share.clickShareTopNavButton(); await a11y.testAppSnapshot(); }); - it('Open sidebar filter', async () => { + it('a11y test on open sidenav filter', async () => { await PageObjects.discover.openSidebarFieldFilter(); await a11y.testAppSnapshot(); - }); - - it('Close sidebar filter', async () => { await PageObjects.discover.closeSidebarFieldFilter(); - await a11y.testAppSnapshot(); }); - it('Add a field from sidebar', async () => { + it('a11y test on tables with columns view', async () => { for (const columnName of TEST_COLUMN_NAMES) { - await PageObjects.discover.clickFieldListItemAdd(columnName); + await PageObjects.discover.clickFieldListItemToggle(columnName); } await a11y.testAppSnapshot(); }); - it('Add more fields from sidebar', async () => { - for (const [columnName, value] of TEST_FILTER_COLUMN_NAMES) { - await PageObjects.discover.clickFieldListItem(columnName); - await PageObjects.discover.clickFieldListPlusFilter(columnName, value); - } + it('a11y test on save queries popover', async () => { + await PageObjects.discover.clickSavedQueriesPopOver(); await a11y.testAppSnapshot(); }); - // Context view test - it('should open context view on a doc', async () => { - await retry.try(async () => { - await docTable.clickRowToggle(); - // click the open action - const rowActions = await docTable.getRowActions(); - if (!rowActions.length) { - throw new Error('row actions empty, trying again'); - } - await rowActions[0].click(); - }); + it('a11y test on save queries panel', async () => { + await PageObjects.discover.clickCurrentSavedQuery(); + await a11y.testAppSnapshot(); + }); + + it('a11y test on toggle include filters option on saved queries panel', async () => { + await PageObjects.discover.setSaveQueryFormTitle('test'); + await PageObjects.discover.toggleIncludeFilters(); await a11y.testAppSnapshot(); + await PageObjects.discover.saveCurrentSavedQuery(); }); - // Adding rest of the tests after https://github.com/elastic/kibana/issues/53888 is resolved + // issue - https://github.com/elastic/kibana/issues/78488 + it.skip('a11y test on saved queries list panel', async () => { + await PageObjects.discover.clickSavedQueriesPopOver(); + await testSubjects.moveMouseTo( + 'saved-query-list-item load-saved-query-test-button saved-query-list-item-selected saved-query-list-item-selected' + ); + await testSubjects.find('delete-saved-query-test-button'); + await a11y.testAppSnapshot(); + }); }); } diff --git a/test/accessibility/apps/filter_panel.ts b/test/accessibility/apps/filter_panel.ts new file mode 100644 index 0000000000000..02f02ca015cac --- /dev/null +++ b/test/accessibility/apps/filter_panel.ts @@ -0,0 +1,95 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { FtrProviderContext } from '../ftr_provider_context'; + +export default function ({ getService, getPageObjects }: FtrProviderContext) { + const PageObjects = getPageObjects(['common', 'discover', 'home']); + const a11y = getService('a11y'); + const filterBar = getService('filterBar'); + const testSubjects = getService('testSubjects'); + const browser = getService('browser'); + + describe('Filter panel', () => { + before(async () => { + await PageObjects.common.navigateToUrl('home', '/tutorial_directory/sampleData', { + useActualUrl: true, + }); + await PageObjects.home.addSampleDataSet('flights'); + await PageObjects.common.navigateToApp('discover'); + await PageObjects.discover.selectIndexPattern('kibana_sample_data_flights'); + }); + + it('a11y test on add filter panel', async () => { + await PageObjects.discover.openAddFilterPanel(); + await a11y.testAppSnapshot(); + await filterBar.addFilter('OriginCityName', 'is', 'Rome'); + }); + + it('a11y test on filter panel with custom label', async () => { + await filterBar.clickEditFilter('OriginCityName', 'Rome'); + await testSubjects.click('createCustomLabel'); + await a11y.testAppSnapshot(); + }); + + it('a11y test on Edit filter as Query DSL panel', async () => { + await testSubjects.click('editQueryDSL'); + await a11y.testAppSnapshot(); + await browser.pressKeys(browser.keys.ESCAPE); + }); + + // the following tests filter panel options which changes UI + it('a11y test on filter panel options panel', async () => { + await filterBar.addFilter('DestCountry', 'is', 'AU'); + await testSubjects.click('showFilterActions'); + await a11y.testAppSnapshot(); + }); + + it('a11y test on disable all filter options view', async () => { + await testSubjects.click('disableAllFilters'); + await a11y.testAppSnapshot(); + }); + + it('a11y test on pin filters view', async () => { + await testSubjects.click('showFilterActions'); + await testSubjects.click('enableAllFilters'); + await testSubjects.click('showFilterActions'); + await testSubjects.click('pinAllFilters'); + await a11y.testAppSnapshot(); + }); + + it('a11y test on unpin all filters view', async () => { + await testSubjects.click('showFilterActions'); + await testSubjects.click('unpinAllFilters'); + await a11y.testAppSnapshot(); + }); + + it('a11y test on invert inclusion of all filters view', async () => { + await testSubjects.click('showFilterActions'); + await testSubjects.click('invertInclusionAllFilters'); + await a11y.testAppSnapshot(); + }); + + it('a11y test on remove all filtes view', async () => { + await testSubjects.click('showFilterActions'); + await testSubjects.click('removeAllFilters'); + await a11y.testAppSnapshot(); + }); + }); +} diff --git a/test/accessibility/apps/management.ts b/test/accessibility/apps/management.ts index 08177f54ee881..994aa03950437 100644 --- a/test/accessibility/apps/management.ts +++ b/test/accessibility/apps/management.ts @@ -35,6 +35,10 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await PageObjects.settings.navigateTo(); }); + after(async () => { + await esArchiver.unload('logstash_functional'); + }); + it('main view', async () => { await a11y.testAppSnapshot(); }); diff --git a/test/accessibility/config.ts b/test/accessibility/config.ts index dd366c17a4ba7..9068a7e06defc 100644 --- a/test/accessibility/config.ts +++ b/test/accessibility/config.ts @@ -35,6 +35,7 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) { require.resolve('./apps/management'), require.resolve('./apps/console'), require.resolve('./apps/home'), + require.resolve('./apps/filter_panel'), ], pageObjects, services, diff --git a/test/accessibility/services/a11y/a11y.ts b/test/accessibility/services/a11y/a11y.ts index 35cef2b81d64e..871e50385eb8d 100644 --- a/test/accessibility/services/a11y/a11y.ts +++ b/test/accessibility/services/a11y/a11y.ts @@ -36,6 +36,8 @@ interface TestOptions { export const normalizeResult = (report: any) => { if (report.error) { + const error = new Error(report.error.message); + error.stack = report.error.stack; throw report.error; } @@ -71,7 +73,6 @@ export function A11yProvider({ getService }: FtrProviderContext) { .concat(excludeTestSubj || []) .map((ts) => [testSubjectToCss(ts)]) .concat([ - ['.ace_scrollbar'], [ '.leaflet-vega-container[role="graphics-document"][aria-roledescription="visualization"]', ], @@ -97,7 +98,7 @@ export function A11yProvider({ getService }: FtrProviderContext) { runOnly: ['wcag2a', 'wcag2aa'], rules: { 'color-contrast': { - enabled: false, + enabled: false, // disabled because we have too many failures }, bypass: { enabled: false, // disabled because it's too flaky diff --git a/test/accessibility/services/a11y/analyze_with_axe.js b/test/accessibility/services/a11y/analyze_with_axe.js index 3cff67fa306dc..aaecdbeb0e95d 100644 --- a/test/accessibility/services/a11y/analyze_with_axe.js +++ b/test/accessibility/services/a11y/analyze_with_axe.js @@ -23,6 +23,26 @@ export function analyzeWithAxe(context, options, callback) { Promise.resolve() .then(() => { if (window.axe) { + window.axe.configure({ + rules: [ + { + id: 'scrollable-region-focusable', + selector: '[data-skip-axe="scrollable-region-focusable"]', + }, + { + id: 'aria-required-children', + selector: '[data-skip-axe="aria-required-children"] > *', + }, + { + id: 'label', + selector: '[data-test-subj="comboBoxSearchInput"] *', + }, + { + id: 'aria-roles', + selector: '[data-test-subj="comboBoxSearchInput"] *', + }, + ], + }); return window.axe.run(context, options); } @@ -31,7 +51,14 @@ export function analyzeWithAxe(context, options, callback) { }) .then( (result) => callback({ result }), - (error) => callback({ error }) + (error) => { + callback({ + error: { + message: error.message, + stack: error.stack, + }, + }); + } ); } diff --git a/test/api_integration/apis/index_patterns/fields_for_wildcard_route/response.js b/test/api_integration/apis/index_patterns/fields_for_wildcard_route/response.js index 45a09be6c2deb..ae96f17fdceb9 100644 --- a/test/api_integration/apis/index_patterns/fields_for_wildcard_route/response.js +++ b/test/api_integration/apis/index_patterns/fields_for_wildcard_route/response.js @@ -28,12 +28,12 @@ export default function ({ getService }) { expect(resp.body.fields).to.eql(sortBy(resp.body.fields, 'name')); }; - describe('response', () => { + describe('fields_for_wildcard_route response', () => { before(() => esArchiver.load('index_patterns/basic_index')); after(() => esArchiver.unload('index_patterns/basic_index')); - it('returns a flattened version of the fields in es', () => - supertest + it('returns a flattened version of the fields in es', async () => { + await supertest .get('/api/index_patterns/_fields_for_wildcard') .query({ pattern: 'basic_index' }) .expect(200, { @@ -86,10 +86,12 @@ export default function ({ getService }) { }, ], }) - .then(ensureFieldsAreSorted)); + .then(ensureFieldsAreSorted); + }); - it('always returns a field for all passed meta fields', () => - supertest + // https://github.com/elastic/kibana/issues/79813 + it.skip('always returns a field for all passed meta fields', async () => { + await supertest .get('/api/index_patterns/_fields_for_wildcard') .query({ pattern: 'basic_index', @@ -168,14 +170,16 @@ export default function ({ getService }) { }, ], }) - .then(ensureFieldsAreSorted)); + .then(ensureFieldsAreSorted); + }); - it('returns 404 when the pattern does not exist', () => - supertest + it('returns 404 when the pattern does not exist', async () => { + await supertest .get('/api/index_patterns/_fields_for_wildcard') .query({ pattern: '[non-existing-pattern]its-invalid-*', }) - .expect(404)); + .expect(404); + }); }); } diff --git a/test/api_integration/apis/kql_telemetry/kql_telemetry.js b/test/api_integration/apis/kql_telemetry/kql_telemetry.js index a696cd148485f..f28b01def3e5a 100644 --- a/test/api_integration/apis/kql_telemetry/kql_telemetry.js +++ b/test/api_integration/apis/kql_telemetry/kql_telemetry.js @@ -32,7 +32,7 @@ export default function ({ getService }) { it('should increment the opt *in* counter in the .kibana/kql-telemetry document', async () => { await supertest - .post('/api/kibana/kql_opt_in_telemetry') + .post('/api/kibana/kql_opt_in_stats') .set('content-type', 'application/json') .send({ opt_in: true }) .expect(200); @@ -50,7 +50,7 @@ export default function ({ getService }) { it('should increment the opt *out* counter in the .kibana/kql-telemetry document', async () => { await supertest - .post('/api/kibana/kql_opt_in_telemetry') + .post('/api/kibana/kql_opt_in_stats') .set('content-type', 'application/json') .send({ opt_in: false }) .expect(200); @@ -68,7 +68,7 @@ export default function ({ getService }) { it('should report success when opt *in* is incremented successfully', () => { return supertest - .post('/api/kibana/kql_opt_in_telemetry') + .post('/api/kibana/kql_opt_in_stats') .set('content-type', 'application/json') .send({ opt_in: true }) .expect('Content-Type', /json/) @@ -80,7 +80,7 @@ export default function ({ getService }) { it('should report success when opt *out* is incremented successfully', () => { return supertest - .post('/api/kibana/kql_opt_in_telemetry') + .post('/api/kibana/kql_opt_in_stats') .set('content-type', 'application/json') .send({ opt_in: false }) .expect('Content-Type', /json/) @@ -93,27 +93,27 @@ export default function ({ getService }) { it('should only accept literal boolean values for the opt_in POST body param', function () { return Bluebird.all([ supertest - .post('/api/kibana/kql_opt_in_telemetry') + .post('/api/kibana/kql_opt_in_stats') .set('content-type', 'application/json') .send({ opt_in: 'notabool' }) .expect(400), supertest - .post('/api/kibana/kql_opt_in_telemetry') + .post('/api/kibana/kql_opt_in_stats') .set('content-type', 'application/json') .send({ opt_in: 0 }) .expect(400), supertest - .post('/api/kibana/kql_opt_in_telemetry') + .post('/api/kibana/kql_opt_in_stats') .set('content-type', 'application/json') .send({ opt_in: null }) .expect(400), supertest - .post('/api/kibana/kql_opt_in_telemetry') + .post('/api/kibana/kql_opt_in_stats') .set('content-type', 'application/json') .send({ opt_in: undefined }) .expect(400), supertest - .post('/api/kibana/kql_opt_in_telemetry') + .post('/api/kibana/kql_opt_in_stats') .set('content-type', 'application/json') .send({}) .expect(400), diff --git a/test/common/config.js b/test/common/config.js index 6a62151b12814..9d6d531ae4b37 100644 --- a/test/common/config.js +++ b/test/common/config.js @@ -48,6 +48,9 @@ export default function () { `--elasticsearch.username=${kibanaServerTestUser.username}`, `--elasticsearch.password=${kibanaServerTestUser.password}`, `--home.disableWelcomeScreen=true`, + // Needed for async search functional tests to introduce a delay + `--data.search.aggs.shardDelay.enabled=true`, + `--security.showInsecureClusterWarning=false`, '--telemetry.banner=false', '--telemetry.optIn=false', // These are *very* important to have them pointing to staging diff --git a/test/common/services/kibana_server/extend_es_archiver.js b/test/common/services/kibana_server/extend_es_archiver.js index 4efdfc4dddf77..f6e14061aed2a 100644 --- a/test/common/services/kibana_server/extend_es_archiver.js +++ b/test/common/services/kibana_server/extend_es_archiver.js @@ -33,9 +33,15 @@ export function extendEsArchiver({ esArchiver, kibanaServer, retry, defaults }) // esArchiver methods return a stats object, with information about the indexes created const stats = await originalMethod.apply(esArchiver, args); + const statsKeys = Object.keys(stats); + const kibanaKeys = statsKeys.filter( + // this also matches stats keys like '.kibana_1' and '.kibana_2,.kibana_1' + (key) => key.includes(KIBANA_INDEX) && (stats[key].created || stats[key].deleted) + ); + // if the kibana index was created by the esArchiver then update the uiSettings // with the defaults to make sure that they are always in place initially - if (stats[KIBANA_INDEX] && (stats[KIBANA_INDEX].created || stats[KIBANA_INDEX].deleted)) { + if (kibanaKeys.length > 0) { await retry.try(async () => { await kibanaServer.uiSettings.update(defaults); }); diff --git a/test/functional/apps/dashboard/edit_visualizations.js b/test/functional/apps/dashboard/edit_visualizations.js new file mode 100644 index 0000000000000..a9bd2e87bcad5 --- /dev/null +++ b/test/functional/apps/dashboard/edit_visualizations.js @@ -0,0 +1,100 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +import expect from '@kbn/expect'; + +export default function ({ getService, getPageObjects }) { + const PageObjects = getPageObjects(['dashboard', 'header', 'visualize', 'common', 'visEditor']); + const esArchiver = getService('esArchiver'); + const testSubjects = getService('testSubjects'); + const kibanaServer = getService('kibanaServer'); + const dashboardPanelActions = getService('dashboardPanelActions'); + const dashboardVisualizations = getService('dashboardVisualizations'); + + const originalMarkdownText = 'Original markdown text'; + const modifiedMarkdownText = 'Modified markdown text'; + + const createMarkdownVis = async (title) => { + await testSubjects.click('dashboardAddNewPanelButton'); + await dashboardVisualizations.ensureNewVisualizationDialogIsShowing(); + await PageObjects.visualize.clickMarkdownWidget(); + await PageObjects.visEditor.setMarkdownTxt(originalMarkdownText); + await PageObjects.visEditor.clickGo(); + await PageObjects.visualize.saveVisualizationExpectSuccess(title, { + saveAsNew: true, + redirectToOrigin: true, + }); + }; + + const editMarkdownVis = async () => { + await dashboardPanelActions.openContextMenu(); + await dashboardPanelActions.clickEdit(); + await PageObjects.header.waitUntilLoadingHasFinished(); + await PageObjects.visEditor.setMarkdownTxt(modifiedMarkdownText); + await PageObjects.visEditor.clickGo(); + }; + + describe('edit visualizations from dashboard', () => { + before(async () => { + await esArchiver.load('dashboard/current/kibana'); + await kibanaServer.uiSettings.replace({ + defaultIndex: '0bf35f60-3dc9-11e8-8660-4d65aa086b3c', + }); + await PageObjects.common.navigateToApp('dashboard'); + }); + + it('save button returns to dashboard after editing visualization with changes saved', async () => { + const title = 'test save'; + await PageObjects.dashboard.gotoDashboardLandingPage(); + await PageObjects.dashboard.clickNewDashboard(); + + await createMarkdownVis(title); + + await editMarkdownVis(); + await PageObjects.visualize.saveVisualizationAndReturn(); + + const markdownText = await testSubjects.find('markdownBody'); + expect(await markdownText.getVisibleText()).to.eql(modifiedMarkdownText); + }); + + it('cancel button returns to dashboard after editing visualization without saving', async () => { + const title = 'test cancel'; + await PageObjects.dashboard.gotoDashboardLandingPage(); + await PageObjects.dashboard.clickNewDashboard(); + + await createMarkdownVis(title); + + await editMarkdownVis(); + await PageObjects.visualize.cancelAndReturn(true); + + const markdownText = await testSubjects.find('markdownBody'); + expect(await markdownText.getVisibleText()).to.eql(originalMarkdownText); + }); + + it('cancel button returns to dashboard with no modal if there are no changes to apply', async () => { + await dashboardPanelActions.openContextMenu(); + await dashboardPanelActions.clickEdit(); + await PageObjects.header.waitUntilLoadingHasFinished(); + + await PageObjects.visualize.cancelAndReturn(false); + + const markdownText = await testSubjects.find('markdownBody'); + expect(await markdownText.getVisibleText()).to.eql(originalMarkdownText); + }); + }); +} diff --git a/test/functional/apps/dashboard/index.js b/test/functional/apps/dashboard/index.js index 5a30456bd59ab..b62907dfe2c24 100644 --- a/test/functional/apps/dashboard/index.js +++ b/test/functional/apps/dashboard/index.js @@ -53,9 +53,11 @@ export default function ({ getService, loadTestFile }) { loadTestFile(require.resolve('./embeddable_rendering')); loadTestFile(require.resolve('./create_and_add_embeddables')); loadTestFile(require.resolve('./edit_embeddable_redirects')); + loadTestFile(require.resolve('./edit_visualizations')); loadTestFile(require.resolve('./time_zones')); loadTestFile(require.resolve('./dashboard_options')); loadTestFile(require.resolve('./data_shared_attributes')); + loadTestFile(require.resolve('./share')); loadTestFile(require.resolve('./embed_mode')); loadTestFile(require.resolve('./dashboard_back_button')); loadTestFile(require.resolve('./dashboard_error_handling')); @@ -96,7 +98,9 @@ export default function ({ getService, loadTestFile }) { loadTestFile(require.resolve('./dashboard_time_picker')); loadTestFile(require.resolve('./bwc_shared_urls')); - loadTestFile(require.resolve('./panel_controls')); + loadTestFile(require.resolve('./panel_replacing')); + loadTestFile(require.resolve('./panel_cloning')); + loadTestFile(require.resolve('./panel_context_menu')); loadTestFile(require.resolve('./dashboard_state')); }); diff --git a/test/functional/apps/dashboard/panel_cloning.ts b/test/functional/apps/dashboard/panel_cloning.ts new file mode 100644 index 0000000000000..0535b66f08a16 --- /dev/null +++ b/test/functional/apps/dashboard/panel_cloning.ts @@ -0,0 +1,80 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import expect from '@kbn/expect'; +import { PIE_CHART_VIS_NAME } from '../../page_objects/dashboard_page'; +import { FtrProviderContext } from '../../ftr_provider_context'; + +export default function ({ getService, getPageObjects }: FtrProviderContext) { + const dashboardPanelActions = getService('dashboardPanelActions'); + const dashboardAddPanel = getService('dashboardAddPanel'); + const PageObjects = getPageObjects([ + 'dashboard', + 'header', + 'visualize', + 'discover', + 'timePicker', + ]); + + describe('dashboard panel cloning', function viewEditModeTests() { + before(async function () { + await PageObjects.dashboard.initTests(); + await PageObjects.dashboard.preserveCrossAppState(); + await PageObjects.dashboard.clickNewDashboard(); + await PageObjects.timePicker.setHistoricalDataRange(); + await dashboardAddPanel.addVisualization(PIE_CHART_VIS_NAME); + }); + + after(async function () { + await PageObjects.dashboard.gotoDashboardLandingPage(); + }); + + it('clones a panel', async () => { + const initialPanelTitles = await PageObjects.dashboard.getPanelTitles(); + await dashboardPanelActions.clonePanelByTitle(PIE_CHART_VIS_NAME); + await PageObjects.header.waitUntilLoadingHasFinished(); + await PageObjects.dashboard.waitForRenderComplete(); + const postPanelTitles = await PageObjects.dashboard.getPanelTitles(); + expect(postPanelTitles.length).to.equal(initialPanelTitles.length + 1); + }); + + it('appends a clone title tag', async () => { + const panelTitles = await PageObjects.dashboard.getPanelTitles(); + expect(panelTitles[1]).to.equal(PIE_CHART_VIS_NAME + ' (copy)'); + }); + + it('retains original panel dimensions', async () => { + const panelDimensions = await PageObjects.dashboard.getPanelDimensions(); + expect(panelDimensions[0]).to.eql(panelDimensions[1]); + }); + + it('gives a correct title to the clone of a clone', async () => { + const initialPanelTitles = await PageObjects.dashboard.getPanelTitles(); + const clonedPanelName = initialPanelTitles[initialPanelTitles.length - 1]; + await dashboardPanelActions.clonePanelByTitle(clonedPanelName); + await PageObjects.header.waitUntilLoadingHasFinished(); + await PageObjects.dashboard.waitForRenderComplete(); + const postPanelTitles = await PageObjects.dashboard.getPanelTitles(); + expect(postPanelTitles.length).to.equal(initialPanelTitles.length + 1); + expect(postPanelTitles[postPanelTitles.length - 1]).to.equal( + PIE_CHART_VIS_NAME + ' (copy 1)' + ); + }); + }); +} diff --git a/test/functional/apps/dashboard/panel_context_menu.ts b/test/functional/apps/dashboard/panel_context_menu.ts new file mode 100644 index 0000000000000..0b9e873f46151 --- /dev/null +++ b/test/functional/apps/dashboard/panel_context_menu.ts @@ -0,0 +1,185 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import expect from '@kbn/expect'; +import { PIE_CHART_VIS_NAME } from '../../page_objects/dashboard_page'; +import { VisualizeConstants } from '../../../../src/plugins/visualize/public/application/visualize_constants'; +import { FtrProviderContext } from '../../ftr_provider_context'; + +export default function ({ getService, getPageObjects }: FtrProviderContext) { + const browser = getService('browser'); + const dashboardPanelActions = getService('dashboardPanelActions'); + const dashboardAddPanel = getService('dashboardAddPanel'); + const dashboardVisualizations = getService('dashboardVisualizations'); + const PageObjects = getPageObjects([ + 'dashboard', + 'header', + 'visualize', + 'discover', + 'timePicker', + ]); + const dashboardName = 'Dashboard Panel Controls Test'; + + describe('dashboard panel context menu', function viewEditModeTests() { + before(async function () { + await PageObjects.dashboard.initTests(); + await PageObjects.dashboard.preserveCrossAppState(); + await PageObjects.dashboard.clickNewDashboard(); + await PageObjects.timePicker.setHistoricalDataRange(); + await dashboardAddPanel.addVisualization(PIE_CHART_VIS_NAME); + }); + + after(async function () { + await PageObjects.dashboard.gotoDashboardLandingPage(); + }); + + it('are hidden in view mode', async function () { + await PageObjects.dashboard.saveDashboard(dashboardName); + + await dashboardPanelActions.openContextMenu(); + await dashboardPanelActions.expectMissingEditPanelAction(); + await dashboardPanelActions.expectMissingRemovePanelAction(); + }); + + it('are shown in edit mode', async function () { + await PageObjects.dashboard.switchToEditMode(); + + const isContextMenuIconVisible = await dashboardPanelActions.isContextMenuIconVisible(); + expect(isContextMenuIconVisible).to.equal(true); + + await dashboardPanelActions.expectExistsEditPanelAction(); + await dashboardPanelActions.expectExistsClonePanelAction(); + await dashboardPanelActions.expectExistsReplacePanelAction(); + await dashboardPanelActions.expectExistsRemovePanelAction(); + await dashboardPanelActions.expectExistsToggleExpandAction(); + }); + + it('are shown in edit mode after a hard refresh', async () => { + // Based off an actual bug encountered in a PR where a hard refresh in + // edit mode did not show the edit mode controls. + const currentUrl = await browser.getCurrentUrl(); + // The second parameter of true will include the timestamp in the url and + // trigger a hard refresh. + await browser.get(currentUrl.toString(), true); + await PageObjects.header.waitUntilLoadingHasFinished(); + + await dashboardPanelActions.expectExistsEditPanelAction(); + await dashboardPanelActions.expectExistsClonePanelAction(); + await dashboardPanelActions.expectExistsReplacePanelAction(); + await dashboardPanelActions.expectExistsRemovePanelAction(); + + // Get rid of the timestamp in the url. + await browser.get(currentUrl.toString(), false); + }); + + describe('visualization object edit menu', () => { + it('opens a visualization when edit link is clicked', async () => { + await dashboardPanelActions.clickEdit(); + await PageObjects.header.waitUntilLoadingHasFinished(); + const currentUrl = await browser.getCurrentUrl(); + expect(currentUrl).to.contain(VisualizeConstants.EDIT_PATH); + }); + + it('deletes the visualization when delete link is clicked', async () => { + await PageObjects.header.clickDashboard(); + await PageObjects.header.waitUntilLoadingHasFinished(); + await dashboardPanelActions.removePanel(); + + const panelCount = await PageObjects.dashboard.getPanelCount(); + expect(panelCount).to.be(0); + }); + }); + + describe('saved search object edit menu', () => { + const searchName = 'my search'; + + before(async () => { + await PageObjects.header.clickDiscover(); + await PageObjects.discover.clickNewSearchButton(); + await dashboardVisualizations.createSavedSearch({ name: searchName, fields: ['bytes'] }); + await PageObjects.header.waitUntilLoadingHasFinished(); + await PageObjects.header.clickDashboard(); + + const inViewMode = await PageObjects.dashboard.getIsInViewMode(); + if (inViewMode) await PageObjects.dashboard.switchToEditMode(); + await dashboardAddPanel.addSavedSearch(searchName); + }); + + it('should be one panel on dashboard', async () => { + const panelCount = await PageObjects.dashboard.getPanelCount(); + expect(panelCount).to.be(1); + }); + + it('opens a saved search when edit link is clicked', async () => { + await dashboardPanelActions.clickEdit(); + await PageObjects.header.waitUntilLoadingHasFinished(); + const queryName = await PageObjects.discover.getCurrentQueryName(); + expect(queryName).to.be(searchName); + }); + + it('deletes the saved search when delete link is clicked', async () => { + await PageObjects.header.clickDashboard(); + await PageObjects.header.waitUntilLoadingHasFinished(); + await dashboardPanelActions.removePanel(); + + const panelCount = await PageObjects.dashboard.getPanelCount(); + expect(panelCount).to.be(0); + }); + }); + + describe('on an expanded panel', function () { + before('reset dashboard', async () => { + const currentUrl = await browser.getCurrentUrl(); + await browser.get(currentUrl.toString(), false); + }); + + before('and add one panel and save to put dashboard in "view" mode', async () => { + await dashboardAddPanel.addVisualization(PIE_CHART_VIS_NAME); + await PageObjects.dashboard.saveDashboard(dashboardName); + }); + + before('expand panel to "full screen"', async () => { + await dashboardPanelActions.clickExpandPanelToggle(); + }); + + it('context menu actions are hidden in view mode', async function () { + await dashboardPanelActions.expectMissingEditPanelAction(); + await dashboardPanelActions.expectMissingDuplicatePanelAction(); + await dashboardPanelActions.expectMissingReplacePanelAction(); + await dashboardPanelActions.expectMissingRemovePanelAction(); + }); + + describe('in edit mode', () => { + it('switch to edit mode', async function () { + await PageObjects.dashboard.switchToEditMode(); + }); + + it('some context menu actions should be present', async function () { + await dashboardPanelActions.expectExistsEditPanelAction(); + await dashboardPanelActions.expectExistsClonePanelAction(); + await dashboardPanelActions.expectExistsReplacePanelAction(); + }); + + it('"remove panel" action should not be present', async function () { + await dashboardPanelActions.expectMissingRemovePanelAction(); + }); + }); + }); + }); +} diff --git a/test/functional/apps/dashboard/panel_controls.js b/test/functional/apps/dashboard/panel_controls.js deleted file mode 100644 index 748e9fdc5f19d..0000000000000 --- a/test/functional/apps/dashboard/panel_controls.js +++ /dev/null @@ -1,293 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import expect from '@kbn/expect'; - -import { - PIE_CHART_VIS_NAME, - AREA_CHART_VIS_NAME, - LINE_CHART_VIS_NAME, -} from '../../page_objects/dashboard_page'; -import { VisualizeConstants } from '../../../../src/plugins/visualize/public/application/visualize_constants'; - -export default function ({ getService, getPageObjects }) { - const browser = getService('browser'); - const dashboardPanelActions = getService('dashboardPanelActions'); - const dashboardAddPanel = getService('dashboardAddPanel'); - const dashboardReplacePanel = getService('dashboardReplacePanel'); - const dashboardVisualizations = getService('dashboardVisualizations'); - const renderable = getService('renderable'); - const PageObjects = getPageObjects([ - 'dashboard', - 'header', - 'visualize', - 'discover', - 'timePicker', - ]); - const dashboardName = 'Dashboard Panel Controls Test'; - - describe('dashboard panel controls', function viewEditModeTests() { - before(async function () { - await PageObjects.dashboard.initTests(); - await PageObjects.dashboard.preserveCrossAppState(); - }); - - after(async function () { - await PageObjects.dashboard.gotoDashboardLandingPage(); - }); - - describe('visualization object replace flyout', () => { - let intialDimensions; - before(async () => { - await PageObjects.dashboard.clickNewDashboard(); - await PageObjects.timePicker.setHistoricalDataRange(); - await dashboardAddPanel.addVisualization(PIE_CHART_VIS_NAME); - await dashboardAddPanel.addVisualization(LINE_CHART_VIS_NAME); - intialDimensions = await PageObjects.dashboard.getPanelDimensions(); - }); - - after(async function () { - await PageObjects.dashboard.gotoDashboardLandingPage(); - }); - - it('replaces old panel with selected panel', async () => { - await dashboardPanelActions.replacePanelByTitle(PIE_CHART_VIS_NAME); - await dashboardReplacePanel.replaceEmbeddable(AREA_CHART_VIS_NAME); - await PageObjects.header.waitUntilLoadingHasFinished(); - const panelTitles = await PageObjects.dashboard.getPanelTitles(); - expect(panelTitles.length).to.be(2); - expect(panelTitles[0]).to.be(AREA_CHART_VIS_NAME); - }); - - it('replaces selected visualization with old dimensions', async () => { - const newDimensions = await PageObjects.dashboard.getPanelDimensions(); - expect(intialDimensions[0]).to.eql(newDimensions[0]); - }); - - it('replaced panel persisted correctly when dashboard is hard refreshed', async () => { - const currentUrl = await browser.getCurrentUrl(); - await browser.get(currentUrl, true); - await PageObjects.header.waitUntilLoadingHasFinished(); - await PageObjects.dashboard.waitForRenderComplete(); - const panelTitles = await PageObjects.dashboard.getPanelTitles(); - expect(panelTitles.length).to.be(2); - expect(panelTitles[0]).to.be(AREA_CHART_VIS_NAME); - }); - - it('replaced panel with saved search', async () => { - const replacedSearch = 'replaced saved search'; - await dashboardVisualizations.createSavedSearch({ - name: replacedSearch, - fields: ['bytes', 'agent'], - }); - await PageObjects.header.clickDashboard(); - const inViewMode = await PageObjects.dashboard.getIsInViewMode(); - if (inViewMode) { - await PageObjects.dashboard.switchToEditMode(); - } - await dashboardPanelActions.replacePanelByTitle(AREA_CHART_VIS_NAME); - await dashboardReplacePanel.replaceEmbeddable(replacedSearch, 'search'); - await PageObjects.header.waitUntilLoadingHasFinished(); - await PageObjects.dashboard.waitForRenderComplete(); - const panelTitles = await PageObjects.dashboard.getPanelTitles(); - expect(panelTitles.length).to.be(2); - expect(panelTitles[0]).to.be(replacedSearch); - }); - }); - - describe('panel cloning', function () { - before(async () => { - await PageObjects.dashboard.clickNewDashboard(); - await PageObjects.timePicker.setHistoricalDataRange(); - await dashboardAddPanel.addVisualization(PIE_CHART_VIS_NAME); - }); - - after(async function () { - await PageObjects.dashboard.gotoDashboardLandingPage(); - }); - - it('clones a panel', async () => { - const initialPanelTitles = await PageObjects.dashboard.getPanelTitles(); - await dashboardPanelActions.clonePanelByTitle(PIE_CHART_VIS_NAME); - await PageObjects.header.waitUntilLoadingHasFinished(); - await PageObjects.dashboard.waitForRenderComplete(); - const postPanelTitles = await PageObjects.dashboard.getPanelTitles(); - expect(postPanelTitles.length).to.equal(initialPanelTitles.length + 1); - }); - - it('appends a clone title tag', async () => { - const panelTitles = await PageObjects.dashboard.getPanelTitles(); - expect(panelTitles[1]).to.equal(PIE_CHART_VIS_NAME + ' (copy)'); - }); - - it('retains original panel dimensions', async () => { - const panelDimensions = await PageObjects.dashboard.getPanelDimensions(); - expect(panelDimensions[0]).to.eql(panelDimensions[1]); - }); - - it('gives a correct title to the clone of a clone', async () => { - const initialPanelTitles = await PageObjects.dashboard.getPanelTitles(); - const clonedPanelName = initialPanelTitles[initialPanelTitles.length - 1]; - await dashboardPanelActions.clonePanelByTitle(clonedPanelName); - await PageObjects.header.waitUntilLoadingHasFinished(); - await PageObjects.dashboard.waitForRenderComplete(); - const postPanelTitles = await PageObjects.dashboard.getPanelTitles(); - expect(postPanelTitles.length).to.equal(initialPanelTitles.length + 1); - expect(postPanelTitles[postPanelTitles.length - 1]).to.equal( - PIE_CHART_VIS_NAME + ' (copy 1)' - ); - }); - }); - - describe('panel edit controls', function () { - before(async () => { - await PageObjects.dashboard.clickNewDashboard(); - await PageObjects.timePicker.setHistoricalDataRange(); - await dashboardAddPanel.addVisualization(PIE_CHART_VIS_NAME); - }); - - it('are hidden in view mode', async function () { - await PageObjects.dashboard.saveDashboard(dashboardName); - - await dashboardPanelActions.openContextMenu(); - await dashboardPanelActions.expectMissingEditPanelAction(); - await dashboardPanelActions.expectMissingRemovePanelAction(); - }); - - it('are shown in edit mode', async function () { - await PageObjects.dashboard.switchToEditMode(); - - const isContextMenuIconVisible = await dashboardPanelActions.isContextMenuIconVisible(); - expect(isContextMenuIconVisible).to.equal(true); - await dashboardPanelActions.openContextMenu(); - - await dashboardPanelActions.expectExistsEditPanelAction(); - await dashboardPanelActions.expectExistsReplacePanelAction(); - await dashboardPanelActions.expectExistsDuplicatePanelAction(); - await dashboardPanelActions.expectExistsRemovePanelAction(); - }); - - // Based off an actual bug encountered in a PR where a hard refresh in edit mode did not show the edit mode - // controls. - it('are shown in edit mode after a hard refresh', async () => { - const currentUrl = await browser.getCurrentUrl(); - // the second parameter of true will include the timestamp in the url and trigger a hard refresh. - await browser.get(currentUrl.toString(), true); - await PageObjects.header.waitUntilLoadingHasFinished(); - - await dashboardPanelActions.openContextMenu(); - await dashboardPanelActions.expectExistsEditPanelAction(); - await dashboardPanelActions.expectExistsReplacePanelAction(); - await dashboardPanelActions.expectExistsDuplicatePanelAction(); - await dashboardPanelActions.expectExistsRemovePanelAction(); - - // Get rid of the timestamp in the url. - await browser.get(currentUrl.toString(), false); - }); - - describe('on an expanded panel', function () { - it('are hidden in view mode', async function () { - await renderable.waitForRender(); - await PageObjects.dashboard.saveDashboard(dashboardName); - await dashboardPanelActions.openContextMenu(); - await dashboardPanelActions.clickExpandPanelToggle(); - await dashboardPanelActions.openContextMenu(); - await dashboardPanelActions.expectMissingEditPanelAction(); - await dashboardPanelActions.expectMissingReplacePanelAction(); - await dashboardPanelActions.expectMissingDuplicatePanelAction(); - await dashboardPanelActions.expectMissingRemovePanelAction(); - }); - - it('in edit mode hides remove icons ', async function () { - await PageObjects.dashboard.switchToEditMode(); - await dashboardPanelActions.openContextMenu(); - await dashboardPanelActions.expectExistsEditPanelAction(); - await dashboardPanelActions.expectExistsReplacePanelAction(); - await dashboardPanelActions.expectExistsDuplicatePanelAction(); - await dashboardPanelActions.expectMissingRemovePanelAction(); - await dashboardPanelActions.clickExpandPanelToggle(); - }); - }); - - describe('visualization object edit menu', () => { - it('opens a visualization when edit link is clicked', async () => { - await dashboardPanelActions.openContextMenu(); - await dashboardPanelActions.clickEdit(); - await PageObjects.header.waitUntilLoadingHasFinished(); - const currentUrl = await browser.getCurrentUrl(); - expect(currentUrl).to.contain(VisualizeConstants.EDIT_PATH); - }); - - it('deletes the visualization when delete link is clicked', async () => { - await PageObjects.header.clickDashboard(); - await PageObjects.header.waitUntilLoadingHasFinished(); - await dashboardPanelActions.removePanel(); - - const panelCount = await PageObjects.dashboard.getPanelCount(); - expect(panelCount).to.be(0); - }); - }); - - describe('saved search object edit menu', () => { - const searchName = 'my search'; - before(async () => { - await PageObjects.header.clickDiscover(); - await PageObjects.discover.clickNewSearchButton(); - await dashboardVisualizations.createSavedSearch({ name: searchName, fields: ['bytes'] }); - await PageObjects.header.waitUntilLoadingHasFinished(); - await PageObjects.header.clickDashboard(); - const inViewMode = await PageObjects.dashboard.getIsInViewMode(); - if (inViewMode) { - await PageObjects.dashboard.switchToEditMode(); - } - await dashboardAddPanel.addSavedSearch(searchName); - - const panelCount = await PageObjects.dashboard.getPanelCount(); - expect(panelCount).to.be(1); - }); - - it('opens a saved search when edit link is clicked', async () => { - await dashboardPanelActions.openContextMenu(); - await dashboardPanelActions.clickEdit(); - await PageObjects.header.waitUntilLoadingHasFinished(); - const queryName = await PageObjects.discover.getCurrentQueryName(); - expect(queryName).to.be(searchName); - }); - - it('deletes the saved search when delete link is clicked', async () => { - await PageObjects.header.clickDashboard(); - await PageObjects.header.waitUntilLoadingHasFinished(); - await dashboardPanelActions.removePanel(); - - const panelCount = await PageObjects.dashboard.getPanelCount(); - expect(panelCount).to.be(0); - }); - }); - }); - - // Panel expand should also be shown in view mode, but only on mouse hover. - describe('panel expand control', function () { - it('shown in edit mode', async function () { - await PageObjects.dashboard.gotoDashboardEditMode(dashboardName); - await dashboardPanelActions.openContextMenu(); - await dashboardPanelActions.expectExistsToggleExpandAction(); - }); - }); - }); -} diff --git a/test/functional/apps/dashboard/panel_expand_toggle.js b/test/functional/apps/dashboard/panel_expand_toggle.js index e3343f29922e2..7fe3f87918e57 100644 --- a/test/functional/apps/dashboard/panel_expand_toggle.js +++ b/test/functional/apps/dashboard/panel_expand_toggle.js @@ -21,6 +21,7 @@ import expect from '@kbn/expect'; export default function ({ getService, getPageObjects }) { const retry = getService('retry'); + const browser = getService('browser'); const esArchiver = getService('esArchiver'); const kibanaServer = getService('kibanaServer'); const dashboardPanelActions = getService('dashboardPanelActions'); @@ -61,5 +62,18 @@ export default function ({ getService, getPageObjects }) { expect(panelCountAfterMaxThenMinimize).to.be(panelCount); }); }); + + it('minimizes using the browser back button', async () => { + const panelCount = await PageObjects.dashboard.getPanelCount(); + + await dashboardPanelActions.openContextMenu(); + await dashboardPanelActions.clickExpandPanelToggle(); + + await browser.goBack(); + await retry.try(async () => { + const panelCountAfterMaxThenMinimize = await PageObjects.dashboard.getPanelCount(); + expect(panelCountAfterMaxThenMinimize).to.be(panelCount); + }); + }); }); } diff --git a/test/functional/apps/dashboard/panel_replacing.ts b/test/functional/apps/dashboard/panel_replacing.ts new file mode 100644 index 0000000000000..6bf3dbbe47b1d --- /dev/null +++ b/test/functional/apps/dashboard/panel_replacing.ts @@ -0,0 +1,100 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import expect from '@kbn/expect'; +import { + PIE_CHART_VIS_NAME, + AREA_CHART_VIS_NAME, + LINE_CHART_VIS_NAME, +} from '../../page_objects/dashboard_page'; +import { FtrProviderContext } from '../../ftr_provider_context'; + +export default function ({ getService, getPageObjects }: FtrProviderContext) { + const browser = getService('browser'); + const dashboardPanelActions = getService('dashboardPanelActions'); + const dashboardAddPanel = getService('dashboardAddPanel'); + const dashboardReplacePanel = getService('dashboardReplacePanel'); + const dashboardVisualizations = getService('dashboardVisualizations'); + const PageObjects = getPageObjects([ + 'dashboard', + 'header', + 'visualize', + 'discover', + 'timePicker', + ]); + + describe('replace dashboard panels', function viewEditModeTests() { + let intialDimensions: undefined | Array<{ width: number; height: number }>; + + before(async function () { + await PageObjects.dashboard.initTests(); + await PageObjects.dashboard.preserveCrossAppState(); + await PageObjects.dashboard.clickNewDashboard(); + await PageObjects.timePicker.setHistoricalDataRange(); + await dashboardAddPanel.addVisualization(PIE_CHART_VIS_NAME); + await dashboardAddPanel.addVisualization(LINE_CHART_VIS_NAME); + intialDimensions = await PageObjects.dashboard.getPanelDimensions(); + }); + + after(async function () { + await PageObjects.dashboard.gotoDashboardLandingPage(); + }); + + it('replaces old panel with selected panel', async () => { + await dashboardPanelActions.replacePanelByTitle(PIE_CHART_VIS_NAME); + await dashboardReplacePanel.replaceEmbeddable(AREA_CHART_VIS_NAME); + await PageObjects.header.waitUntilLoadingHasFinished(); + const panelTitles = await PageObjects.dashboard.getPanelTitles(); + expect(panelTitles.length).to.be(2); + expect(panelTitles[0]).to.be(AREA_CHART_VIS_NAME); + const newDimensions = await PageObjects.dashboard.getPanelDimensions(); + expect(intialDimensions![0]).to.eql(newDimensions[0]); + }); + + it('replaced panel persisted correctly when dashboard is hard refreshed', async () => { + const currentUrl = await browser.getCurrentUrl(); + await browser.get(currentUrl, true); + await PageObjects.header.waitUntilLoadingHasFinished(); + await PageObjects.dashboard.waitForRenderComplete(); + const panelTitles = await PageObjects.dashboard.getPanelTitles(); + expect(panelTitles.length).to.be(2); + expect(panelTitles[0]).to.be(AREA_CHART_VIS_NAME); + }); + + it('replaced panel with saved search', async () => { + const replacedSearch = 'replaced saved search'; + await dashboardVisualizations.createSavedSearch({ + name: replacedSearch, + fields: ['bytes', 'agent'], + }); + await PageObjects.header.clickDashboard(); + const inViewMode = await PageObjects.dashboard.getIsInViewMode(); + if (inViewMode) { + await PageObjects.dashboard.switchToEditMode(); + } + await dashboardPanelActions.replacePanelByTitle(AREA_CHART_VIS_NAME); + await dashboardReplacePanel.replaceEmbeddable(replacedSearch, 'search'); + await PageObjects.header.waitUntilLoadingHasFinished(); + await PageObjects.dashboard.waitForRenderComplete(); + const panelTitles = await PageObjects.dashboard.getPanelTitles(); + expect(panelTitles.length).to.be(2); + expect(panelTitles[0]).to.be(replacedSearch); + }); + }); +} diff --git a/test/functional/apps/dashboard/share.ts b/test/functional/apps/dashboard/share.ts new file mode 100644 index 0000000000000..cc9c4786f0592 --- /dev/null +++ b/test/functional/apps/dashboard/share.ts @@ -0,0 +1,45 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import expect from '@kbn/expect'; +import { FtrProviderContext } from '../../ftr_provider_context'; + +export default function ({ getService, getPageObjects }: FtrProviderContext) { + const esArchiver = getService('esArchiver'); + const kibanaServer = getService('kibanaServer'); + const PageObjects = getPageObjects(['dashboard', 'common', 'share']); + + describe('share dashboard', () => { + before(async () => { + await esArchiver.load('dashboard/current/kibana'); + await kibanaServer.uiSettings.replace({ + defaultIndex: '0bf35f60-3dc9-11e8-8660-4d65aa086b3c', + }); + await PageObjects.common.navigateToApp('dashboard'); + await PageObjects.dashboard.preserveCrossAppState(); + await PageObjects.dashboard.loadSavedDashboard('few panels'); + }); + + it('has "panels" state when sharing a snapshot', async () => { + await PageObjects.share.clickShareTopNavButton(); + const sharedUrl = await PageObjects.share.getSharedUrl(); + expect(sharedUrl).to.contain('panels'); + }); + }); +} diff --git a/test/functional/apps/discover/_doc_navigation.js b/test/functional/apps/discover/_doc_navigation.js index 5ae799f8756c0..87a150c7d6961 100644 --- a/test/functional/apps/discover/_doc_navigation.js +++ b/test/functional/apps/discover/_doc_navigation.js @@ -28,7 +28,6 @@ export default function ({ getService, getPageObjects }) { const esArchiver = getService('esArchiver'); const retry = getService('retry'); - // Flaky: https://github.com/elastic/kibana/issues/71216 describe('doc link in discover', function contextSize() { beforeEach(async function () { log.debug('load kibana index with default index pattern'); diff --git a/test/functional/apps/discover/_errors.js b/test/functional/apps/discover/_errors.js deleted file mode 100644 index 614059dc8ac94..0000000000000 --- a/test/functional/apps/discover/_errors.js +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import expect from '@kbn/expect'; - -export default function ({ getService, getPageObjects }) { - const esArchiver = getService('esArchiver'); - const testSubjects = getService('testSubjects'); - const PageObjects = getPageObjects(['common', 'discover', 'timePicker']); - - describe('errors', function describeIndexTests() { - before(async function () { - await esArchiver.loadIfNeeded('logstash_functional'); - await esArchiver.load('invalid_scripted_field'); - await PageObjects.timePicker.setDefaultAbsoluteRangeViaUiSettings(); - await PageObjects.common.navigateToApp('discover'); - }); - - after(async function () { - await esArchiver.unload('invalid_scripted_field'); - }); - - describe('invalid scripted field error', () => { - it('is rendered', async () => { - const isFetchErrorVisible = await testSubjects.exists('discoverFetchError'); - expect(isFetchErrorVisible).to.be(true); - }); - }); - }); -} diff --git a/test/functional/apps/discover/_errors.ts b/test/functional/apps/discover/_errors.ts new file mode 100644 index 0000000000000..7f1552b90668b --- /dev/null +++ b/test/functional/apps/discover/_errors.ts @@ -0,0 +1,48 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import expect from '@kbn/expect'; +import { FtrProviderContext } from '../../ftr_provider_context'; + +export default function ({ getService, getPageObjects }: FtrProviderContext) { + const esArchiver = getService('esArchiver'); + const toasts = getService('toasts'); + const PageObjects = getPageObjects(['common', 'discover', 'timePicker']); + + describe('errors', function describeIndexTests() { + before(async function () { + await esArchiver.loadIfNeeded('logstash_functional'); + await esArchiver.load('invalid_scripted_field'); + await PageObjects.timePicker.setDefaultAbsoluteRangeViaUiSettings(); + await PageObjects.common.navigateToApp('discover'); + }); + + after(async function () { + await esArchiver.unload('invalid_scripted_field'); + }); + + describe('invalid scripted field error', () => { + it('is rendered', async () => { + const toast = await toasts.getToastElement(1); + const painlessStackTrace = await toast.findByTestSubject('painlessStackTrace'); + expect(painlessStackTrace).not.to.be(undefined); + }); + }); + }); +} diff --git a/test/functional/apps/discover/_field_data.js b/test/functional/apps/discover/_field_data.js index f0472fb5a3da5..d9cb09432b26f 100644 --- a/test/functional/apps/discover/_field_data.js +++ b/test/functional/apps/discover/_field_data.js @@ -27,7 +27,8 @@ export default function ({ getService, getPageObjects }) { const queryBar = getService('queryBar'); const PageObjects = getPageObjects(['common', 'header', 'discover', 'visualize', 'timePicker']); - describe('discover tab', function describeIndexTests() { + // FLAKY: https://github.com/elastic/kibana/issues/78689 + describe.skip('discover tab', function describeIndexTests() { this.tags('includeFirefox'); before(async function () { await esArchiver.loadIfNeeded('logstash_functional'); diff --git a/test/functional/apps/discover/_indexpattern_without_timefield.ts b/test/functional/apps/discover/_indexpattern_without_timefield.ts index 99a7045551dc9..677b27c31bd86 100644 --- a/test/functional/apps/discover/_indexpattern_without_timefield.ts +++ b/test/functional/apps/discover/_indexpattern_without_timefield.ts @@ -22,16 +22,19 @@ import { FtrProviderContext } from '../../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { const esArchiver = getService('esArchiver'); const kibanaServer = getService('kibanaServer'); + const security = getService('security'); const PageObjects = getPageObjects(['common', 'timePicker', 'discover']); describe('indexpattern without timefield', () => { before(async () => { + await security.testUser.setRoles(['kibana_admin', 'kibana_timefield']); await esArchiver.loadIfNeeded('index_pattern_without_timefield'); await kibanaServer.uiSettings.replace({ defaultIndex: 'without-timefield' }); await PageObjects.common.navigateToApp('discover'); }); after(async () => { + await security.testUser.restoreDefaults(); await esArchiver.unload('index_pattern_without_timefield'); }); diff --git a/test/functional/apps/discover/_inspector.js b/test/functional/apps/discover/_inspector.js index 900ad28e14e69..fcb66fbd52cf7 100644 --- a/test/functional/apps/discover/_inspector.js +++ b/test/functional/apps/discover/_inspector.js @@ -34,7 +34,8 @@ export default function ({ getService, getPageObjects }) { return hitsCountStatsRow[STATS_ROW_VALUE_INDEX]; } - describe('inspect', () => { + // FLAKY: https://github.com/elastic/kibana/issues/39842 + describe.skip('inspect', () => { before(async () => { await esArchiver.loadIfNeeded('logstash_functional'); await esArchiver.load('discover'); diff --git a/test/functional/apps/home/_add_data.js b/test/functional/apps/home/_add_data.js index 6ba123e579f7a..401a5becceb30 100644 --- a/test/functional/apps/home/_add_data.js +++ b/test/functional/apps/home/_add_data.js @@ -28,7 +28,7 @@ export default function ({ getService, getPageObjects }) { await PageObjects.common.navigateToUrl('home', 'tutorial_directory', { useActualUrl: true }); await PageObjects.header.waitUntilLoadingHasFinished(); await retry.try(async () => { - const tutorialExists = await PageObjects.home.doesSynopsisExist('netflow'); + const tutorialExists = await PageObjects.home.doesSynopsisExist('netflowlogs'); expect(tutorialExists).to.be(true); }); }); diff --git a/test/functional/apps/management/_index_pattern_popularity.js b/test/functional/apps/management/_index_pattern_popularity.js index e2fcf50ef2c12..530b8e1111a0c 100644 --- a/test/functional/apps/management/_index_pattern_popularity.js +++ b/test/functional/apps/management/_index_pattern_popularity.js @@ -60,7 +60,7 @@ export default function ({ getService, getPageObjects }) { // check that it is 0 (previous increase was cancelled const popularity = await PageObjects.settings.getPopularity(); log.debug('popularity = ' + popularity); - expect(popularity).to.be(''); + expect(popularity).to.be('0'); }); it('can be saved', async function () { diff --git a/test/functional/apps/visualize/_tsvb_chart.ts b/test/functional/apps/visualize/_tsvb_chart.ts index bfe0da7a5b24f..3e325d5e6b907 100644 --- a/test/functional/apps/visualize/_tsvb_chart.ts +++ b/test/functional/apps/visualize/_tsvb_chart.ts @@ -135,11 +135,11 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await PageObjects.visualBuilder.clickPanelOptions('metric'); const fromTime = 'Oct 22, 2018 @ 00:00:00.000'; const toTime = 'Oct 28, 2018 @ 23:59:59.999'; + await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); // Sometimes popovers take some time to appear in Firefox (#71979) await retry.tryForTime(20000, async () => { - await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); await PageObjects.visualBuilder.setIndexPatternValue('kibana_sample_data_flights'); - await PageObjects.common.sleep(3000); + await PageObjects.visualBuilder.waitForIndexPatternTimeFieldOptionsLoaded(); await PageObjects.visualBuilder.selectIndexPatternTimeField('timestamp'); }); const newValue = await PageObjects.visualBuilder.getMetricValue(); diff --git a/test/functional/apps/visualize/_tsvb_time_series.ts b/test/functional/apps/visualize/_tsvb_time_series.ts index 0b2a52b367a20..d4a079a38c814 100644 --- a/test/functional/apps/visualize/_tsvb_time_series.ts +++ b/test/functional/apps/visualize/_tsvb_time_series.ts @@ -84,8 +84,10 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { await visualBuilder.clickSeriesOption(); await visualBuilder.enterSeriesTemplate('$ {{value}}'); - const actualCount = await visualBuilder.getRhythmChartLegendValue(); - expect(actualCount).to.be(expectedLegendValue); + await retry.try(async () => { + const actualCount = await visualBuilder.getRhythmChartLegendValue(); + expect(actualCount).to.be(expectedLegendValue); + }); }); it('should show the correct count in the legend with percent formatter', async () => { diff --git a/test/functional/config.js b/test/functional/config.js index 15097d9346471..6081810d41272 100644 --- a/test/functional/config.js +++ b/test/functional/config.js @@ -229,6 +229,21 @@ export default async function ({ readConfigFile }) { kibana: [], }, + kibana_timefield: { + elasticsearch: { + cluster: [], + indices: [ + { + names: ['without-timefield', 'with-timefield'], + privileges: ['read', 'view_index_metadata'], + field_security: { grant: ['*'], except: [] }, + }, + ], + run_as: [], + }, + kibana: [], + }, + kibana_large_strings: { elasticsearch: { cluster: [], diff --git a/test/functional/page_objects/common_page.ts b/test/functional/page_objects/common_page.ts index 459f596b30256..cc229ef0c2e08 100644 --- a/test/functional/page_objects/common_page.ts +++ b/test/functional/page_objects/common_page.ts @@ -434,7 +434,7 @@ export function CommonPageProvider({ getService, getPageObjects }: FtrProviderCo } } - async getBodyText() { + async getJsonBodyText() { if (await find.existsByCssSelector('a[id=rawdata-tab]', defaultFindTimeout)) { // Firefox has 3 tabs and requires navigation to see Raw output await find.clickByCssSelector('a[id=rawdata-tab]'); @@ -449,6 +449,11 @@ export function CommonPageProvider({ getService, getPageObjects }: FtrProviderCo } } + async getBodyText() { + const body = await find.byCssSelector('body'); + return await body.getVisibleText(); + } + /** * Helper to detect an OSS licensed Kibana * Useful for functional testing in cloud environment @@ -500,6 +505,16 @@ export function CommonPageProvider({ getService, getPageObjects }: FtrProviderCo async scrollKibanaBodyTop() { await browser.setScrollToById('kibana-body', 0, 0); } + + /** + * Dismiss Banner if available. + */ + async dismissBanner() { + if (await testSubjects.exists('global-banner-item')) { + const button = await find.byButtonText('Dismiss'); + await button.click(); + } + } } return new CommonPage(); diff --git a/test/functional/page_objects/discover_page.ts b/test/functional/page_objects/discover_page.ts index 7a99509257bf7..e522f41952a49 100644 --- a/test/functional/page_objects/discover_page.ts +++ b/test/functional/page_objects/discover_page.ts @@ -119,8 +119,7 @@ export function DiscoverPageProvider({ getService, getPageObjects }: FtrProvider public async loadSavedSearch(searchName: string) { await this.openLoadSavedSearchPanel(); - const searchLink = await find.byButtonText(searchName); - await searchLink.click(); + await testSubjects.click(`savedObjectTitle${searchName.split(' ').join('-')}`); await header.waitUntilLoadingHasFinished(); } @@ -387,6 +386,42 @@ export function DiscoverPageProvider({ getService, getPageObjects }: FtrProvider return await this.isDiscoverAppOnScreen(); }); } + + public async showAllFilterActions() { + await testSubjects.click('showFilterActions'); + } + + public async clickSavedQueriesPopOver() { + await testSubjects.click('saved-query-management-popover-button'); + } + + public async clickCurrentSavedQuery() { + await testSubjects.click('saved-query-management-save-button'); + } + + public async setSaveQueryFormTitle(savedQueryName: string) { + await testSubjects.setValue('saveQueryFormTitle', savedQueryName); + } + + public async toggleIncludeFilters() { + await testSubjects.click('saveQueryFormIncludeFiltersOption'); + } + + public async saveCurrentSavedQuery() { + await testSubjects.click('savedQueryFormSaveButton'); + } + + public async deleteSavedQuery() { + await testSubjects.click('delete-saved-query-TEST-button'); + } + + public async confirmDeletionOfSavedQuery() { + await testSubjects.click('confirmModalConfirmButton'); + } + + public async clearSavedQuery() { + await testSubjects.click('saved-query-management-clear-button'); + } } return new DiscoverPage(); diff --git a/test/functional/page_objects/error_page.ts b/test/functional/page_objects/error_page.ts index 332ce835d0b1c..bc256f55155df 100644 --- a/test/functional/page_objects/error_page.ts +++ b/test/functional/page_objects/error_page.ts @@ -26,17 +26,11 @@ export function ErrorPageProvider({ getPageObjects }: FtrProviderContext) { class ErrorPage { public async expectForbidden() { const messageText = await common.getBodyText(); - expect(messageText).to.eql( - JSON.stringify({ - statusCode: 403, - error: 'Forbidden', - message: 'Forbidden', - }) - ); + expect(messageText).to.contain('You do not have permission to access the requested page'); } public async expectNotFound() { - const messageText = await common.getBodyText(); + const messageText = await common.getJsonBodyText(); expect(messageText).to.eql( JSON.stringify({ statusCode: 404, diff --git a/test/functional/page_objects/newsfeed_page.ts b/test/functional/page_objects/newsfeed_page.ts index 52267138819ab..6e5e801589295 100644 --- a/test/functional/page_objects/newsfeed_page.ts +++ b/test/functional/page_objects/newsfeed_page.ts @@ -21,6 +21,7 @@ import { FtrProviderContext } from '../ftr_provider_context'; export function NewsfeedPageProvider({ getService, getPageObjects }: FtrProviderContext) { const log = getService('log'); + const find = getService('find'); const retry = getService('retry'); const flyout = getService('flyout'); const testSubjects = getService('testSubjects'); @@ -49,7 +50,7 @@ export function NewsfeedPageProvider({ getService, getPageObjects }: FtrProvider } async getRedButtonSign() { - return await testSubjects.exists('showBadgeNews'); + return await find.existsByCssSelector('.euiHeaderSectionItemButton__notification--dot'); } async getNewsfeedList() { diff --git a/test/functional/page_objects/visual_builder_page.ts b/test/functional/page_objects/visual_builder_page.ts index 6e49fd3b03494..37634d0248b04 100644 --- a/test/functional/page_objects/visual_builder_page.ts +++ b/test/functional/page_objects/visual_builder_page.ts @@ -453,6 +453,14 @@ export function VisualBuilderPageProvider({ getService, getPageObjects }: FtrPro await PageObjects.header.waitUntilLoadingHasFinished(); } + public async waitForIndexPatternTimeFieldOptionsLoaded() { + await retry.waitFor('combobox options loaded', async () => { + const options = await comboBox.getOptions('metricsIndexPatternFieldsSelect'); + log.debug(`-- optionsCount=${options.length}`); + return options.length > 0; + }); + } + public async selectIndexPatternTimeField(timeField: string) { await retry.try(async () => { await comboBox.clearInputField('metricsIndexPatternFieldsSelect'); diff --git a/test/functional/page_objects/visualize_page.ts b/test/functional/page_objects/visualize_page.ts index 92692767b096d..9619c81370cd8 100644 --- a/test/functional/page_objects/visualize_page.ts +++ b/test/functional/page_objects/visualize_page.ts @@ -70,6 +70,7 @@ export function VisualizePageProvider({ getService, getPageObjects }: FtrProvide public async navigateToNewVisualization() { await common.navigateToApp('visualize'); + await header.waitUntilLoadingHasFinished(); await this.clickNewVisualization(); await this.waitForVisualizationSelectPage(); } @@ -362,6 +363,20 @@ export function VisualizePageProvider({ getService, getPageObjects }: FtrProvide await header.waitUntilLoadingHasFinished(); await testSubjects.missingOrFail('visualizesaveAndReturnButton'); } + + public async cancelAndReturn(showConfirmModal: boolean) { + await header.waitUntilLoadingHasFinished(); + await testSubjects.existOrFail('visualizeCancelAndReturnButton'); + await testSubjects.click('visualizeCancelAndReturnButton'); + if (showConfirmModal) { + await retry.waitFor( + 'confirm modal to show', + async () => await testSubjects.exists('appLeaveConfirmModal') + ); + await testSubjects.exists('confirmModalConfirmButton'); + await testSubjects.click('confirmModalConfirmButton'); + } + } } return new VisualizePage(); diff --git a/test/functional/services/combo_box.ts b/test/functional/services/combo_box.ts index ac7a40361d065..57e1857989950 100644 --- a/test/functional/services/combo_box.ts +++ b/test/functional/services/combo_box.ts @@ -58,6 +58,17 @@ export function ComboBoxProvider({ getService, getPageObjects }: FtrProviderCont return isMouseClick ? await element.clickMouseButton() : await element._webElement.click(); } + /** + * Finds combobox element options + * + * @param comboBoxSelector data-test-subj selector + */ + public async getOptions(comboBoxSelector: string) { + const comboBoxElement = await testSubjects.find(comboBoxSelector); + await this.openOptionsList(comboBoxElement); + return await find.allByCssSelector('.euiFilterSelectItem', WAIT_FOR_EXISTS_TIME); + } + /** * Sets value for specified combobox element * diff --git a/test/functional/services/common/browser.ts b/test/functional/services/common/browser.ts index daf1659f0cfe1..f5fb54c72177f 100644 --- a/test/functional/services/common/browser.ts +++ b/test/functional/services/common/browser.ts @@ -474,6 +474,10 @@ export async function BrowserProvider({ getService }: FtrProviderContext) { return parseInt(scrollSize, 10); } + public async scrollTop() { + await driver.executeScript('document.documentElement.scrollTop = 0'); + } + // return promise with REAL scroll position public async setScrollTop(scrollSize: number | string) { await driver.executeScript('document.body.scrollTop = ' + scrollSize); diff --git a/test/functional/services/common/failure_debugging.ts b/test/functional/services/common/failure_debugging.ts index aa67c455e0100..8b0e095b71ff8 100644 --- a/test/functional/services/common/failure_debugging.ts +++ b/test/functional/services/common/failure_debugging.ts @@ -38,7 +38,7 @@ export async function FailureDebuggingProvider({ getService }: FtrProviderContex const log = getService('log'); const browser = getService('browser'); - if (process.env.CI !== 'true') { + if (process.env.CI !== 'true' && !process.env.stack_functional_integration) { await del(config.get('failureDebugging.htmlDirectory')); } diff --git a/test/functional/services/common/screenshots.ts b/test/functional/services/common/screenshots.ts index daa55240f3eb7..5bce0d4cf6c87 100644 --- a/test/functional/services/common/screenshots.ts +++ b/test/functional/services/common/screenshots.ts @@ -40,7 +40,7 @@ export async function ScreenshotsProvider({ getService }: FtrProviderContext) { const FAILURE_DIRECTORY = resolve(config.get('screenshots.directory'), 'failure'); const BASELINE_DIRECTORY = resolve(config.get('screenshots.directory'), 'baseline'); - if (process.env.CI !== 'true') { + if (process.env.CI !== 'true' && !process.env.stack_functional_integration) { await del([SESSION_DIRECTORY, FAILURE_DIRECTORY]); } diff --git a/test/functional/services/common/snapshots.ts b/test/functional/services/common/snapshots.ts index 2e0b360e594e5..03eadff82e31f 100644 --- a/test/functional/services/common/snapshots.ts +++ b/test/functional/services/common/snapshots.ts @@ -35,7 +35,7 @@ export async function SnapshotsProvider({ getService }: FtrProviderContext) { const SESSION_DIRECTORY = resolve(config.get('snapshots.directory'), 'session'); const BASELINE_DIRECTORY = resolve(config.get('snapshots.directory'), 'baseline'); - if (process.env.CI !== 'true') { + if (process.env.CI !== 'true' && !process.env.stack_functional_integration) { await del([SESSION_DIRECTORY]); } diff --git a/test/functional/services/dashboard/panel_actions.ts b/test/functional/services/dashboard/panel_actions.ts index bc21a62b9df79..2cea377d327e1 100644 --- a/test/functional/services/dashboard/panel_actions.ts +++ b/test/functional/services/dashboard/panel_actions.ts @@ -59,12 +59,32 @@ export function DashboardPanelActionsProvider({ getService, getPageObjects }: Ft async openContextMenu(parent?: WebElementWrapper) { log.debug(`openContextMenu(${parent}`); + if (await testSubjects.exists('embeddablePanelContextMenuOpen')) return; await this.toggleContextMenu(parent); await this.expectContextMenuToBeOpen(); } + async hasContextMenuMoreItem() { + return await testSubjects.exists('embeddablePanelMore-mainMenu'); + } + + async clickContextMenuMoreItem() { + const hasMoreSubPanel = await testSubjects.exists('embeddablePanelMore-mainMenu'); + if (hasMoreSubPanel) { + await testSubjects.click('embeddablePanelMore-mainMenu'); + } + } + + async openContextMenuMorePanel(parent?: WebElementWrapper) { + await this.openContextMenu(parent); + await this.clickContextMenuMoreItem(); + } + async clickEdit() { log.debug('clickEdit'); + await this.openContextMenu(); + const isActionVisible = await testSubjects.exists(EDIT_PANEL_DATA_TEST_SUBJ); + if (!isActionVisible) await this.clickContextMenuMoreItem(); await testSubjects.clickWhenNotDisabled(EDIT_PANEL_DATA_TEST_SUBJ); await PageObjects.header.waitUntilLoadingHasFinished(); await PageObjects.common.waitForTopNavToBeVisible(); @@ -82,18 +102,28 @@ export function DashboardPanelActionsProvider({ getService, getPageObjects }: Ft } async clickExpandPanelToggle() { + log.debug(`clickExpandPanelToggle`); + this.openContextMenu(); + const isActionVisible = await testSubjects.exists(TOGGLE_EXPAND_PANEL_DATA_TEST_SUBJ); + if (!isActionVisible) await this.clickContextMenuMoreItem(); await testSubjects.click(TOGGLE_EXPAND_PANEL_DATA_TEST_SUBJ); } async removePanel() { log.debug('removePanel'); await this.openContextMenu(); + const isActionVisible = await testSubjects.exists(REMOVE_PANEL_DATA_TEST_SUBJ); + if (!isActionVisible) await this.clickContextMenuMoreItem(); + const isPanelActionVisible = await testSubjects.exists(REMOVE_PANEL_DATA_TEST_SUBJ); + if (!isPanelActionVisible) await this.clickContextMenuMoreItem(); await testSubjects.click(REMOVE_PANEL_DATA_TEST_SUBJ); } async removePanelByTitle(title: string) { const header = await this.getPanelHeading(title); await this.openContextMenu(header); + const isActionVisible = await testSubjects.exists(REMOVE_PANEL_DATA_TEST_SUBJ); + if (!isActionVisible) await this.clickContextMenuMoreItem(); await testSubjects.click(REMOVE_PANEL_DATA_TEST_SUBJ); } @@ -110,6 +140,10 @@ export function DashboardPanelActionsProvider({ getService, getPageObjects }: Ft } else { await this.openContextMenu(); } + const actionExists = await testSubjects.exists(REPLACE_PANEL_DATA_TEST_SUBJ); + if (!actionExists) { + await this.clickContextMenuMoreItem(); + } await testSubjects.click(REPLACE_PANEL_DATA_TEST_SUBJ); } @@ -131,52 +165,78 @@ export function DashboardPanelActionsProvider({ getService, getPageObjects }: Ft async openInspector(parent: WebElementWrapper) { await this.openContextMenu(parent); + const exists = await testSubjects.exists(OPEN_INSPECTOR_TEST_SUBJ); + if (!exists) { + await this.clickContextMenuMoreItem(); + } await testSubjects.click(OPEN_INSPECTOR_TEST_SUBJ); } async expectExistsRemovePanelAction() { log.debug('expectExistsRemovePanelAction'); - await testSubjects.existOrFail(REMOVE_PANEL_DATA_TEST_SUBJ); + await this.expectExistsPanelAction(REMOVE_PANEL_DATA_TEST_SUBJ); } - async expectMissingRemovePanelAction() { - log.debug('expectMissingRemovePanelAction'); - await testSubjects.missingOrFail(REMOVE_PANEL_DATA_TEST_SUBJ); + async expectExistsPanelAction(testSubject: string) { + log.debug('expectExistsPanelAction', testSubject); + await this.openContextMenu(); + if (await testSubjects.exists(CLONE_PANEL_DATA_TEST_SUBJ)) return; + if (await this.hasContextMenuMoreItem()) { + await this.clickContextMenuMoreItem(); + } + await testSubjects.existOrFail(CLONE_PANEL_DATA_TEST_SUBJ); + await this.toggleContextMenu(); + } + + async expectMissingPanelAction(testSubject: string) { + log.debug('expectMissingPanelAction', testSubject); + await this.openContextMenu(); + await testSubjects.missingOrFail(testSubject); + if (await this.hasContextMenuMoreItem()) { + await this.clickContextMenuMoreItem(); + await testSubjects.missingOrFail(testSubject); + } + await this.toggleContextMenu(); } async expectExistsEditPanelAction() { log.debug('expectExistsEditPanelAction'); - await testSubjects.existOrFail(EDIT_PANEL_DATA_TEST_SUBJ); + await this.expectExistsPanelAction(EDIT_PANEL_DATA_TEST_SUBJ); } async expectExistsReplacePanelAction() { log.debug('expectExistsReplacePanelAction'); - await testSubjects.existOrFail(REPLACE_PANEL_DATA_TEST_SUBJ); + await this.expectExistsPanelAction(REPLACE_PANEL_DATA_TEST_SUBJ); } - async expectExistsDuplicatePanelAction() { - log.debug('expectExistsDuplicatePanelAction'); - await testSubjects.existOrFail(REPLACE_PANEL_DATA_TEST_SUBJ); + async expectExistsClonePanelAction() { + log.debug('expectExistsClonePanelAction'); + await this.expectExistsPanelAction(CLONE_PANEL_DATA_TEST_SUBJ); } async expectMissingEditPanelAction() { log.debug('expectMissingEditPanelAction'); - await testSubjects.missingOrFail(EDIT_PANEL_DATA_TEST_SUBJ); + await this.expectMissingPanelAction(EDIT_PANEL_DATA_TEST_SUBJ); } async expectMissingReplacePanelAction() { log.debug('expectMissingReplacePanelAction'); - await testSubjects.missingOrFail(REPLACE_PANEL_DATA_TEST_SUBJ); + await this.expectMissingPanelAction(REPLACE_PANEL_DATA_TEST_SUBJ); } async expectMissingDuplicatePanelAction() { log.debug('expectMissingDuplicatePanelAction'); - await testSubjects.missingOrFail(REPLACE_PANEL_DATA_TEST_SUBJ); + await this.expectMissingPanelAction(CLONE_PANEL_DATA_TEST_SUBJ); + } + + async expectMissingRemovePanelAction() { + log.debug('expectMissingRemovePanelAction'); + await this.expectMissingPanelAction(REMOVE_PANEL_DATA_TEST_SUBJ); } async expectExistsToggleExpandAction() { log.debug('expectExistsToggleExpandAction'); - await testSubjects.existOrFail(TOGGLE_EXPAND_PANEL_DATA_TEST_SUBJ); + await this.expectExistsPanelAction(TOGGLE_EXPAND_PANEL_DATA_TEST_SUBJ); } async getPanelHeading(title: string) { diff --git a/test/functional/services/dashboard/replace_panel.ts b/test/functional/services/dashboard/replace_panel.ts index d1cb4e5e697a1..2abc9cf23b72e 100644 --- a/test/functional/services/dashboard/replace_panel.ts +++ b/test/functional/services/dashboard/replace_panel.ts @@ -73,7 +73,7 @@ export function DashboardReplacePanelProvider({ getService }: FtrProviderContext return this.replaceEmbeddable(vizName, 'visualization'); } - async replaceEmbeddable(embeddableName: string, embeddableType: string) { + async replaceEmbeddable(embeddableName: string, embeddableType?: string) { log.debug( `DashboardReplacePanel.replaceEmbeddable, name: ${embeddableName}, type: ${embeddableType}` ); diff --git a/test/functional/services/query_bar.ts b/test/functional/services/query_bar.ts index 8cd63fb2f4a51..3b4645bc42821 100644 --- a/test/functional/services/query_bar.ts +++ b/test/functional/services/query_bar.ts @@ -87,6 +87,11 @@ export function QueryBarProvider({ getService, getPageObjects }: FtrProviderCont const queryLanguageButton = await testSubjects.find('switchQueryLanguageButton'); expect((await queryLanguageButton.getVisibleText()).toLowerCase()).to.eql(lang); } + + public async getSuggestions() { + const suggestions = await testSubjects.findAll('autoCompleteSuggestionText'); + return Promise.all(suggestions.map((suggestion) => suggestion.getVisibleText())); + } } return new QueryBar(); diff --git a/test/functional/services/toasts.ts b/test/functional/services/toasts.ts index a70e4ba464ae8..f5416a44e3b5a 100644 --- a/test/functional/services/toasts.ts +++ b/test/functional/services/toasts.ts @@ -63,7 +63,7 @@ export function ToastsProvider({ getService }: FtrProviderContext) { } } - private async getToastElement(index: number) { + public async getToastElement(index: number) { const list = await this.getGlobalToastList(); return await list.findByCssSelector(`.euiToast:nth-child(${index})`); } diff --git a/test/interpreter_functional/plugins/kbn_tp_run_pipeline/package.json b/test/interpreter_functional/plugins/kbn_tp_run_pipeline/package.json index ace6a48ed8ff5..0d6d0286c5a8f 100644 --- a/test/interpreter_functional/plugins/kbn_tp_run_pipeline/package.json +++ b/test/interpreter_functional/plugins/kbn_tp_run_pipeline/package.json @@ -12,7 +12,7 @@ "build": "rm -rf './target' && tsc" }, "devDependencies": { - "@elastic/eui": "28.4.0", + "@elastic/eui": "29.3.0", "@kbn/plugin-helpers": "1.0.0", "react": "^16.12.0", "react-dom": "^16.12.0", diff --git a/test/interpreter_functional/snapshots/baseline/partial_test_1.json b/test/interpreter_functional/snapshots/baseline/partial_test_1.json index 6b2f93b47c0b2..9c642e5e266d0 100644 --- a/test/interpreter_functional/snapshots/baseline/partial_test_1.json +++ b/test/interpreter_functional/snapshots/baseline/partial_test_1.json @@ -1 +1 @@ -{"as":"visualization","type":"render","value":{"params":{"listenOnChange":true},"visConfig":{"bucket":{"accessor":0,"format":{"id":"string","params":{}},"type":"vis_dimension"},"maxFontSize":72,"metric":{"accessor":1,"format":{"id":"number","params":{}},"type":"vis_dimension"},"minFontSize":18,"orientation":"single","scale":"linear","showLabel":true},"visData":{"columns":[{"id":"col-0-2","meta":{"aggConfigParams":{"field":"response.raw","missingBucket":false,"missingBucketLabel":"Missing","order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","size":4},"indexPatternId":"logstash-*","type":"terms"},"name":"response.raw: Descending"},{"id":"col-1-1","meta":{"aggConfigParams":{},"indexPatternId":"logstash-*","type":"count"},"name":"Count"}],"rows":[{"col-0-2":"200","col-1-1":12891},{"col-0-2":"404","col-1-1":696},{"col-0-2":"503","col-1-1":417}],"type":"kibana_datatable"},"visType":"tagcloud"}} \ No newline at end of file +{"as":"tagloud_vis","type":"render","value":{"visData":{"columns":[{"id":"col-0-2","meta":{"aggConfigParams":{"field":"response.raw","missingBucket":false,"missingBucketLabel":"Missing","order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","size":4},"indexPatternId":"logstash-*","type":"terms"},"name":"response.raw: Descending"},{"id":"col-1-1","meta":{"aggConfigParams":{},"indexPatternId":"logstash-*","type":"count"},"name":"Count"}],"rows":[{"col-0-2":"200","col-1-1":12891},{"col-0-2":"404","col-1-1":696},{"col-0-2":"503","col-1-1":417}],"type":"kibana_datatable"},"visParams":{"bucket":{"accessor":0,"format":{"id":"string","params":{}},"type":"vis_dimension"},"maxFontSize":72,"metric":{"accessor":1,"format":{"id":"number","params":{}},"type":"vis_dimension"},"minFontSize":18,"orientation":"single","scale":"linear","showLabel":true},"visType":"tagcloud"}} \ No newline at end of file diff --git a/test/interpreter_functional/snapshots/baseline/tagcloud_all_data.json b/test/interpreter_functional/snapshots/baseline/tagcloud_all_data.json index ae1e817424cb1..153eea71dd8d1 100644 --- a/test/interpreter_functional/snapshots/baseline/tagcloud_all_data.json +++ b/test/interpreter_functional/snapshots/baseline/tagcloud_all_data.json @@ -1 +1 @@ -{"as":"visualization","type":"render","value":{"params":{"listenOnChange":true},"visConfig":{"bucket":{"accessor":1,"format":{"id":"string","params":{}},"type":"vis_dimension"},"maxFontSize":72,"metric":{"accessor":0,"format":{"id":"string","params":{}},"type":"vis_dimension"},"minFontSize":18,"orientation":"single","scale":"linear","showLabel":true},"visData":{"columns":[{"id":"col-0-2","meta":{"aggConfigParams":{"field":"response.raw","missingBucket":false,"missingBucketLabel":"Missing","order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","size":4},"indexPatternId":"logstash-*","type":"terms"},"name":"response.raw: Descending"},{"id":"col-1-1","meta":{"aggConfigParams":{},"indexPatternId":"logstash-*","type":"count"},"name":"Count"}],"rows":[{"col-0-2":"200","col-1-1":12891},{"col-0-2":"404","col-1-1":696},{"col-0-2":"503","col-1-1":417}],"type":"kibana_datatable"},"visType":"tagcloud"}} \ No newline at end of file +{"as":"tagloud_vis","type":"render","value":{"visData":{"columns":[{"id":"col-0-2","meta":{"aggConfigParams":{"field":"response.raw","missingBucket":false,"missingBucketLabel":"Missing","order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","size":4},"indexPatternId":"logstash-*","type":"terms"},"name":"response.raw: Descending"},{"id":"col-1-1","meta":{"aggConfigParams":{},"indexPatternId":"logstash-*","type":"count"},"name":"Count"}],"rows":[{"col-0-2":"200","col-1-1":12891},{"col-0-2":"404","col-1-1":696},{"col-0-2":"503","col-1-1":417}],"type":"kibana_datatable"},"visParams":{"bucket":{"accessor":1,"format":{"id":"string","params":{}},"type":"vis_dimension"},"maxFontSize":72,"metric":{"accessor":0,"format":{"id":"string","params":{}},"type":"vis_dimension"},"minFontSize":18,"orientation":"single","scale":"linear","showLabel":true},"visType":"tagcloud"}} \ No newline at end of file diff --git a/test/interpreter_functional/snapshots/baseline/tagcloud_fontsize.json b/test/interpreter_functional/snapshots/baseline/tagcloud_fontsize.json index c0da479472880..d5f01afa468ab 100644 --- a/test/interpreter_functional/snapshots/baseline/tagcloud_fontsize.json +++ b/test/interpreter_functional/snapshots/baseline/tagcloud_fontsize.json @@ -1 +1 @@ -{"as":"visualization","type":"render","value":{"params":{"listenOnChange":true},"visConfig":{"bucket":{"accessor":1,"format":{"id":"string","params":{}},"type":"vis_dimension"},"maxFontSize":40,"metric":{"accessor":0,"format":{"id":"string","params":{}},"type":"vis_dimension"},"minFontSize":20,"orientation":"single","scale":"linear","showLabel":true},"visData":{"columns":[{"id":"col-0-2","meta":{"aggConfigParams":{"field":"response.raw","missingBucket":false,"missingBucketLabel":"Missing","order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","size":4},"indexPatternId":"logstash-*","type":"terms"},"name":"response.raw: Descending"},{"id":"col-1-1","meta":{"aggConfigParams":{},"indexPatternId":"logstash-*","type":"count"},"name":"Count"}],"rows":[{"col-0-2":"200","col-1-1":12891},{"col-0-2":"404","col-1-1":696},{"col-0-2":"503","col-1-1":417}],"type":"kibana_datatable"},"visType":"tagcloud"}} \ No newline at end of file +{"as":"tagloud_vis","type":"render","value":{"visData":{"columns":[{"id":"col-0-2","meta":{"aggConfigParams":{"field":"response.raw","missingBucket":false,"missingBucketLabel":"Missing","order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","size":4},"indexPatternId":"logstash-*","type":"terms"},"name":"response.raw: Descending"},{"id":"col-1-1","meta":{"aggConfigParams":{},"indexPatternId":"logstash-*","type":"count"},"name":"Count"}],"rows":[{"col-0-2":"200","col-1-1":12891},{"col-0-2":"404","col-1-1":696},{"col-0-2":"503","col-1-1":417}],"type":"kibana_datatable"},"visParams":{"bucket":{"accessor":1,"format":{"id":"string","params":{}},"type":"vis_dimension"},"maxFontSize":40,"metric":{"accessor":0,"format":{"id":"string","params":{}},"type":"vis_dimension"},"minFontSize":20,"orientation":"single","scale":"linear","showLabel":true},"visType":"tagcloud"}} \ No newline at end of file diff --git a/test/interpreter_functional/snapshots/baseline/tagcloud_metric_data.json b/test/interpreter_functional/snapshots/baseline/tagcloud_metric_data.json index c5fbcd63b0685..72b5e957c19a5 100644 --- a/test/interpreter_functional/snapshots/baseline/tagcloud_metric_data.json +++ b/test/interpreter_functional/snapshots/baseline/tagcloud_metric_data.json @@ -1 +1 @@ -{"as":"visualization","type":"render","value":{"params":{"listenOnChange":true},"visConfig":{"maxFontSize":72,"metric":{"accessor":0,"format":{"id":"string","params":{}},"type":"vis_dimension"},"minFontSize":18,"orientation":"single","scale":"linear","showLabel":true},"visData":{"columns":[{"id":"col-0-2","meta":{"aggConfigParams":{"field":"response.raw","missingBucket":false,"missingBucketLabel":"Missing","order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","size":4},"indexPatternId":"logstash-*","type":"terms"},"name":"response.raw: Descending"},{"id":"col-1-1","meta":{"aggConfigParams":{},"indexPatternId":"logstash-*","type":"count"},"name":"Count"}],"rows":[{"col-0-2":"200","col-1-1":12891},{"col-0-2":"404","col-1-1":696},{"col-0-2":"503","col-1-1":417}],"type":"kibana_datatable"},"visType":"tagcloud"}} \ No newline at end of file +{"as":"tagloud_vis","type":"render","value":{"visData":{"columns":[{"id":"col-0-2","meta":{"aggConfigParams":{"field":"response.raw","missingBucket":false,"missingBucketLabel":"Missing","order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","size":4},"indexPatternId":"logstash-*","type":"terms"},"name":"response.raw: Descending"},{"id":"col-1-1","meta":{"aggConfigParams":{},"indexPatternId":"logstash-*","type":"count"},"name":"Count"}],"rows":[{"col-0-2":"200","col-1-1":12891},{"col-0-2":"404","col-1-1":696},{"col-0-2":"503","col-1-1":417}],"type":"kibana_datatable"},"visParams":{"maxFontSize":72,"metric":{"accessor":0,"format":{"id":"string","params":{}},"type":"vis_dimension"},"minFontSize":18,"orientation":"single","scale":"linear","showLabel":true},"visType":"tagcloud"}} \ No newline at end of file diff --git a/test/interpreter_functional/snapshots/baseline/tagcloud_options.json b/test/interpreter_functional/snapshots/baseline/tagcloud_options.json index b67b074449403..7cbe7cc79882f 100644 --- a/test/interpreter_functional/snapshots/baseline/tagcloud_options.json +++ b/test/interpreter_functional/snapshots/baseline/tagcloud_options.json @@ -1 +1 @@ -{"as":"visualization","type":"render","value":{"params":{"listenOnChange":true},"visConfig":{"bucket":{"accessor":1,"format":{"id":"string","params":{}},"type":"vis_dimension"},"maxFontSize":72,"metric":{"accessor":0,"format":{"id":"string","params":{}},"type":"vis_dimension"},"minFontSize":18,"orientation":"multiple","scale":"log","showLabel":true},"visData":{"columns":[{"id":"col-0-2","meta":{"aggConfigParams":{"field":"response.raw","missingBucket":false,"missingBucketLabel":"Missing","order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","size":4},"indexPatternId":"logstash-*","type":"terms"},"name":"response.raw: Descending"},{"id":"col-1-1","meta":{"aggConfigParams":{},"indexPatternId":"logstash-*","type":"count"},"name":"Count"}],"rows":[{"col-0-2":"200","col-1-1":12891},{"col-0-2":"404","col-1-1":696},{"col-0-2":"503","col-1-1":417}],"type":"kibana_datatable"},"visType":"tagcloud"}} \ No newline at end of file +{"as":"tagloud_vis","type":"render","value":{"visData":{"columns":[{"id":"col-0-2","meta":{"aggConfigParams":{"field":"response.raw","missingBucket":false,"missingBucketLabel":"Missing","order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","size":4},"indexPatternId":"logstash-*","type":"terms"},"name":"response.raw: Descending"},{"id":"col-1-1","meta":{"aggConfigParams":{},"indexPatternId":"logstash-*","type":"count"},"name":"Count"}],"rows":[{"col-0-2":"200","col-1-1":12891},{"col-0-2":"404","col-1-1":696},{"col-0-2":"503","col-1-1":417}],"type":"kibana_datatable"},"visParams":{"bucket":{"accessor":1,"format":{"id":"string","params":{}},"type":"vis_dimension"},"maxFontSize":72,"metric":{"accessor":0,"format":{"id":"string","params":{}},"type":"vis_dimension"},"minFontSize":18,"orientation":"multiple","scale":"log","showLabel":true},"visType":"tagcloud"}} \ No newline at end of file diff --git a/test/interpreter_functional/snapshots/session/partial_test_1.json b/test/interpreter_functional/snapshots/session/partial_test_1.json index 6b2f93b47c0b2..9c642e5e266d0 100644 --- a/test/interpreter_functional/snapshots/session/partial_test_1.json +++ b/test/interpreter_functional/snapshots/session/partial_test_1.json @@ -1 +1 @@ -{"as":"visualization","type":"render","value":{"params":{"listenOnChange":true},"visConfig":{"bucket":{"accessor":0,"format":{"id":"string","params":{}},"type":"vis_dimension"},"maxFontSize":72,"metric":{"accessor":1,"format":{"id":"number","params":{}},"type":"vis_dimension"},"minFontSize":18,"orientation":"single","scale":"linear","showLabel":true},"visData":{"columns":[{"id":"col-0-2","meta":{"aggConfigParams":{"field":"response.raw","missingBucket":false,"missingBucketLabel":"Missing","order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","size":4},"indexPatternId":"logstash-*","type":"terms"},"name":"response.raw: Descending"},{"id":"col-1-1","meta":{"aggConfigParams":{},"indexPatternId":"logstash-*","type":"count"},"name":"Count"}],"rows":[{"col-0-2":"200","col-1-1":12891},{"col-0-2":"404","col-1-1":696},{"col-0-2":"503","col-1-1":417}],"type":"kibana_datatable"},"visType":"tagcloud"}} \ No newline at end of file +{"as":"tagloud_vis","type":"render","value":{"visData":{"columns":[{"id":"col-0-2","meta":{"aggConfigParams":{"field":"response.raw","missingBucket":false,"missingBucketLabel":"Missing","order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","size":4},"indexPatternId":"logstash-*","type":"terms"},"name":"response.raw: Descending"},{"id":"col-1-1","meta":{"aggConfigParams":{},"indexPatternId":"logstash-*","type":"count"},"name":"Count"}],"rows":[{"col-0-2":"200","col-1-1":12891},{"col-0-2":"404","col-1-1":696},{"col-0-2":"503","col-1-1":417}],"type":"kibana_datatable"},"visParams":{"bucket":{"accessor":0,"format":{"id":"string","params":{}},"type":"vis_dimension"},"maxFontSize":72,"metric":{"accessor":1,"format":{"id":"number","params":{}},"type":"vis_dimension"},"minFontSize":18,"orientation":"single","scale":"linear","showLabel":true},"visType":"tagcloud"}} \ No newline at end of file diff --git a/test/interpreter_functional/snapshots/session/tagcloud_all_data.json b/test/interpreter_functional/snapshots/session/tagcloud_all_data.json index ae1e817424cb1..153eea71dd8d1 100644 --- a/test/interpreter_functional/snapshots/session/tagcloud_all_data.json +++ b/test/interpreter_functional/snapshots/session/tagcloud_all_data.json @@ -1 +1 @@ -{"as":"visualization","type":"render","value":{"params":{"listenOnChange":true},"visConfig":{"bucket":{"accessor":1,"format":{"id":"string","params":{}},"type":"vis_dimension"},"maxFontSize":72,"metric":{"accessor":0,"format":{"id":"string","params":{}},"type":"vis_dimension"},"minFontSize":18,"orientation":"single","scale":"linear","showLabel":true},"visData":{"columns":[{"id":"col-0-2","meta":{"aggConfigParams":{"field":"response.raw","missingBucket":false,"missingBucketLabel":"Missing","order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","size":4},"indexPatternId":"logstash-*","type":"terms"},"name":"response.raw: Descending"},{"id":"col-1-1","meta":{"aggConfigParams":{},"indexPatternId":"logstash-*","type":"count"},"name":"Count"}],"rows":[{"col-0-2":"200","col-1-1":12891},{"col-0-2":"404","col-1-1":696},{"col-0-2":"503","col-1-1":417}],"type":"kibana_datatable"},"visType":"tagcloud"}} \ No newline at end of file +{"as":"tagloud_vis","type":"render","value":{"visData":{"columns":[{"id":"col-0-2","meta":{"aggConfigParams":{"field":"response.raw","missingBucket":false,"missingBucketLabel":"Missing","order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","size":4},"indexPatternId":"logstash-*","type":"terms"},"name":"response.raw: Descending"},{"id":"col-1-1","meta":{"aggConfigParams":{},"indexPatternId":"logstash-*","type":"count"},"name":"Count"}],"rows":[{"col-0-2":"200","col-1-1":12891},{"col-0-2":"404","col-1-1":696},{"col-0-2":"503","col-1-1":417}],"type":"kibana_datatable"},"visParams":{"bucket":{"accessor":1,"format":{"id":"string","params":{}},"type":"vis_dimension"},"maxFontSize":72,"metric":{"accessor":0,"format":{"id":"string","params":{}},"type":"vis_dimension"},"minFontSize":18,"orientation":"single","scale":"linear","showLabel":true},"visType":"tagcloud"}} \ No newline at end of file diff --git a/test/interpreter_functional/snapshots/session/tagcloud_fontsize.json b/test/interpreter_functional/snapshots/session/tagcloud_fontsize.json index c0da479472880..d5f01afa468ab 100644 --- a/test/interpreter_functional/snapshots/session/tagcloud_fontsize.json +++ b/test/interpreter_functional/snapshots/session/tagcloud_fontsize.json @@ -1 +1 @@ -{"as":"visualization","type":"render","value":{"params":{"listenOnChange":true},"visConfig":{"bucket":{"accessor":1,"format":{"id":"string","params":{}},"type":"vis_dimension"},"maxFontSize":40,"metric":{"accessor":0,"format":{"id":"string","params":{}},"type":"vis_dimension"},"minFontSize":20,"orientation":"single","scale":"linear","showLabel":true},"visData":{"columns":[{"id":"col-0-2","meta":{"aggConfigParams":{"field":"response.raw","missingBucket":false,"missingBucketLabel":"Missing","order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","size":4},"indexPatternId":"logstash-*","type":"terms"},"name":"response.raw: Descending"},{"id":"col-1-1","meta":{"aggConfigParams":{},"indexPatternId":"logstash-*","type":"count"},"name":"Count"}],"rows":[{"col-0-2":"200","col-1-1":12891},{"col-0-2":"404","col-1-1":696},{"col-0-2":"503","col-1-1":417}],"type":"kibana_datatable"},"visType":"tagcloud"}} \ No newline at end of file +{"as":"tagloud_vis","type":"render","value":{"visData":{"columns":[{"id":"col-0-2","meta":{"aggConfigParams":{"field":"response.raw","missingBucket":false,"missingBucketLabel":"Missing","order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","size":4},"indexPatternId":"logstash-*","type":"terms"},"name":"response.raw: Descending"},{"id":"col-1-1","meta":{"aggConfigParams":{},"indexPatternId":"logstash-*","type":"count"},"name":"Count"}],"rows":[{"col-0-2":"200","col-1-1":12891},{"col-0-2":"404","col-1-1":696},{"col-0-2":"503","col-1-1":417}],"type":"kibana_datatable"},"visParams":{"bucket":{"accessor":1,"format":{"id":"string","params":{}},"type":"vis_dimension"},"maxFontSize":40,"metric":{"accessor":0,"format":{"id":"string","params":{}},"type":"vis_dimension"},"minFontSize":20,"orientation":"single","scale":"linear","showLabel":true},"visType":"tagcloud"}} \ No newline at end of file diff --git a/test/interpreter_functional/snapshots/session/tagcloud_metric_data.json b/test/interpreter_functional/snapshots/session/tagcloud_metric_data.json index c5fbcd63b0685..72b5e957c19a5 100644 --- a/test/interpreter_functional/snapshots/session/tagcloud_metric_data.json +++ b/test/interpreter_functional/snapshots/session/tagcloud_metric_data.json @@ -1 +1 @@ -{"as":"visualization","type":"render","value":{"params":{"listenOnChange":true},"visConfig":{"maxFontSize":72,"metric":{"accessor":0,"format":{"id":"string","params":{}},"type":"vis_dimension"},"minFontSize":18,"orientation":"single","scale":"linear","showLabel":true},"visData":{"columns":[{"id":"col-0-2","meta":{"aggConfigParams":{"field":"response.raw","missingBucket":false,"missingBucketLabel":"Missing","order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","size":4},"indexPatternId":"logstash-*","type":"terms"},"name":"response.raw: Descending"},{"id":"col-1-1","meta":{"aggConfigParams":{},"indexPatternId":"logstash-*","type":"count"},"name":"Count"}],"rows":[{"col-0-2":"200","col-1-1":12891},{"col-0-2":"404","col-1-1":696},{"col-0-2":"503","col-1-1":417}],"type":"kibana_datatable"},"visType":"tagcloud"}} \ No newline at end of file +{"as":"tagloud_vis","type":"render","value":{"visData":{"columns":[{"id":"col-0-2","meta":{"aggConfigParams":{"field":"response.raw","missingBucket":false,"missingBucketLabel":"Missing","order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","size":4},"indexPatternId":"logstash-*","type":"terms"},"name":"response.raw: Descending"},{"id":"col-1-1","meta":{"aggConfigParams":{},"indexPatternId":"logstash-*","type":"count"},"name":"Count"}],"rows":[{"col-0-2":"200","col-1-1":12891},{"col-0-2":"404","col-1-1":696},{"col-0-2":"503","col-1-1":417}],"type":"kibana_datatable"},"visParams":{"maxFontSize":72,"metric":{"accessor":0,"format":{"id":"string","params":{}},"type":"vis_dimension"},"minFontSize":18,"orientation":"single","scale":"linear","showLabel":true},"visType":"tagcloud"}} \ No newline at end of file diff --git a/test/interpreter_functional/snapshots/session/tagcloud_options.json b/test/interpreter_functional/snapshots/session/tagcloud_options.json index b67b074449403..7cbe7cc79882f 100644 --- a/test/interpreter_functional/snapshots/session/tagcloud_options.json +++ b/test/interpreter_functional/snapshots/session/tagcloud_options.json @@ -1 +1 @@ -{"as":"visualization","type":"render","value":{"params":{"listenOnChange":true},"visConfig":{"bucket":{"accessor":1,"format":{"id":"string","params":{}},"type":"vis_dimension"},"maxFontSize":72,"metric":{"accessor":0,"format":{"id":"string","params":{}},"type":"vis_dimension"},"minFontSize":18,"orientation":"multiple","scale":"log","showLabel":true},"visData":{"columns":[{"id":"col-0-2","meta":{"aggConfigParams":{"field":"response.raw","missingBucket":false,"missingBucketLabel":"Missing","order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","size":4},"indexPatternId":"logstash-*","type":"terms"},"name":"response.raw: Descending"},{"id":"col-1-1","meta":{"aggConfigParams":{},"indexPatternId":"logstash-*","type":"count"},"name":"Count"}],"rows":[{"col-0-2":"200","col-1-1":12891},{"col-0-2":"404","col-1-1":696},{"col-0-2":"503","col-1-1":417}],"type":"kibana_datatable"},"visType":"tagcloud"}} \ No newline at end of file +{"as":"tagloud_vis","type":"render","value":{"visData":{"columns":[{"id":"col-0-2","meta":{"aggConfigParams":{"field":"response.raw","missingBucket":false,"missingBucketLabel":"Missing","order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","size":4},"indexPatternId":"logstash-*","type":"terms"},"name":"response.raw: Descending"},{"id":"col-1-1","meta":{"aggConfigParams":{},"indexPatternId":"logstash-*","type":"count"},"name":"Count"}],"rows":[{"col-0-2":"200","col-1-1":12891},{"col-0-2":"404","col-1-1":696},{"col-0-2":"503","col-1-1":417}],"type":"kibana_datatable"},"visParams":{"bucket":{"accessor":1,"format":{"id":"string","params":{}},"type":"vis_dimension"},"maxFontSize":72,"metric":{"accessor":0,"format":{"id":"string","params":{}},"type":"vis_dimension"},"minFontSize":18,"orientation":"multiple","scale":"log","showLabel":true},"visType":"tagcloud"}} \ No newline at end of file diff --git a/test/plugin_functional/plugins/data_search/kibana.json b/test/plugin_functional/plugins/data_search/kibana.json new file mode 100644 index 0000000000000..3acbe9f97d8f0 --- /dev/null +++ b/test/plugin_functional/plugins/data_search/kibana.json @@ -0,0 +1,9 @@ +{ + "id": "data_search_plugin", + "version": "0.0.1", + "kibanaVersion": "kibana", + "configPath": ["data_search_test_plugin"], + "server": true, + "ui": false, + "requiredPlugins": ["data"] +} diff --git a/test/plugin_functional/plugins/data_search/package.json b/test/plugin_functional/plugins/data_search/package.json new file mode 100644 index 0000000000000..de2bb5cfaa564 --- /dev/null +++ b/test/plugin_functional/plugins/data_search/package.json @@ -0,0 +1,15 @@ +{ + "name": "data_search_plugin", + "version": "1.0.0", + "kibana": { + "version": "kibana" + }, + "license": "Apache-2.0", + "scripts": { + "kbn": "node ../../../../scripts/kbn.js", + "build": "rm -rf './target' && tsc" + }, + "devDependencies": { + "typescript": "4.0.2" + } +} diff --git a/test/plugin_functional/plugins/data_search/server/index.ts b/test/plugin_functional/plugins/data_search/server/index.ts new file mode 100644 index 0000000000000..0dc4b0afd4f47 --- /dev/null +++ b/test/plugin_functional/plugins/data_search/server/index.ts @@ -0,0 +1,24 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { PluginInitializer } from 'src/core/server'; +import { DataSearchTestPlugin, TestPluginSetup, TestPluginStart } from './plugin'; + +export const plugin: PluginInitializer = () => + new DataSearchTestPlugin(); diff --git a/test/plugin_functional/plugins/data_search/server/plugin.ts b/test/plugin_functional/plugins/data_search/server/plugin.ts new file mode 100644 index 0000000000000..e016ef56802f3 --- /dev/null +++ b/test/plugin_functional/plugins/data_search/server/plugin.ts @@ -0,0 +1,85 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { CoreSetup, Plugin } from 'kibana/server'; +import { schema } from '@kbn/config-schema'; +import { PluginStart as DataPluginStart } from '../../../../../src/plugins/data/server'; + +export interface DataSearchTestStartDeps { + data: DataPluginStart; +} + +export class DataSearchTestPlugin + implements Plugin { + public setup(core: CoreSetup) { + const router = core.http.createRouter(); + + router.get( + { path: '/api/data_search_plugin/search_source/as_scoped', validate: false }, + async (context, req, res) => { + const [, { data }] = await core.getStartServices(); + // Just make sure `asScoped` can be called + await data.search.searchSource.asScoped(req); + return res.ok(); + } + ); + + router.get( + { path: '/api/data_search_plugin/search_source/create_empty', validate: false }, + async (context, req, res) => { + const [, { data }] = await core.getStartServices(); + const service = await data.search.searchSource.asScoped(req); + const searchSource = service.createEmpty(); + return res.ok({ body: searchSource.serialize() }); + } + ); + + router.post( + { + path: '/api/data_search_plugin/search_source/create', + validate: { + body: schema.object({}, { unknowns: 'allow' }), + }, + }, + async (context, req, res) => { + const [{ savedObjects }, { data }] = await core.getStartServices(); + const service = await data.search.searchSource.asScoped(req); + const savedObjectsClient = savedObjects.getScopedClient(req); + + // Since the index pattern ID can change on each test run, we need + // to look it up on the fly and insert it into the request. + const indexPatterns = await data.indexPatterns.indexPatternsServiceFactory( + savedObjectsClient + ); + const ids = await indexPatterns.getIds(); + // @ts-expect-error Force overwriting the request + req.body.index = ids[0]; + const searchSource = await service.create(req.body); + + return res.ok({ body: searchSource.serialize() }); + } + ); + } + + public start() {} + public stop() {} +} + +export type TestPluginSetup = ReturnType; +export type TestPluginStart = ReturnType; diff --git a/test/plugin_functional/plugins/data_search/tsconfig.json b/test/plugin_functional/plugins/data_search/tsconfig.json new file mode 100644 index 0000000000000..72793a327d97e --- /dev/null +++ b/test/plugin_functional/plugins/data_search/tsconfig.json @@ -0,0 +1,15 @@ +{ + "extends": "../../../../tsconfig.base.json", + "compilerOptions": { + "outDir": "./target", + "skipLibCheck": true + }, + "include": [ + "server/**/*.ts", + "../../../../typings/**/*" + ], + "exclude": [], + "references": [ + { "path": "../../../../src/core/tsconfig.json" } + ] +} diff --git a/test/plugin_functional/plugins/elasticsearch_client_plugin/server/plugin.ts b/test/plugin_functional/plugins/elasticsearch_client_plugin/server/plugin.ts index 5e018ca7818d3..8b6c8a99c73e8 100644 --- a/test/plugin_functional/plugins/elasticsearch_client_plugin/server/plugin.ts +++ b/test/plugin_functional/plugins/elasticsearch_client_plugin/server/plugin.ts @@ -26,7 +26,7 @@ export class ElasticsearchClientPlugin implements Plugin { { path: '/api/elasticsearch_client_plugin/context/ping', validate: false }, async (context, req, res) => { const { body } = await context.core.elasticsearch.client.asInternalUser.ping(); - return res.ok({ body }); + return res.ok({ body: JSON.stringify(body) }); } ); router.get( @@ -34,14 +34,14 @@ export class ElasticsearchClientPlugin implements Plugin { async (context, req, res) => { const [coreStart] = await core.getStartServices(); const { body } = await coreStart.elasticsearch.client.asInternalUser.ping(); - return res.ok({ body }); + return res.ok({ body: JSON.stringify(body) }); } ); router.get( { path: '/api/elasticsearch_client_plugin/custom_client/ping', validate: false }, async (context, req, res) => { const { body } = await this.client!.asInternalUser.ping(); - return res.ok({ body }); + return res.ok({ body: JSON.stringify(body) }); } ); } diff --git a/test/plugin_functional/plugins/index_patterns/server/plugin.ts b/test/plugin_functional/plugins/index_patterns/server/plugin.ts index 1c85f226623cb..a54502b740211 100644 --- a/test/plugin_functional/plugins/index_patterns/server/plugin.ts +++ b/test/plugin_functional/plugins/index_patterns/server/plugin.ts @@ -39,8 +39,9 @@ export class IndexPatternsTestPlugin router.get( { path: '/api/index-patterns-plugin/get-all', validate: false }, async (context, req, res) => { - const [, { data }] = await core.getStartServices(); - const service = await data.indexPatterns.indexPatternsServiceFactory(req); + const [{ savedObjects }, { data }] = await core.getStartServices(); + const savedObjectsClient = savedObjects.getScopedClient(req); + const service = await data.indexPatterns.indexPatternsServiceFactory(savedObjectsClient); const ids = await service.getIds(); return res.ok({ body: ids }); } @@ -57,8 +58,9 @@ export class IndexPatternsTestPlugin }, async (context, req, res) => { const id = (req.params as Record).id; - const [, { data }] = await core.getStartServices(); - const service = await data.indexPatterns.indexPatternsServiceFactory(req); + const [{ savedObjects }, { data }] = await core.getStartServices(); + const savedObjectsClient = savedObjects.getScopedClient(req); + const service = await data.indexPatterns.indexPatternsServiceFactory(savedObjectsClient); const ip = await service.get(id); return res.ok({ body: ip.toSpec() }); } @@ -74,11 +76,12 @@ export class IndexPatternsTestPlugin }, }, async (context, req, res) => { - const [, { data }] = await core.getStartServices(); + const [{ savedObjects }, { data }] = await core.getStartServices(); const id = (req.params as Record).id; - const service = await data.indexPatterns.indexPatternsServiceFactory(req); + const savedObjectsClient = savedObjects.getScopedClient(req); + const service = await data.indexPatterns.indexPatternsServiceFactory(savedObjectsClient); const ip = await service.get(id); - await service.save(ip); + await service.updateSavedObject(ip); return res.ok(); } ); @@ -93,9 +96,10 @@ export class IndexPatternsTestPlugin }, }, async (context, req, res) => { - const [, { data }] = await core.getStartServices(); + const [{ savedObjects }, { data }] = await core.getStartServices(); const id = (req.params as Record).id; - const service = await data.indexPatterns.indexPatternsServiceFactory(req); + const savedObjectsClient = savedObjects.getScopedClient(req); + const service = await data.indexPatterns.indexPatternsServiceFactory(savedObjectsClient); await service.delete(id); return res.ok(); } diff --git a/test/plugin_functional/plugins/kbn_sample_panel_action/package.json b/test/plugin_functional/plugins/kbn_sample_panel_action/package.json index d98fa468bd6d1..8efd2ee432415 100644 --- a/test/plugin_functional/plugins/kbn_sample_panel_action/package.json +++ b/test/plugin_functional/plugins/kbn_sample_panel_action/package.json @@ -12,7 +12,7 @@ "build": "rm -rf './target' && tsc" }, "devDependencies": { - "@elastic/eui": "28.4.0", + "@elastic/eui": "29.3.0", "react": "^16.12.0", "typescript": "4.0.2" } diff --git a/test/plugin_functional/plugins/kbn_tp_custom_visualizations/package.json b/test/plugin_functional/plugins/kbn_tp_custom_visualizations/package.json index 3ac03b444deaf..4405063e54c06 100644 --- a/test/plugin_functional/plugins/kbn_tp_custom_visualizations/package.json +++ b/test/plugin_functional/plugins/kbn_tp_custom_visualizations/package.json @@ -12,7 +12,7 @@ "build": "rm -rf './target' && tsc" }, "devDependencies": { - "@elastic/eui": "28.4.0", + "@elastic/eui": "29.3.0", "@kbn/plugin-helpers": "1.0.0", "react": "^16.12.0", "typescript": "4.0.2" diff --git a/test/plugin_functional/test_suites/data_plugin/index.ts b/test/plugin_functional/test_suites/data_plugin/index.ts index 1c3f118135ffa..bbf9d823e357e 100644 --- a/test/plugin_functional/test_suites/data_plugin/index.ts +++ b/test/plugin_functional/test_suites/data_plugin/index.ts @@ -17,9 +17,25 @@ * under the License. */ -// @ts-expect-error -export default function ({ loadTestFile }) { +import { PluginFunctionalProviderContext } from '../../services'; + +export default function ({ + getPageObjects, + getService, + loadTestFile, +}: PluginFunctionalProviderContext) { + const esArchiver = getService('esArchiver'); + const PageObjects = getPageObjects(['common', 'header', 'settings']); + describe('data plugin', () => { + before(async () => { + await esArchiver.loadIfNeeded( + '../functional/fixtures/es_archiver/getting_started/shakespeare' + ); + await PageObjects.common.navigateToApp('settings'); + await PageObjects.settings.createIndexPattern('shakespeare', ''); + }); loadTestFile(require.resolve('./index_patterns')); + loadTestFile(require.resolve('./search')); }); } diff --git a/test/plugin_functional/test_suites/data_plugin/index_patterns.ts b/test/plugin_functional/test_suites/data_plugin/index_patterns.ts index 2db9eb733f805..4359816efb958 100644 --- a/test/plugin_functional/test_suites/data_plugin/index_patterns.ts +++ b/test/plugin_functional/test_suites/data_plugin/index_patterns.ts @@ -20,20 +20,11 @@ import expect from '@kbn/expect'; import { PluginFunctionalProviderContext } from '../../services'; import '../../plugins/core_provider_plugin/types'; -export default function ({ getService, getPageObjects }: PluginFunctionalProviderContext) { +export default function ({ getService }: PluginFunctionalProviderContext) { const supertest = getService('supertest'); - const esArchiver = getService('esArchiver'); - const PageObjects = getPageObjects(['common', 'settings']); describe('index patterns', function () { let indexPatternId = ''; - before(async () => { - await esArchiver.loadIfNeeded( - '../functional/fixtures/es_archiver/getting_started/shakespeare' - ); - await PageObjects.common.navigateToApp('settings'); - await PageObjects.settings.createIndexPattern('shakespeare', ''); - }); it('can get all ids', async () => { const body = await (await supertest.get('/api/index-patterns-plugin/get-all').expect(200)) @@ -46,14 +37,14 @@ export default function ({ getService, getPageObjects }: PluginFunctionalProvide const body = await ( await supertest.get(`/api/index-patterns-plugin/get/${indexPatternId}`).expect(200) ).body; - expect(body.fields.length > 0).to.equal(true); + expect(typeof body.id).to.equal('string'); }); it('can update index pattern', async () => { - const body = await ( - await supertest.get(`/api/index-patterns-plugin/update/${indexPatternId}`).expect(200) - ).body; - expect(body).to.eql({}); + const resp = await supertest + .get(`/api/index-patterns-plugin/update/${indexPatternId}`) + .expect(200); + expect(resp.body).to.eql({}); }); it('can delete index pattern', async () => { diff --git a/test/plugin_functional/test_suites/data_plugin/search.ts b/test/plugin_functional/test_suites/data_plugin/search.ts new file mode 100644 index 0000000000000..730b05cdb65e9 --- /dev/null +++ b/test/plugin_functional/test_suites/data_plugin/search.ts @@ -0,0 +1,65 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import expect from '@kbn/expect'; +import { PluginFunctionalProviderContext } from '../../services'; + +export default function ({ getService }: PluginFunctionalProviderContext) { + const supertest = getService('supertest'); + + describe('data.search', () => { + describe('searchSource', () => { + const searchSourceFields = { + highlightAll: true, + index: '', + query: { + language: 'kuery', + query: 'play_name:\\"Henry IV\\"', + }, + version: true, + }; + + it('asScoped()', async () => { + await supertest.get('/api/data_search_plugin/search_source/as_scoped').expect(200); + }); + + it('createEmpty()', async () => { + await supertest + .get('/api/data_search_plugin/search_source/create_empty') + .expect(200) + .expect(JSON.stringify({ searchSourceJSON: '{}', references: [] })); + }); + + it('create()', async () => { + await supertest + .post('/api/data_search_plugin/search_source/create') + .set('kbn-xsrf', 'anything') + .send(searchSourceFields) + .expect(200) + .expect(({ body }) => { + const searchSourceJSON = JSON.parse(body.searchSourceJSON); + expect(Object.keys(body)).to.eql(['searchSourceJSON', 'references']); + expect(searchSourceJSON.query).to.eql(searchSourceFields.query); + expect(body.references[0].type).to.equal('index-pattern'); + expect(searchSourceJSON.indexRefName).to.equal(body.references[0].name); + }); + }); + }); + }); +} diff --git a/test/scripts/checks/bundle_limits.sh b/test/scripts/checks/bundle_limits.sh new file mode 100755 index 0000000000000..10d9d9343fda4 --- /dev/null +++ b/test/scripts/checks/bundle_limits.sh @@ -0,0 +1,5 @@ +#!/usr/bin/env bash + +source src/dev/ci_setup/setup_env.sh + +node scripts/build_kibana_platform_plugins --validate-limits diff --git a/test/scripts/checks/verify_dependency_versions.sh b/test/scripts/checks/verify_dependency_versions.sh deleted file mode 100755 index b73a71e7ff7fd..0000000000000 --- a/test/scripts/checks/verify_dependency_versions.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/usr/bin/env bash - -source src/dev/ci_setup/setup_env.sh - -yarn run grunt run:verifyDependencyVersions diff --git a/test/scripts/jenkins_build_plugins.sh b/test/scripts/jenkins_build_plugins.sh index 0c3ee4e3f261f..59df02d401167 100755 --- a/test/scripts/jenkins_build_plugins.sh +++ b/test/scripts/jenkins_build_plugins.sh @@ -5,7 +5,6 @@ source src/dev/ci_setup/setup_env.sh echo " -> building kibana platform plugins" node scripts/build_kibana_platform_plugins \ --oss \ - --filter '!alertingExample' \ --scan-dir "$KIBANA_DIR/test/plugin_functional/plugins" \ --scan-dir "$KIBANA_DIR/test/interpreter_functional/plugins" \ --workers 6 \ diff --git a/test/scripts/jenkins_test_setup_oss.sh b/test/scripts/jenkins_test_setup_oss.sh index b7eac33f35176..53626ce89462a 100755 --- a/test/scripts/jenkins_test_setup_oss.sh +++ b/test/scripts/jenkins_test_setup_oss.sh @@ -3,11 +3,7 @@ source test/scripts/jenkins_test_setup.sh if [[ -z "$CODE_COVERAGE" ]]; then - - destDir="build/kibana-build-oss" - if [[ ! "$TASK_QUEUE_PROCESS_ID" ]]; then - destDir="${destDir}-${CI_PARALLEL_PROCESS_NUMBER}" - fi + destDir="$WORKSPACE/kibana-build-oss-${TASK_QUEUE_PROCESS_ID:-$CI_PARALLEL_PROCESS_NUMBER}" if [[ ! -d $destDir ]]; then mkdir -p $destDir diff --git a/test/scripts/jenkins_test_setup_xpack.sh b/test/scripts/jenkins_test_setup_xpack.sh index 74a3de77e3a76..b9227fd8ff416 100755 --- a/test/scripts/jenkins_test_setup_xpack.sh +++ b/test/scripts/jenkins_test_setup_xpack.sh @@ -3,11 +3,7 @@ source test/scripts/jenkins_test_setup.sh if [[ -z "$CODE_COVERAGE" ]]; then - - destDir="build/kibana-build-xpack" - if [[ ! "$TASK_QUEUE_PROCESS_ID" ]]; then - destDir="${destDir}-${CI_PARALLEL_PROCESS_NUMBER}" - fi + destDir="$WORKSPACE/kibana-build-xpack-${TASK_QUEUE_PROCESS_ID:-$CI_PARALLEL_PROCESS_NUMBER}" if [[ ! -d $destDir ]]; then mkdir -p $destDir diff --git a/test/scripts/jenkins_xpack_build_plugins.sh b/test/scripts/jenkins_xpack_build_plugins.sh index 3fd3d02de1304..289e64f66c89b 100755 --- a/test/scripts/jenkins_xpack_build_plugins.sh +++ b/test/scripts/jenkins_xpack_build_plugins.sh @@ -10,5 +10,6 @@ node scripts/build_kibana_platform_plugins \ --scan-dir "$XPACK_DIR/test/alerting_api_integration/plugins" \ --scan-dir "$XPACK_DIR/test/plugin_api_integration/plugins" \ --scan-dir "$XPACK_DIR/test/plugin_api_perf/plugins" \ + --scan-dir "$XPACK_DIR/test/licensing_plugin/plugins" \ --workers 12 \ --verbose diff --git a/test/security_functional/config.ts b/test/security_functional/config.ts new file mode 100644 index 0000000000000..2a35d40678fd2 --- /dev/null +++ b/test/security_functional/config.ts @@ -0,0 +1,54 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import path from 'path'; +import { FtrConfigProviderContext } from '@kbn/test/types/ftr'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const functionalConfig = await readConfigFile(require.resolve('../functional/config')); + + return { + testFiles: [require.resolve('./index.ts')], + services: functionalConfig.get('services'), + pageObjects: functionalConfig.get('pageObjects'), + servers: functionalConfig.get('servers'), + esTestCluster: functionalConfig.get('esTestCluster'), + apps: {}, + esArchiver: { + directory: path.resolve(__dirname, '../functional/fixtures/es_archiver'), + }, + snapshots: { + directory: path.resolve(__dirname, 'snapshots'), + }, + junit: { + reportName: 'Security OSS Functional Tests', + }, + kbnTestServer: { + ...functionalConfig.get('kbnTestServer'), + serverArgs: [ + ...functionalConfig + .get('kbnTestServer.serverArgs') + .filter((arg: string) => !arg.startsWith('--security.showInsecureClusterWarning')), + '--security.showInsecureClusterWarning=true', + // Required to load new platform plugins via `--plugin-path` flag. + '--env.name=development', + ], + }, + }; +} diff --git a/test/security_functional/index.ts b/test/security_functional/index.ts new file mode 100644 index 0000000000000..8066a4eacf61a --- /dev/null +++ b/test/security_functional/index.ts @@ -0,0 +1,27 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +import { FtrProviderContext } from '../functional/ftr_provider_context'; + +// eslint-disable-next-line import/no-default-export +export default function ({ loadTestFile }: FtrProviderContext) { + describe('Security OSS', function () { + this.tags(['skipCloud', 'ciGroup2']); + loadTestFile(require.resolve('./insecure_cluster_warning')); + }); +} diff --git a/test/security_functional/insecure_cluster_warning.ts b/test/security_functional/insecure_cluster_warning.ts new file mode 100644 index 0000000000000..03d9d248d6790 --- /dev/null +++ b/test/security_functional/insecure_cluster_warning.ts @@ -0,0 +1,87 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { FtrProviderContext } from 'test/functional/ftr_provider_context'; + +// eslint-disable-next-line import/no-default-export +export default function ({ getService, getPageObjects }: FtrProviderContext) { + const pageObjects = getPageObjects(['common']); + const testSubjects = getService('testSubjects'); + const browser = getService('browser'); + const esArchiver = getService('esArchiver'); + + describe('Insecure Cluster Warning', () => { + before(async () => { + await pageObjects.common.navigateToApp('home'); + await browser.setLocalStorageItem('insecureClusterWarningVisibility', ''); + // starting without user data + await esArchiver.unload('hamlet'); + }); + + after(async () => { + await esArchiver.unload('hamlet'); + }); + + describe('without user data', () => { + before(async () => { + await browser.setLocalStorageItem('insecureClusterWarningVisibility', ''); + await esArchiver.unload('hamlet'); + }); + + it('should not warn when the cluster contains no user data', async () => { + await browser.setLocalStorageItem( + 'insecureClusterWarningVisibility', + JSON.stringify({ show: false }) + ); + await pageObjects.common.navigateToApp('home'); + await testSubjects.missingOrFail('insecureClusterDefaultAlertText'); + }); + }); + + describe('with user data', () => { + before(async () => { + await pageObjects.common.navigateToApp('home'); + await browser.setLocalStorageItem('insecureClusterWarningVisibility', ''); + await esArchiver.load('hamlet'); + }); + + after(async () => { + await esArchiver.unload('hamlet'); + }); + + it('should warn about an insecure cluster, and hide when dismissed', async () => { + await pageObjects.common.navigateToApp('home'); + await testSubjects.existOrFail('insecureClusterDefaultAlertText'); + + await testSubjects.click('defaultDismissAlertButton'); + + await testSubjects.missingOrFail('insecureClusterDefaultAlertText'); + }); + + it('should not warn when local storage is configured to hide', async () => { + await browser.setLocalStorageItem( + 'insecureClusterWarningVisibility', + JSON.stringify({ show: false }) + ); + await pageObjects.common.navigateToApp('home'); + await testSubjects.missingOrFail('insecureClusterDefaultAlertText'); + }); + }); + }); +} diff --git a/test/tsconfig.json b/test/tsconfig.json index 6e846690d54d9..2c92367f84823 100644 --- a/test/tsconfig.json +++ b/test/tsconfig.json @@ -18,6 +18,8 @@ "interpreter_functional/plugins/**/*" ], "references": [ - { "path": "../src/core/tsconfig.json" } + { "path": "../src/core/tsconfig.json" }, + { "path": "../src/plugins/kibana_utils/tsconfig.json" }, + { "path": "../src/plugins/kibana_react/tsconfig.json" } ] } diff --git a/test/typings/query_string.d.ts b/test/typings/query_string.d.ts deleted file mode 100644 index 3e4a8fa4da6a0..0000000000000 --- a/test/typings/query_string.d.ts +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -declare module 'query-string' { - type ArrayFormat = 'bracket' | 'index' | 'none'; - - export interface ParseOptions { - arrayFormat?: ArrayFormat; - sort: ((itemLeft: string, itemRight: string) => number) | false; - } - - export interface ParsedQuery { - [key: string]: T | T[] | null | undefined; - } - - export function parse(str: string, options?: ParseOptions): ParsedQuery; - - export function parseUrl(str: string, options?: ParseOptions): { url: string; query: any }; - - export interface StringifyOptions { - strict?: boolean; - encode?: boolean; - arrayFormat?: ArrayFormat; - sort: ((itemLeft: string, itemRight: string) => number) | false; - } - - export function stringify(obj: object, options?: StringifyOptions): string; - - export function extract(str: string): string; -} diff --git a/tsconfig.base.json b/tsconfig.base.json index 58a6237846a54..0aad8d6b9c124 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -39,6 +39,8 @@ // Resolve modules in the same way as Node.js. Aka make `require` works the // same in TypeScript as it does in Node.js. "moduleResolution": "node", + // "resolveJsonModule" allows for importing, extracting types from and generating .json files. + "resolveJsonModule": true, // Disallow inconsistently-cased references to the same file. "forceConsistentCasingInFileNames": true, // Forbid unused local variables as the rule was deprecated by ts-lint diff --git a/tsconfig.json b/tsconfig.json index 11838627c5319..cf112b26a2cbb 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -12,7 +12,9 @@ "exclude": [ "src/**/__fixtures__/**/*", "src/test_utils/**/*", - "src/core/**/*" + "src/core/**/*", + "src/plugins/kibana_utils/**/*", + "src/plugins/kibana_react/**/*" // In the build we actually exclude **/public/**/* from this config so that // we can run the TSC on both this and the .browser version of this config // file, but if we did it during development IDEs would not be able to find @@ -21,6 +23,8 @@ ], "references": [ { "path": "./src/test_utils/tsconfig.json" }, - { "path": "./src/core/tsconfig.json" } + { "path": "./src/core/tsconfig.json" }, + { "path": "./src/plugins/kibana_utils/tsconfig.json" }, + { "path": "./src/plugins/kibana_react/tsconfig.json" } ] } diff --git a/tsconfig.refs.json b/tsconfig.refs.json index 66282687f633b..54bd07e4b134c 100644 --- a/tsconfig.refs.json +++ b/tsconfig.refs.json @@ -1,7 +1,9 @@ { "include": [], "references": [ - { "path": "./src/test_utils" }, - { "path": "./src/core" }, + { "path": "./src/test_utils/tsconfig.json" }, + { "path": "./src/core/tsconfig.json" }, + { "path": "./src/plugins/kibana_utils/tsconfig.json" }, + { "path": "./src/plugins/kibana_react/tsconfig.json" }, ] } diff --git a/tsconfig.types.json b/tsconfig.types.json index 4b7dfa2d014a3..86a45f6db1697 100644 --- a/tsconfig.types.json +++ b/tsconfig.types.json @@ -13,6 +13,11 @@ "src/core/public/index.ts", "src/plugins/data/server/index.ts", "src/plugins/data/public/index.ts", + "src/plugins/embeddable/server/index.ts", + "src/plugins/embeddable/public/index.ts", + "src/plugins/expressions/server/index.ts", + "src/plugins/expressions/public/index.ts", + "src/plugins/ui_actions/public/index.ts", "typings" ] } diff --git a/typings/index.d.ts b/typings/index.d.ts index 6d97aca4024c3..db6530d3f9e0b 100644 --- a/typings/index.d.ts +++ b/typings/index.d.ts @@ -35,15 +35,6 @@ declare module '*.svg' { export default content; } -// allow JSON files to be imported directly without lint errors -// see: https://github.com/palantir/tslint/issues/1264#issuecomment-228433367 -// and: https://github.com/Microsoft/TypeScript/wiki/Breaking-Changes#arbitrary-expressions-are-forbidden-in-export-assignments-in-ambient-contexts -declare module '*.json' { - const json: any; - // eslint-disable-next-line import/no-default-export - export default json; -} - type MethodKeysOf = { [K in keyof T]: T[K] extends (...args: any[]) => any ? K : never; }[keyof T]; diff --git a/typings/query_string.d.ts b/typings/query_string.d.ts deleted file mode 100644 index 3e4a8fa4da6a0..0000000000000 --- a/typings/query_string.d.ts +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -declare module 'query-string' { - type ArrayFormat = 'bracket' | 'index' | 'none'; - - export interface ParseOptions { - arrayFormat?: ArrayFormat; - sort: ((itemLeft: string, itemRight: string) => number) | false; - } - - export interface ParsedQuery { - [key: string]: T | T[] | null | undefined; - } - - export function parse(str: string, options?: ParseOptions): ParsedQuery; - - export function parseUrl(str: string, options?: ParseOptions): { url: string; query: any }; - - export interface StringifyOptions { - strict?: boolean; - encode?: boolean; - arrayFormat?: ArrayFormat; - sort: ((itemLeft: string, itemRight: string) => number) | false; - } - - export function stringify(obj: object, options?: StringifyOptions): string; - - export function extract(str: string): string; -} diff --git a/vars/githubPr.groovy b/vars/githubPr.groovy index ec3dbd919fed6..fd5412c905683 100644 --- a/vars/githubPr.groovy +++ b/vars/githubPr.groovy @@ -87,15 +87,6 @@ def getLatestBuildInfo(comment) { return comment ? getBuildInfoFromComment(comment.body) : null } -def createBuildInfo() { - return [ - status: buildUtils.getBuildStatus(), - url: env.BUILD_URL, - number: env.BUILD_NUMBER, - commit: getCommitHash() - ] -} - def getHistoryText(builds) { if (!builds || builds.size() < 1) { return "" @@ -155,6 +146,16 @@ def getTestFailuresMessage() { return messages.join("\n") } +def getBuildStatusIncludingMetrics() { + def status = buildUtils.getBuildStatus() + + if (status == 'SUCCESS' && !ciStats.getMetricsSuccess()) { + return 'FAILURE' + } + + return status +} + def getNextCommentMessage(previousCommentInfo = [:], isFinal = false) { def info = previousCommentInfo ?: [:] info.builds = previousCommentInfo.builds ?: [] @@ -163,7 +164,10 @@ def getNextCommentMessage(previousCommentInfo = [:], isFinal = false) { info.builds = info.builds.findAll { it.number != env.BUILD_NUMBER } def messages = [] - def status = buildUtils.getBuildStatus() + + def status = isFinal + ? getBuildStatusIncludingMetrics() + : buildUtils.getBuildStatus() if (!isFinal) { def failuresPart = status != 'SUCCESS' ? ', with failures' : '' @@ -228,7 +232,12 @@ def getNextCommentMessage(previousCommentInfo = [:], isFinal = false) { messages << "To update your PR or re-run it, just comment with:\n`@elasticmachine merge upstream`" - info.builds << createBuildInfo() + info.builds << [ + status: status, + url: env.BUILD_URL, + number: env.BUILD_NUMBER, + commit: getCommitHash() + ] messages << """ - {{ monitoringMain.instance }}

    +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [id](./kibana-plugin-plugins-embeddable-server.enhancementregistrydefinition.id.md) | string | | + diff --git a/docs/development/plugins/embeddable/server/kibana-plugin-plugins-embeddable-server.md b/docs/development/plugins/embeddable/server/kibana-plugin-plugins-embeddable-server.md new file mode 100644 index 0000000000000..19ee57d677250 --- /dev/null +++ b/docs/development/plugins/embeddable/server/kibana-plugin-plugins-embeddable-server.md @@ -0,0 +1,20 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-server](./kibana-plugin-plugins-embeddable-server.md) + +## kibana-plugin-plugins-embeddable-server package + +## Interfaces + +| Interface | Description | +| --- | --- | +| [EmbeddableRegistryDefinition](./kibana-plugin-plugins-embeddable-server.embeddableregistrydefinition.md) | | +| [EmbeddableSetup](./kibana-plugin-plugins-embeddable-server.embeddablesetup.md) | | +| [EnhancementRegistryDefinition](./kibana-plugin-plugins-embeddable-server.enhancementregistrydefinition.md) | | + +## Variables + +| Variable | Description | +| --- | --- | +| [plugin](./kibana-plugin-plugins-embeddable-server.plugin.md) | | + diff --git a/docs/development/plugins/embeddable/server/kibana-plugin-plugins-embeddable-server.plugin.md b/docs/development/plugins/embeddable/server/kibana-plugin-plugins-embeddable-server.plugin.md new file mode 100644 index 0000000000000..989f3c3e60963 --- /dev/null +++ b/docs/development/plugins/embeddable/server/kibana-plugin-plugins-embeddable-server.plugin.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-embeddable-server](./kibana-plugin-plugins-embeddable-server.md) > [plugin](./kibana-plugin-plugins-embeddable-server.plugin.md) + +## plugin variable + +Signature: + +```typescript +plugin: () => EmbeddableServerPlugin +``` diff --git a/docs/development/plugins/expressions/public/index.md b/docs/development/plugins/expressions/public/index.md new file mode 100644 index 0000000000000..ade7a9e90b517 --- /dev/null +++ b/docs/development/plugins/expressions/public/index.md @@ -0,0 +1,12 @@ + + +[Home](./index.md) + +## API Reference + +## Packages + +| Package | Description | +| --- | --- | +| [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) | | + diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.anyexpressionfunctiondefinition.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.anyexpressionfunctiondefinition.md new file mode 100644 index 0000000000000..f905a1028d217 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.anyexpressionfunctiondefinition.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [AnyExpressionFunctionDefinition](./kibana-plugin-plugins-expressions-public.anyexpressionfunctiondefinition.md) + +## AnyExpressionFunctionDefinition type + +Type to capture every possible expression function definition. + +Signature: + +```typescript +export declare type AnyExpressionFunctionDefinition = ExpressionFunctionDefinition, any>; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.anyexpressiontypedefinition.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.anyexpressiontypedefinition.md new file mode 100644 index 0000000000000..c213de4341a6a --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.anyexpressiontypedefinition.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [AnyExpressionTypeDefinition](./kibana-plugin-plugins-expressions-public.anyexpressiontypedefinition.md) + +## AnyExpressionTypeDefinition type + +Signature: + +```typescript +export declare type AnyExpressionTypeDefinition = ExpressionTypeDefinition; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.argumenttype.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.argumenttype.md new file mode 100644 index 0000000000000..bf80b863fda90 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.argumenttype.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ArgumentType](./kibana-plugin-plugins-expressions-public.argumenttype.md) + +## ArgumentType type + +This type represents all of the possible combinations of properties of an Argument in an Expression Function. The presence or absence of certain fields influence the shape and presence of others within each `arg` in the specification. + +Signature: + +```typescript +export declare type ArgumentType = SingleArgumentType | MultipleArgumentType | UnresolvedSingleArgumentType | UnresolvedMultipleArgumentType; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.buildexpression.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.buildexpression.md new file mode 100644 index 0000000000000..e1d522588aae8 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.buildexpression.md @@ -0,0 +1,24 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [buildExpression](./kibana-plugin-plugins-expressions-public.buildexpression.md) + +## buildExpression() function + +Makes it easy to progressively build, update, and traverse an expression AST. You can either start with an empty AST, or provide an expression string, AST, or array of expression function builders to use as initial state. + +Signature: + +```typescript +export declare function buildExpression(initialState?: ExpressionAstFunctionBuilder[] | ExpressionAstExpression | string): ExpressionAstExpressionBuilder; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| initialState | ExpressionAstFunctionBuilder[] | ExpressionAstExpression | string | | + +Returns: + +`ExpressionAstExpressionBuilder` + diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.buildexpressionfunction.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.buildexpressionfunction.md new file mode 100644 index 0000000000000..79deb7157130e --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.buildexpressionfunction.md @@ -0,0 +1,30 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [buildExpressionFunction](./kibana-plugin-plugins-expressions-public.buildexpressionfunction.md) + +## buildExpressionFunction() function + +Manages an AST for a single expression function. The return value can be provided to `buildExpression` to add this function to an expression. + +Note that to preserve type safety and ensure no args are missing, all required arguments for the specified function must be provided up front. If desired, they can be changed or removed later. + +Signature: + +```typescript +export declare function buildExpressionFunction(fnName: InferFunctionDefinition['name'], +initialArgs: { + [K in keyof FunctionArgs]: FunctionArgs[K] | ExpressionAstExpressionBuilder | ExpressionAstExpressionBuilder[]; +}): ExpressionAstFunctionBuilder; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fnName | InferFunctionDefinition<FnDef>['name'] | | +| initialArgs | {
    [K in keyof FunctionArgs<FnDef>]: FunctionArgs<FnDef>[K] | ExpressionAstExpressionBuilder | ExpressionAstExpressionBuilder[];
    } | | + +Returns: + +`ExpressionAstFunctionBuilder` + diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.datatable.columns.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.datatable.columns.md new file mode 100644 index 0000000000000..d24c4f4dfb176 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.datatable.columns.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [Datatable](./kibana-plugin-plugins-expressions-public.datatable.md) > [columns](./kibana-plugin-plugins-expressions-public.datatable.columns.md) + +## Datatable.columns property + +Signature: + +```typescript +columns: DatatableColumn[]; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.datatable.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.datatable.md new file mode 100644 index 0000000000000..f2daf656dfa73 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.datatable.md @@ -0,0 +1,22 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [Datatable](./kibana-plugin-plugins-expressions-public.datatable.md) + +## Datatable interface + +A `Datatable` in Canvas is a unique structure that represents tabulated data. + +Signature: + +```typescript +export interface Datatable +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [columns](./kibana-plugin-plugins-expressions-public.datatable.columns.md) | DatatableColumn[] | | +| [rows](./kibana-plugin-plugins-expressions-public.datatable.rows.md) | DatatableRow[] | | +| [type](./kibana-plugin-plugins-expressions-public.datatable.type.md) | typeof name | | + diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.datatable.rows.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.datatable.rows.md new file mode 100644 index 0000000000000..0d52e446b09fd --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.datatable.rows.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [Datatable](./kibana-plugin-plugins-expressions-public.datatable.md) > [rows](./kibana-plugin-plugins-expressions-public.datatable.rows.md) + +## Datatable.rows property + +Signature: + +```typescript +rows: DatatableRow[]; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.datatable.type.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.datatable.type.md new file mode 100644 index 0000000000000..e0ee6fd5d8372 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.datatable.type.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [Datatable](./kibana-plugin-plugins-expressions-public.datatable.md) > [type](./kibana-plugin-plugins-expressions-public.datatable.type.md) + +## Datatable.type property + +Signature: + +```typescript +type: typeof name; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.datatablecolumn.id.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.datatablecolumn.id.md new file mode 100644 index 0000000000000..d9b98e6cf939e --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.datatablecolumn.id.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [DatatableColumn](./kibana-plugin-plugins-expressions-public.datatablecolumn.md) > [id](./kibana-plugin-plugins-expressions-public.datatablecolumn.id.md) + +## DatatableColumn.id property + +Signature: + +```typescript +id: string; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.datatablecolumn.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.datatablecolumn.md new file mode 100644 index 0000000000000..d67a5d9b36b12 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.datatablecolumn.md @@ -0,0 +1,22 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [DatatableColumn](./kibana-plugin-plugins-expressions-public.datatablecolumn.md) + +## DatatableColumn interface + +This type represents the shape of a column in a `Datatable`. + +Signature: + +```typescript +export interface DatatableColumn +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [id](./kibana-plugin-plugins-expressions-public.datatablecolumn.id.md) | string | | +| [meta](./kibana-plugin-plugins-expressions-public.datatablecolumn.meta.md) | DatatableColumnMeta | | +| [name](./kibana-plugin-plugins-expressions-public.datatablecolumn.name.md) | string | | + diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.datatablecolumn.meta.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.datatablecolumn.meta.md new file mode 100644 index 0000000000000..a5414dde86f97 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.datatablecolumn.meta.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [DatatableColumn](./kibana-plugin-plugins-expressions-public.datatablecolumn.md) > [meta](./kibana-plugin-plugins-expressions-public.datatablecolumn.meta.md) + +## DatatableColumn.meta property + +Signature: + +```typescript +meta: DatatableColumnMeta; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.datatablecolumn.name.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.datatablecolumn.name.md new file mode 100644 index 0000000000000..74c3883e7a172 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.datatablecolumn.name.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [DatatableColumn](./kibana-plugin-plugins-expressions-public.datatablecolumn.md) > [name](./kibana-plugin-plugins-expressions-public.datatablecolumn.name.md) + +## DatatableColumn.name property + +Signature: + +```typescript +name: string; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.datatablecolumntype.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.datatablecolumntype.md new file mode 100644 index 0000000000000..a06ab351e62c3 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.datatablecolumntype.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [DatatableColumnType](./kibana-plugin-plugins-expressions-public.datatablecolumntype.md) + +## DatatableColumnType type + +This type represents the `type` of any `DatatableColumn` in a `Datatable`. + +Signature: + +```typescript +export declare type DatatableColumnType = 'string' | 'number' | 'boolean' | 'date' | 'null'; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.datatablerow.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.datatablerow.md new file mode 100644 index 0000000000000..87cc15d0d4091 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.datatablerow.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [DatatableRow](./kibana-plugin-plugins-expressions-public.datatablerow.md) + +## DatatableRow type + +This type represents a row in a `Datatable`. + +Signature: + +```typescript +export declare type DatatableRow = Record; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.execution._constructor_.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.execution._constructor_.md new file mode 100644 index 0000000000000..1d0c9f99169db --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.execution._constructor_.md @@ -0,0 +1,20 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [Execution](./kibana-plugin-plugins-expressions-public.execution.md) > [(constructor)](./kibana-plugin-plugins-expressions-public.execution._constructor_.md) + +## Execution.(constructor) + +Constructs a new instance of the `Execution` class + +Signature: + +```typescript +constructor(params: ExecutionParams); +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| params | ExecutionParams<ExtraContext> | | + diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.execution.cancel.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.execution.cancel.md new file mode 100644 index 0000000000000..e87cea30dd5b6 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.execution.cancel.md @@ -0,0 +1,17 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [Execution](./kibana-plugin-plugins-expressions-public.execution.md) > [cancel](./kibana-plugin-plugins-expressions-public.execution.cancel.md) + +## Execution.cancel() method + +Stop execution of expression. + +Signature: + +```typescript +cancel(): void; +``` +Returns: + +`void` + diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.execution.cast.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.execution.cast.md new file mode 100644 index 0000000000000..632849af7c82b --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.execution.cast.md @@ -0,0 +1,23 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [Execution](./kibana-plugin-plugins-expressions-public.execution.md) > [cast](./kibana-plugin-plugins-expressions-public.execution.cast.md) + +## Execution.cast() method + +Signature: + +```typescript +cast(value: any, toTypeNames?: string[]): any; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| value | any | | +| toTypeNames | string[] | | + +Returns: + +`any` + diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.execution.context.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.execution.context.md new file mode 100644 index 0000000000000..732fe94d65617 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.execution.context.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [Execution](./kibana-plugin-plugins-expressions-public.execution.md) > [context](./kibana-plugin-plugins-expressions-public.execution.context.md) + +## Execution.context property + +Execution context - object that allows to do side-effects. Context is passed to every function. + +Signature: + +```typescript +readonly context: ExecutionContext & ExtraContext; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.execution.contract.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.execution.contract.md new file mode 100644 index 0000000000000..fa03297ea22a7 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.execution.contract.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [Execution](./kibana-plugin-plugins-expressions-public.execution.md) > [contract](./kibana-plugin-plugins-expressions-public.execution.contract.md) + +## Execution.contract property + +Contract is a public representation of `Execution` instances. Contract we can return to other plugins for their consumption. + +Signature: + +```typescript +readonly contract: ExecutionContract; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.execution.expression.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.execution.expression.md new file mode 100644 index 0000000000000..a30cc89e8b649 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.execution.expression.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [Execution](./kibana-plugin-plugins-expressions-public.execution.md) > [expression](./kibana-plugin-plugins-expressions-public.execution.expression.md) + +## Execution.expression property + +Signature: + +```typescript +readonly expression: string; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.execution.input.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.execution.input.md new file mode 100644 index 0000000000000..553a463a2b931 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.execution.input.md @@ -0,0 +1,15 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [Execution](./kibana-plugin-plugins-expressions-public.execution.md) > [input](./kibana-plugin-plugins-expressions-public.execution.input.md) + +## Execution.input property + +Initial input of the execution. + +N.B. It is initialized to `null` rather than `undefined` for legacy reasons, because in legacy interpreter it was set to `null` by default. + +Signature: + +```typescript +input: Input; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.execution.inspectoradapters.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.execution.inspectoradapters.md new file mode 100644 index 0000000000000..728015011f7d9 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.execution.inspectoradapters.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [Execution](./kibana-plugin-plugins-expressions-public.execution.md) > [inspectorAdapters](./kibana-plugin-plugins-expressions-public.execution.inspectoradapters.md) + +## Execution.inspectorAdapters property + +Signature: + +```typescript +get inspectorAdapters(): InspectorAdapters; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.execution.interpret.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.execution.interpret.md new file mode 100644 index 0000000000000..31f38b7069812 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.execution.interpret.md @@ -0,0 +1,24 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [Execution](./kibana-plugin-plugins-expressions-public.execution.md) > [interpret](./kibana-plugin-plugins-expressions-public.execution.interpret.md) + +## Execution.interpret() method + +Signature: + +```typescript +interpret(ast: ExpressionAstNode, input: T, options?: ExpressionExecOptions): Promise; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| ast | ExpressionAstNode | | +| input | T | | +| options | ExpressionExecOptions | | + +Returns: + +`Promise` + diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.execution.invokechain.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.execution.invokechain.md new file mode 100644 index 0000000000000..5078baf2ca526 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.execution.invokechain.md @@ -0,0 +1,23 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [Execution](./kibana-plugin-plugins-expressions-public.execution.md) > [invokeChain](./kibana-plugin-plugins-expressions-public.execution.invokechain.md) + +## Execution.invokeChain() method + +Signature: + +```typescript +invokeChain(chainArr: ExpressionAstFunction[], input: unknown): Promise; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| chainArr | ExpressionAstFunction[] | | +| input | unknown | | + +Returns: + +`Promise` + diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.execution.invokefunction.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.execution.invokefunction.md new file mode 100644 index 0000000000000..e90cee8b626d6 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.execution.invokefunction.md @@ -0,0 +1,24 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [Execution](./kibana-plugin-plugins-expressions-public.execution.md) > [invokeFunction](./kibana-plugin-plugins-expressions-public.execution.invokefunction.md) + +## Execution.invokeFunction() method + +Signature: + +```typescript +invokeFunction(fn: ExpressionFunction, input: unknown, args: Record): Promise; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fn | ExpressionFunction | | +| input | unknown | | +| args | Record<string, unknown> | | + +Returns: + +`Promise` + diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.execution.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.execution.md new file mode 100644 index 0000000000000..4d227e6ab85b8 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.execution.md @@ -0,0 +1,43 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [Execution](./kibana-plugin-plugins-expressions-public.execution.md) + +## Execution class + +Signature: + +```typescript +export declare class Execution = Record, Input = unknown, Output = unknown, InspectorAdapters extends Adapters = ExtraContext['inspectorAdapters'] extends object ? ExtraContext['inspectorAdapters'] : DefaultInspectorAdapters> +``` + +## Constructors + +| Constructor | Modifiers | Description | +| --- | --- | --- | +| [(constructor)(params)](./kibana-plugin-plugins-expressions-public.execution._constructor_.md) | | Constructs a new instance of the Execution class | + +## Properties + +| Property | Modifiers | Type | Description | +| --- | --- | --- | --- | +| [context](./kibana-plugin-plugins-expressions-public.execution.context.md) | | ExecutionContext<Input, InspectorAdapters> & ExtraContext | Execution context - object that allows to do side-effects. Context is passed to every function. | +| [contract](./kibana-plugin-plugins-expressions-public.execution.contract.md) | | ExecutionContract<ExtraContext, Input, Output, InspectorAdapters> | Contract is a public representation of Execution instances. Contract we can return to other plugins for their consumption. | +| [expression](./kibana-plugin-plugins-expressions-public.execution.expression.md) | | string | | +| [input](./kibana-plugin-plugins-expressions-public.execution.input.md) | | Input | Initial input of the execution.N.B. It is initialized to null rather than undefined for legacy reasons, because in legacy interpreter it was set to null by default. | +| [inspectorAdapters](./kibana-plugin-plugins-expressions-public.execution.inspectoradapters.md) | | InspectorAdapters | | +| [params](./kibana-plugin-plugins-expressions-public.execution.params.md) | | ExecutionParams<ExtraContext> | | +| [result](./kibana-plugin-plugins-expressions-public.execution.result.md) | | Promise<Output | ExpressionValueError> | | +| [state](./kibana-plugin-plugins-expressions-public.execution.state.md) | | ExecutionContainer<Output | ExpressionValueError> | Dynamic state of the execution. | + +## Methods + +| Method | Modifiers | Description | +| --- | --- | --- | +| [cancel()](./kibana-plugin-plugins-expressions-public.execution.cancel.md) | | Stop execution of expression. | +| [cast(value, toTypeNames)](./kibana-plugin-plugins-expressions-public.execution.cast.md) | | | +| [interpret(ast, input, options)](./kibana-plugin-plugins-expressions-public.execution.interpret.md) | | | +| [invokeChain(chainArr, input)](./kibana-plugin-plugins-expressions-public.execution.invokechain.md) | | | +| [invokeFunction(fn, input, args)](./kibana-plugin-plugins-expressions-public.execution.invokefunction.md) | | | +| [resolveArgs(fnDef, input, argAsts)](./kibana-plugin-plugins-expressions-public.execution.resolveargs.md) | | | +| [start(input)](./kibana-plugin-plugins-expressions-public.execution.start.md) | | Call this method to start execution.N.B. input is initialized to null rather than undefined for legacy reasons, because in legacy interpreter it was set to null by default. | + diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.execution.params.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.execution.params.md new file mode 100644 index 0000000000000..cd90bf6adab47 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.execution.params.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [Execution](./kibana-plugin-plugins-expressions-public.execution.md) > [params](./kibana-plugin-plugins-expressions-public.execution.params.md) + +## Execution.params property + +Signature: + +```typescript +readonly params: ExecutionParams; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.execution.resolveargs.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.execution.resolveargs.md new file mode 100644 index 0000000000000..ab67dff604a86 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.execution.resolveargs.md @@ -0,0 +1,24 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [Execution](./kibana-plugin-plugins-expressions-public.execution.md) > [resolveArgs](./kibana-plugin-plugins-expressions-public.execution.resolveargs.md) + +## Execution.resolveArgs() method + +Signature: + +```typescript +resolveArgs(fnDef: ExpressionFunction, input: unknown, argAsts: any): Promise; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fnDef | ExpressionFunction | | +| input | unknown | | +| argAsts | any | | + +Returns: + +`Promise` + diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.execution.result.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.execution.result.md new file mode 100644 index 0000000000000..e0167a3a378fe --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.execution.result.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [Execution](./kibana-plugin-plugins-expressions-public.execution.md) > [result](./kibana-plugin-plugins-expressions-public.execution.result.md) + +## Execution.result property + +Signature: + +```typescript +get result(): Promise; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.execution.start.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.execution.start.md new file mode 100644 index 0000000000000..c6edc43d423dc --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.execution.start.md @@ -0,0 +1,26 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [Execution](./kibana-plugin-plugins-expressions-public.execution.md) > [start](./kibana-plugin-plugins-expressions-public.execution.start.md) + +## Execution.start() method + +Call this method to start execution. + +N.B. `input` is initialized to `null` rather than `undefined` for legacy reasons, because in legacy interpreter it was set to `null` by default. + +Signature: + +```typescript +start(input?: Input): void; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| input | Input | | + +Returns: + +`void` + diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.execution.state.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.execution.state.md new file mode 100644 index 0000000000000..ca8b57b760f29 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.execution.state.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [Execution](./kibana-plugin-plugins-expressions-public.execution.md) > [state](./kibana-plugin-plugins-expressions-public.execution.state.md) + +## Execution.state property + +Dynamic state of the execution. + +Signature: + +```typescript +readonly state: ExecutionContainer; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executioncontainer.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executioncontainer.md new file mode 100644 index 0000000000000..5cea6c4bc4b8f --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executioncontainer.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExecutionContainer](./kibana-plugin-plugins-expressions-public.executioncontainer.md) + +## ExecutionContainer type + +Signature: + +```typescript +export declare type ExecutionContainer = StateContainer, ExecutionPureTransitions>; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executioncontext.abortsignal.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executioncontext.abortsignal.md new file mode 100644 index 0000000000000..caedf4344dc35 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executioncontext.abortsignal.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExecutionContext](./kibana-plugin-plugins-expressions-public.executioncontext.md) > [abortSignal](./kibana-plugin-plugins-expressions-public.executioncontext.abortsignal.md) + +## ExecutionContext.abortSignal property + +Adds ability to abort current execution. + +Signature: + +```typescript +abortSignal: AbortSignal; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executioncontext.getinitialinput.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executioncontext.getinitialinput.md new file mode 100644 index 0000000000000..460b1622c6fbd --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executioncontext.getinitialinput.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExecutionContext](./kibana-plugin-plugins-expressions-public.executioncontext.md) > [getInitialInput](./kibana-plugin-plugins-expressions-public.executioncontext.getinitialinput.md) + +## ExecutionContext.getInitialInput property + +Get initial input with which execution started. + +Signature: + +```typescript +getInitialInput: () => Input; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executioncontext.getsavedobject.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executioncontext.getsavedobject.md new file mode 100644 index 0000000000000..dffce4a091718 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executioncontext.getsavedobject.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExecutionContext](./kibana-plugin-plugins-expressions-public.executioncontext.md) > [getSavedObject](./kibana-plugin-plugins-expressions-public.executioncontext.getsavedobject.md) + +## ExecutionContext.getSavedObject property + +Allows to fetch saved objects from ElasticSearch. In browser `getSavedObject` function is provided automatically by the Expressions plugin. On the server the caller of the expression has to provide this context function. The reason is because on the browser we always know the user who tries to fetch a saved object, thus saved object client is scoped automatically to that user. However, on the server we can scope that saved object client to any user, or even not scope it at all and execute it as an "internal" user. + +Signature: + +```typescript +getSavedObject?: (type: string, id: string) => Promise>; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executioncontext.inspectoradapters.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executioncontext.inspectoradapters.md new file mode 100644 index 0000000000000..6f0db6af5616e --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executioncontext.inspectoradapters.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExecutionContext](./kibana-plugin-plugins-expressions-public.executioncontext.md) > [inspectorAdapters](./kibana-plugin-plugins-expressions-public.executioncontext.inspectoradapters.md) + +## ExecutionContext.inspectorAdapters property + +Adapters for `inspector` plugin. + +Signature: + +```typescript +inspectorAdapters: InspectorAdapters; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executioncontext.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executioncontext.md new file mode 100644 index 0000000000000..786e94455c600 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executioncontext.md @@ -0,0 +1,26 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExecutionContext](./kibana-plugin-plugins-expressions-public.executioncontext.md) + +## ExecutionContext interface + +`ExecutionContext` is an object available to all functions during a single execution; it provides various methods to perform side-effects. + +Signature: + +```typescript +export interface ExecutionContext +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [abortSignal](./kibana-plugin-plugins-expressions-public.executioncontext.abortsignal.md) | AbortSignal | Adds ability to abort current execution. | +| [getInitialInput](./kibana-plugin-plugins-expressions-public.executioncontext.getinitialinput.md) | () => Input | Get initial input with which execution started. | +| [getSavedObject](./kibana-plugin-plugins-expressions-public.executioncontext.getsavedobject.md) | <T extends SavedObjectAttributes = SavedObjectAttributes>(type: string, id: string) => Promise<SavedObject<T>> | Allows to fetch saved objects from ElasticSearch. In browser getSavedObject function is provided automatically by the Expressions plugin. On the server the caller of the expression has to provide this context function. The reason is because on the browser we always know the user who tries to fetch a saved object, thus saved object client is scoped automatically to that user. However, on the server we can scope that saved object client to any user, or even not scope it at all and execute it as an "internal" user. | +| [inspectorAdapters](./kibana-plugin-plugins-expressions-public.executioncontext.inspectoradapters.md) | InspectorAdapters | Adapters for inspector plugin. | +| [search](./kibana-plugin-plugins-expressions-public.executioncontext.search.md) | ExecutionContextSearch | Search context in which expression should operate. | +| [types](./kibana-plugin-plugins-expressions-public.executioncontext.types.md) | Record<string, ExpressionType> | A map of available expression types. | +| [variables](./kibana-plugin-plugins-expressions-public.executioncontext.variables.md) | Record<string, unknown> | Context variables that can be consumed using var and var_set functions. | + diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executioncontext.search.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executioncontext.search.md new file mode 100644 index 0000000000000..05501a475cbd4 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executioncontext.search.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExecutionContext](./kibana-plugin-plugins-expressions-public.executioncontext.md) > [search](./kibana-plugin-plugins-expressions-public.executioncontext.search.md) + +## ExecutionContext.search property + +Search context in which expression should operate. + +Signature: + +```typescript +search?: ExecutionContextSearch; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executioncontext.types.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executioncontext.types.md new file mode 100644 index 0000000000000..0bddaf8455635 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executioncontext.types.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExecutionContext](./kibana-plugin-plugins-expressions-public.executioncontext.md) > [types](./kibana-plugin-plugins-expressions-public.executioncontext.types.md) + +## ExecutionContext.types property + +A map of available expression types. + +Signature: + +```typescript +types: Record; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executioncontext.variables.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executioncontext.variables.md new file mode 100644 index 0000000000000..3f8a87152f9fe --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executioncontext.variables.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExecutionContext](./kibana-plugin-plugins-expressions-public.executioncontext.md) > [variables](./kibana-plugin-plugins-expressions-public.executioncontext.variables.md) + +## ExecutionContext.variables property + +Context variables that can be consumed using `var` and `var_set` functions. + +Signature: + +```typescript +variables: Record; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executioncontract._constructor_.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executioncontract._constructor_.md new file mode 100644 index 0000000000000..89a99ef2f8ef8 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executioncontract._constructor_.md @@ -0,0 +1,20 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExecutionContract](./kibana-plugin-plugins-expressions-public.executioncontract.md) > [(constructor)](./kibana-plugin-plugins-expressions-public.executioncontract._constructor_.md) + +## ExecutionContract.(constructor) + +Constructs a new instance of the `ExecutionContract` class + +Signature: + +```typescript +constructor(execution: Execution); +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| execution | Execution<ExtraContext, Input, Output, InspectorAdapters> | | + diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executioncontract.cancel.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executioncontract.cancel.md new file mode 100644 index 0000000000000..7ddfb824288d1 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executioncontract.cancel.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExecutionContract](./kibana-plugin-plugins-expressions-public.executioncontract.md) > [cancel](./kibana-plugin-plugins-expressions-public.executioncontract.cancel.md) + +## ExecutionContract.cancel property + +Cancel the execution of the expression. This will set abort signal (available in execution context) to aborted state, letting expression functions to stop their execution. + +Signature: + +```typescript +cancel: () => void; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executioncontract.execution.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executioncontract.execution.md new file mode 100644 index 0000000000000..f7911250488f2 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executioncontract.execution.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExecutionContract](./kibana-plugin-plugins-expressions-public.executioncontract.md) > [execution](./kibana-plugin-plugins-expressions-public.executioncontract.execution.md) + +## ExecutionContract.execution property + +Signature: + +```typescript +protected readonly execution: Execution; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executioncontract.getast.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executioncontract.getast.md new file mode 100644 index 0000000000000..d873614d779a9 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executioncontract.getast.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExecutionContract](./kibana-plugin-plugins-expressions-public.executioncontract.md) > [getAst](./kibana-plugin-plugins-expressions-public.executioncontract.getast.md) + +## ExecutionContract.getAst property + +Get AST used to execute the expression. + +Signature: + +```typescript +getAst: () => ExpressionAstExpression; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executioncontract.getdata.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executioncontract.getdata.md new file mode 100644 index 0000000000000..dcd96cf5767bf --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executioncontract.getdata.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExecutionContract](./kibana-plugin-plugins-expressions-public.executioncontract.md) > [getData](./kibana-plugin-plugins-expressions-public.executioncontract.getdata.md) + +## ExecutionContract.getData property + +Returns the final output of expression, if any error happens still wraps that error into `ExpressionValueError` type and returns that. This function never throws. + +Signature: + +```typescript +getData: () => Promise; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executioncontract.getexpression.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executioncontract.getexpression.md new file mode 100644 index 0000000000000..41dbe72fa69b2 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executioncontract.getexpression.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExecutionContract](./kibana-plugin-plugins-expressions-public.executioncontract.md) > [getExpression](./kibana-plugin-plugins-expressions-public.executioncontract.getexpression.md) + +## ExecutionContract.getExpression property + +Get string representation of the expression. Returns the original string if execution was started from a string. If execution was started from an AST this method returns a string generated from AST. + +Signature: + +```typescript +getExpression: () => string; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executioncontract.inspect.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executioncontract.inspect.md new file mode 100644 index 0000000000000..d5202b02b0dfd --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executioncontract.inspect.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExecutionContract](./kibana-plugin-plugins-expressions-public.executioncontract.md) > [inspect](./kibana-plugin-plugins-expressions-public.executioncontract.inspect.md) + +## ExecutionContract.inspect property + +Get Inspector adapters provided to all functions of expression through execution context. + +Signature: + +```typescript +inspect: () => InspectorAdapters; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executioncontract.ispending.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executioncontract.ispending.md new file mode 100644 index 0000000000000..409c31b3fbc2c --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executioncontract.ispending.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExecutionContract](./kibana-plugin-plugins-expressions-public.executioncontract.md) > [isPending](./kibana-plugin-plugins-expressions-public.executioncontract.ispending.md) + +## ExecutionContract.isPending property + +Signature: + +```typescript +get isPending(): boolean; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executioncontract.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executioncontract.md new file mode 100644 index 0000000000000..d05620eace208 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executioncontract.md @@ -0,0 +1,32 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExecutionContract](./kibana-plugin-plugins-expressions-public.executioncontract.md) + +## ExecutionContract class + +`ExecutionContract` is a wrapper around `Execution` class. It provides the same functionality but does not expose Expressions plugin internals. + +Signature: + +```typescript +export declare class ExecutionContract = Record, Input = unknown, Output = unknown, InspectorAdapters = unknown> +``` + +## Constructors + +| Constructor | Modifiers | Description | +| --- | --- | --- | +| [(constructor)(execution)](./kibana-plugin-plugins-expressions-public.executioncontract._constructor_.md) | | Constructs a new instance of the ExecutionContract class | + +## Properties + +| Property | Modifiers | Type | Description | +| --- | --- | --- | --- | +| [cancel](./kibana-plugin-plugins-expressions-public.executioncontract.cancel.md) | | () => void | Cancel the execution of the expression. This will set abort signal (available in execution context) to aborted state, letting expression functions to stop their execution. | +| [execution](./kibana-plugin-plugins-expressions-public.executioncontract.execution.md) | | Execution<ExtraContext, Input, Output, InspectorAdapters> | | +| [getAst](./kibana-plugin-plugins-expressions-public.executioncontract.getast.md) | | () => ExpressionAstExpression | Get AST used to execute the expression. | +| [getData](./kibana-plugin-plugins-expressions-public.executioncontract.getdata.md) | | () => Promise<Output | ExpressionValueError> | Returns the final output of expression, if any error happens still wraps that error into ExpressionValueError type and returns that. This function never throws. | +| [getExpression](./kibana-plugin-plugins-expressions-public.executioncontract.getexpression.md) | | () => string | Get string representation of the expression. Returns the original string if execution was started from a string. If execution was started from an AST this method returns a string generated from AST. | +| [inspect](./kibana-plugin-plugins-expressions-public.executioncontract.inspect.md) | | () => InspectorAdapters | Get Inspector adapters provided to all functions of expression through execution context. | +| [isPending](./kibana-plugin-plugins-expressions-public.executioncontract.ispending.md) | | boolean | | + diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executionparams.ast.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executionparams.ast.md new file mode 100644 index 0000000000000..63487bc4c753e --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executionparams.ast.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExecutionParams](./kibana-plugin-plugins-expressions-public.executionparams.md) > [ast](./kibana-plugin-plugins-expressions-public.executionparams.ast.md) + +## ExecutionParams.ast property + +Signature: + +```typescript +ast?: ExpressionAstExpression; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executionparams.context.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executionparams.context.md new file mode 100644 index 0000000000000..b6013162ef2ae --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executionparams.context.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExecutionParams](./kibana-plugin-plugins-expressions-public.executionparams.md) > [context](./kibana-plugin-plugins-expressions-public.executionparams.context.md) + +## ExecutionParams.context property + +Signature: + +```typescript +context?: ExtraContext; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executionparams.debug.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executionparams.debug.md new file mode 100644 index 0000000000000..61ec72465f55e --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executionparams.debug.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExecutionParams](./kibana-plugin-plugins-expressions-public.executionparams.md) > [debug](./kibana-plugin-plugins-expressions-public.executionparams.debug.md) + +## ExecutionParams.debug property + +Whether to execute expression in \*debug mode\*. In \*debug mode\* inputs and outputs as well as all resolved arguments and time it took to execute each function are saved and are available for introspection. + +Signature: + +```typescript +debug?: boolean; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executionparams.executor.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executionparams.executor.md new file mode 100644 index 0000000000000..ec070842692fe --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executionparams.executor.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExecutionParams](./kibana-plugin-plugins-expressions-public.executionparams.md) > [executor](./kibana-plugin-plugins-expressions-public.executionparams.executor.md) + +## ExecutionParams.executor property + +Signature: + +```typescript +executor: Executor; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executionparams.expression.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executionparams.expression.md new file mode 100644 index 0000000000000..f79728bacd336 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executionparams.expression.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExecutionParams](./kibana-plugin-plugins-expressions-public.executionparams.md) > [expression](./kibana-plugin-plugins-expressions-public.executionparams.expression.md) + +## ExecutionParams.expression property + +Signature: + +```typescript +expression?: string; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executionparams.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executionparams.md new file mode 100644 index 0000000000000..e39dc231fbf96 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executionparams.md @@ -0,0 +1,22 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExecutionParams](./kibana-plugin-plugins-expressions-public.executionparams.md) + +## ExecutionParams interface + +Signature: + +```typescript +export interface ExecutionParams = Record> +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [ast](./kibana-plugin-plugins-expressions-public.executionparams.ast.md) | ExpressionAstExpression | | +| [context](./kibana-plugin-plugins-expressions-public.executionparams.context.md) | ExtraContext | | +| [debug](./kibana-plugin-plugins-expressions-public.executionparams.debug.md) | boolean | Whether to execute expression in \*debug mode\*. In \*debug mode\* inputs and outputs as well as all resolved arguments and time it took to execute each function are saved and are available for introspection. | +| [executor](./kibana-plugin-plugins-expressions-public.executionparams.executor.md) | Executor<any> | | +| [expression](./kibana-plugin-plugins-expressions-public.executionparams.expression.md) | string | | + diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executionstate.ast.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executionstate.ast.md new file mode 100644 index 0000000000000..bd77c959bde63 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executionstate.ast.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExecutionState](./kibana-plugin-plugins-expressions-public.executionstate.md) > [ast](./kibana-plugin-plugins-expressions-public.executionstate.ast.md) + +## ExecutionState.ast property + +Signature: + +```typescript +ast: ExpressionAstExpression; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executionstate.error.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executionstate.error.md new file mode 100644 index 0000000000000..3ec804b3f0f2e --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executionstate.error.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExecutionState](./kibana-plugin-plugins-expressions-public.executionstate.md) > [error](./kibana-plugin-plugins-expressions-public.executionstate.error.md) + +## ExecutionState.error property + +Error happened during the execution. + +Signature: + +```typescript +error?: Error; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executionstate.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executionstate.md new file mode 100644 index 0000000000000..a7848a65fb94b --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executionstate.md @@ -0,0 +1,21 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExecutionState](./kibana-plugin-plugins-expressions-public.executionstate.md) + +## ExecutionState interface + +Signature: + +```typescript +export interface ExecutionState extends ExecutorState +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [ast](./kibana-plugin-plugins-expressions-public.executionstate.ast.md) | ExpressionAstExpression | | +| [error](./kibana-plugin-plugins-expressions-public.executionstate.error.md) | Error | Error happened during the execution. | +| [result](./kibana-plugin-plugins-expressions-public.executionstate.result.md) | Output | Result of the expression execution. | +| [state](./kibana-plugin-plugins-expressions-public.executionstate.state.md) | 'not-started' | 'pending' | 'result' | 'error' | Tracks state of execution.- not-started - before .start() method was called. - pending - immediately after .start() method is called. - result - when expression execution completed. - error - when execution failed with error. | + diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executionstate.result.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executionstate.result.md new file mode 100644 index 0000000000000..571f95211b8bf --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executionstate.result.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExecutionState](./kibana-plugin-plugins-expressions-public.executionstate.md) > [result](./kibana-plugin-plugins-expressions-public.executionstate.result.md) + +## ExecutionState.result property + +Result of the expression execution. + +Signature: + +```typescript +result?: Output; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executionstate.state.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executionstate.state.md new file mode 100644 index 0000000000000..9b6403590e60b --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executionstate.state.md @@ -0,0 +1,15 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExecutionState](./kibana-plugin-plugins-expressions-public.executionstate.md) > [state](./kibana-plugin-plugins-expressions-public.executionstate.state.md) + +## ExecutionState.state property + +Tracks state of execution. + +- `not-started` - before .start() method was called. - `pending` - immediately after .start() method is called. - `result` - when expression execution completed. - `error` - when execution failed with error. + +Signature: + +```typescript +state: 'not-started' | 'pending' | 'result' | 'error'; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executor._constructor_.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executor._constructor_.md new file mode 100644 index 0000000000000..2d776c9536c82 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executor._constructor_.md @@ -0,0 +1,20 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [Executor](./kibana-plugin-plugins-expressions-public.executor.md) > [(constructor)](./kibana-plugin-plugins-expressions-public.executor._constructor_.md) + +## Executor.(constructor) + +Constructs a new instance of the `Executor` class + +Signature: + +```typescript +constructor(state?: ExecutorState); +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| state | ExecutorState<Context> | | + diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executor.context.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executor.context.md new file mode 100644 index 0000000000000..9a35931bbb26b --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executor.context.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [Executor](./kibana-plugin-plugins-expressions-public.executor.md) > [context](./kibana-plugin-plugins-expressions-public.executor.context.md) + +## Executor.context property + +Signature: + +```typescript +get context(): Record; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executor.createexecution.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executor.createexecution.md new file mode 100644 index 0000000000000..e6765064d4a27 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executor.createexecution.md @@ -0,0 +1,24 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [Executor](./kibana-plugin-plugins-expressions-public.executor.md) > [createExecution](./kibana-plugin-plugins-expressions-public.executor.createexecution.md) + +## Executor.createExecution() method + +Signature: + +```typescript +createExecution = Record, Input = unknown, Output = unknown>(ast: string | ExpressionAstExpression, context?: ExtraContext, { debug }?: ExpressionExecOptions): Execution; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| ast | string | ExpressionAstExpression | | +| context | ExtraContext | | +| { debug } | ExpressionExecOptions | | + +Returns: + +`Execution` + diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executor.createwithdefaults.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executor.createwithdefaults.md new file mode 100644 index 0000000000000..a058d1c9f830e --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executor.createwithdefaults.md @@ -0,0 +1,22 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [Executor](./kibana-plugin-plugins-expressions-public.executor.md) > [createWithDefaults](./kibana-plugin-plugins-expressions-public.executor.createwithdefaults.md) + +## Executor.createWithDefaults() method + +Signature: + +```typescript +static createWithDefaults = Record>(state?: ExecutorState): Executor; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| state | ExecutorState<Ctx> | | + +Returns: + +`Executor` + diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executor.extendcontext.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executor.extendcontext.md new file mode 100644 index 0000000000000..a08fcc839110d --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executor.extendcontext.md @@ -0,0 +1,22 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [Executor](./kibana-plugin-plugins-expressions-public.executor.md) > [extendContext](./kibana-plugin-plugins-expressions-public.executor.extendcontext.md) + +## Executor.extendContext() method + +Signature: + +```typescript +extendContext(extraContext: Record): void; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| extraContext | Record<string, unknown> | | + +Returns: + +`void` + diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executor.fork.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executor.fork.md new file mode 100644 index 0000000000000..65aa7978a5910 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executor.fork.md @@ -0,0 +1,15 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [Executor](./kibana-plugin-plugins-expressions-public.executor.md) > [fork](./kibana-plugin-plugins-expressions-public.executor.fork.md) + +## Executor.fork() method + +Signature: + +```typescript +fork(): Executor; +``` +Returns: + +`Executor` + diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executor.functions.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executor.functions.md new file mode 100644 index 0000000000000..3c55c246c91f8 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executor.functions.md @@ -0,0 +1,15 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [Executor](./kibana-plugin-plugins-expressions-public.executor.md) > [functions](./kibana-plugin-plugins-expressions-public.executor.functions.md) + +## Executor.functions property + +> Warning: This API is now obsolete. +> +> + +Signature: + +```typescript +readonly functions: FunctionsRegistry; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executor.getfunction.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executor.getfunction.md new file mode 100644 index 0000000000000..11d04edc9c97d --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executor.getfunction.md @@ -0,0 +1,22 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [Executor](./kibana-plugin-plugins-expressions-public.executor.md) > [getFunction](./kibana-plugin-plugins-expressions-public.executor.getfunction.md) + +## Executor.getFunction() method + +Signature: + +```typescript +getFunction(name: string): ExpressionFunction | undefined; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| name | string | | + +Returns: + +`ExpressionFunction | undefined` + diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executor.getfunctions.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executor.getfunctions.md new file mode 100644 index 0000000000000..1098c867e4c86 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executor.getfunctions.md @@ -0,0 +1,15 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [Executor](./kibana-plugin-plugins-expressions-public.executor.md) > [getFunctions](./kibana-plugin-plugins-expressions-public.executor.getfunctions.md) + +## Executor.getFunctions() method + +Signature: + +```typescript +getFunctions(): Record; +``` +Returns: + +`Record` + diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executor.gettype.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executor.gettype.md new file mode 100644 index 0000000000000..a0dc6deb21d2c --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executor.gettype.md @@ -0,0 +1,22 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [Executor](./kibana-plugin-plugins-expressions-public.executor.md) > [getType](./kibana-plugin-plugins-expressions-public.executor.gettype.md) + +## Executor.getType() method + +Signature: + +```typescript +getType(name: string): ExpressionType | undefined; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| name | string | | + +Returns: + +`ExpressionType | undefined` + diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executor.gettypes.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executor.gettypes.md new file mode 100644 index 0000000000000..a3c72b135cd31 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executor.gettypes.md @@ -0,0 +1,15 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [Executor](./kibana-plugin-plugins-expressions-public.executor.md) > [getTypes](./kibana-plugin-plugins-expressions-public.executor.gettypes.md) + +## Executor.getTypes() method + +Signature: + +```typescript +getTypes(): Record; +``` +Returns: + +`Record` + diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executor.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executor.md new file mode 100644 index 0000000000000..b71c8c79c068f --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executor.md @@ -0,0 +1,43 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [Executor](./kibana-plugin-plugins-expressions-public.executor.md) + +## Executor class + +Signature: + +```typescript +export declare class Executor = Record> +``` + +## Constructors + +| Constructor | Modifiers | Description | +| --- | --- | --- | +| [(constructor)(state)](./kibana-plugin-plugins-expressions-public.executor._constructor_.md) | | Constructs a new instance of the Executor class | + +## Properties + +| Property | Modifiers | Type | Description | +| --- | --- | --- | --- | +| [context](./kibana-plugin-plugins-expressions-public.executor.context.md) | | Record<string, unknown> | | +| [functions](./kibana-plugin-plugins-expressions-public.executor.functions.md) | | FunctionsRegistry | | +| [state](./kibana-plugin-plugins-expressions-public.executor.state.md) | | ExecutorContainer<Context> | | +| [types](./kibana-plugin-plugins-expressions-public.executor.types.md) | | TypesRegistry | | + +## Methods + +| Method | Modifiers | Description | +| --- | --- | --- | +| [createExecution(ast, context, { debug })](./kibana-plugin-plugins-expressions-public.executor.createexecution.md) | | | +| [createWithDefaults(state)](./kibana-plugin-plugins-expressions-public.executor.createwithdefaults.md) | static | | +| [extendContext(extraContext)](./kibana-plugin-plugins-expressions-public.executor.extendcontext.md) | | | +| [fork()](./kibana-plugin-plugins-expressions-public.executor.fork.md) | | | +| [getFunction(name)](./kibana-plugin-plugins-expressions-public.executor.getfunction.md) | | | +| [getFunctions()](./kibana-plugin-plugins-expressions-public.executor.getfunctions.md) | | | +| [getType(name)](./kibana-plugin-plugins-expressions-public.executor.gettype.md) | | | +| [getTypes()](./kibana-plugin-plugins-expressions-public.executor.gettypes.md) | | | +| [registerFunction(functionDefinition)](./kibana-plugin-plugins-expressions-public.executor.registerfunction.md) | | | +| [registerType(typeDefinition)](./kibana-plugin-plugins-expressions-public.executor.registertype.md) | | | +| [run(ast, input, context)](./kibana-plugin-plugins-expressions-public.executor.run.md) | | Execute expression and return result. | + diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executor.registerfunction.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executor.registerfunction.md new file mode 100644 index 0000000000000..b4217fa492a20 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executor.registerfunction.md @@ -0,0 +1,22 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [Executor](./kibana-plugin-plugins-expressions-public.executor.md) > [registerFunction](./kibana-plugin-plugins-expressions-public.executor.registerfunction.md) + +## Executor.registerFunction() method + +Signature: + +```typescript +registerFunction(functionDefinition: AnyExpressionFunctionDefinition | (() => AnyExpressionFunctionDefinition)): void; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| functionDefinition | AnyExpressionFunctionDefinition | (() => AnyExpressionFunctionDefinition) | | + +Returns: + +`void` + diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executor.registertype.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executor.registertype.md new file mode 100644 index 0000000000000..f56e5ffcfb9ee --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executor.registertype.md @@ -0,0 +1,22 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [Executor](./kibana-plugin-plugins-expressions-public.executor.md) > [registerType](./kibana-plugin-plugins-expressions-public.executor.registertype.md) + +## Executor.registerType() method + +Signature: + +```typescript +registerType(typeDefinition: AnyExpressionTypeDefinition | (() => AnyExpressionTypeDefinition)): void; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| typeDefinition | AnyExpressionTypeDefinition | (() => AnyExpressionTypeDefinition) | | + +Returns: + +`void` + diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executor.run.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executor.run.md new file mode 100644 index 0000000000000..e06ce733acd43 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executor.run.md @@ -0,0 +1,26 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [Executor](./kibana-plugin-plugins-expressions-public.executor.md) > [run](./kibana-plugin-plugins-expressions-public.executor.run.md) + +## Executor.run() method + +Execute expression and return result. + +Signature: + +```typescript +run = Record>(ast: string | ExpressionAstExpression, input: Input, context?: ExtraContext): Promise; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| ast | string | ExpressionAstExpression | | +| input | Input | | +| context | ExtraContext | | + +Returns: + +`Promise` + diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executor.state.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executor.state.md new file mode 100644 index 0000000000000..e9b7006980ceb --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executor.state.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [Executor](./kibana-plugin-plugins-expressions-public.executor.md) > [state](./kibana-plugin-plugins-expressions-public.executor.state.md) + +## Executor.state property + +Signature: + +```typescript +readonly state: ExecutorContainer; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executor.types.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executor.types.md new file mode 100644 index 0000000000000..1ab9a5c4621be --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executor.types.md @@ -0,0 +1,15 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [Executor](./kibana-plugin-plugins-expressions-public.executor.md) > [types](./kibana-plugin-plugins-expressions-public.executor.types.md) + +## Executor.types property + +> Warning: This API is now obsolete. +> +> + +Signature: + +```typescript +readonly types: TypesRegistry; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executorcontainer.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executorcontainer.md new file mode 100644 index 0000000000000..f48b001593f94 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executorcontainer.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExecutorContainer](./kibana-plugin-plugins-expressions-public.executorcontainer.md) + +## ExecutorContainer type + +Signature: + +```typescript +export declare type ExecutorContainer = Record> = StateContainer, ExecutorPureTransitions, ExecutorPureSelectors>; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executorstate.context.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executorstate.context.md new file mode 100644 index 0000000000000..d52074b0eecdd --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executorstate.context.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExecutorState](./kibana-plugin-plugins-expressions-public.executorstate.md) > [context](./kibana-plugin-plugins-expressions-public.executorstate.context.md) + +## ExecutorState.context property + +Signature: + +```typescript +context: Context; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executorstate.functions.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executorstate.functions.md new file mode 100644 index 0000000000000..034caf27aaef7 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executorstate.functions.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExecutorState](./kibana-plugin-plugins-expressions-public.executorstate.md) > [functions](./kibana-plugin-plugins-expressions-public.executorstate.functions.md) + +## ExecutorState.functions property + +Signature: + +```typescript +functions: Record; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executorstate.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executorstate.md new file mode 100644 index 0000000000000..e120631285887 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executorstate.md @@ -0,0 +1,20 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExecutorState](./kibana-plugin-plugins-expressions-public.executorstate.md) + +## ExecutorState interface + +Signature: + +```typescript +export interface ExecutorState = Record> +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [context](./kibana-plugin-plugins-expressions-public.executorstate.context.md) | Context | | +| [functions](./kibana-plugin-plugins-expressions-public.executorstate.functions.md) | Record<string, ExpressionFunction> | | +| [types](./kibana-plugin-plugins-expressions-public.executorstate.types.md) | Record<string, ExpressionType> | | + diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executorstate.types.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executorstate.types.md new file mode 100644 index 0000000000000..00cf80c271684 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executorstate.types.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExecutorState](./kibana-plugin-plugins-expressions-public.executorstate.md) > [types](./kibana-plugin-plugins-expressions-public.executorstate.types.md) + +## ExecutorState.types property + +Signature: + +```typescript +types: Record; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionastargument.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionastargument.md new file mode 100644 index 0000000000000..559cec0e841ac --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionastargument.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionAstArgument](./kibana-plugin-plugins-expressions-public.expressionastargument.md) + +## ExpressionAstArgument type + +Signature: + +```typescript +export declare type ExpressionAstArgument = string | boolean | number | ExpressionAstExpression; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionastexpression.chain.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionastexpression.chain.md new file mode 100644 index 0000000000000..b50ac83036ffe --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionastexpression.chain.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionAstExpression](./kibana-plugin-plugins-expressions-public.expressionastexpression.md) > [chain](./kibana-plugin-plugins-expressions-public.expressionastexpression.chain.md) + +## ExpressionAstExpression.chain property + +Signature: + +```typescript +chain: ExpressionAstFunction[]; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionastexpression.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionastexpression.md new file mode 100644 index 0000000000000..537659c51dce8 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionastexpression.md @@ -0,0 +1,19 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionAstExpression](./kibana-plugin-plugins-expressions-public.expressionastexpression.md) + +## ExpressionAstExpression interface + +Signature: + +```typescript +export interface ExpressionAstExpression +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [chain](./kibana-plugin-plugins-expressions-public.expressionastexpression.chain.md) | ExpressionAstFunction[] | | +| [type](./kibana-plugin-plugins-expressions-public.expressionastexpression.type.md) | 'expression' | | + diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionastexpression.type.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionastexpression.type.md new file mode 100644 index 0000000000000..34a86e235a911 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionastexpression.type.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionAstExpression](./kibana-plugin-plugins-expressions-public.expressionastexpression.md) > [type](./kibana-plugin-plugins-expressions-public.expressionastexpression.type.md) + +## ExpressionAstExpression.type property + +Signature: + +```typescript +type: 'expression'; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionastexpressionbuilder.findfunction.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionastexpressionbuilder.findfunction.md new file mode 100644 index 0000000000000..d31f04ad5bf77 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionastexpressionbuilder.findfunction.md @@ -0,0 +1,15 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionAstExpressionBuilder](./kibana-plugin-plugins-expressions-public.expressionastexpressionbuilder.md) > [findFunction](./kibana-plugin-plugins-expressions-public.expressionastexpressionbuilder.findfunction.md) + +## ExpressionAstExpressionBuilder.findFunction property + +Recursively searches expression for all ocurrences of the function, including in subexpressions. + +Useful when performing migrations on a specific function, as you can iterate over the array of references and update all functions at once. + +Signature: + +```typescript +findFunction: (fnName: InferFunctionDefinition['name']) => Array> | []; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionastexpressionbuilder.functions.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionastexpressionbuilder.functions.md new file mode 100644 index 0000000000000..ceaa4c89fb237 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionastexpressionbuilder.functions.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionAstExpressionBuilder](./kibana-plugin-plugins-expressions-public.expressionastexpressionbuilder.md) > [functions](./kibana-plugin-plugins-expressions-public.expressionastexpressionbuilder.functions.md) + +## ExpressionAstExpressionBuilder.functions property + +Array of each of the `buildExpressionFunction()` instances in this expression. Use this to remove or reorder functions in the expression. + +Signature: + +```typescript +functions: ExpressionAstFunctionBuilder[]; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionastexpressionbuilder.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionastexpressionbuilder.md new file mode 100644 index 0000000000000..079e0b3dd8ac1 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionastexpressionbuilder.md @@ -0,0 +1,22 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionAstExpressionBuilder](./kibana-plugin-plugins-expressions-public.expressionastexpressionbuilder.md) + +## ExpressionAstExpressionBuilder interface + +Signature: + +```typescript +export interface ExpressionAstExpressionBuilder +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [findFunction](./kibana-plugin-plugins-expressions-public.expressionastexpressionbuilder.findfunction.md) | <FnDef extends AnyExpressionFunctionDefinition = AnyExpressionFunctionDefinition>(fnName: InferFunctionDefinition<FnDef>['name']) => Array<ExpressionAstFunctionBuilder<FnDef>> | [] | Recursively searches expression for all ocurrences of the function, including in subexpressions.Useful when performing migrations on a specific function, as you can iterate over the array of references and update all functions at once. | +| [functions](./kibana-plugin-plugins-expressions-public.expressionastexpressionbuilder.functions.md) | ExpressionAstFunctionBuilder[] | Array of each of the buildExpressionFunction() instances in this expression. Use this to remove or reorder functions in the expression. | +| [toAst](./kibana-plugin-plugins-expressions-public.expressionastexpressionbuilder.toast.md) | () => ExpressionAstExpression | Converts expression to an AST. ExpressionAstExpression | +| [toString](./kibana-plugin-plugins-expressions-public.expressionastexpressionbuilder.tostring.md) | () => string | Converts expression to an expression string. string | +| [type](./kibana-plugin-plugins-expressions-public.expressionastexpressionbuilder.type.md) | 'expression_builder' | Used to identify expression builder objects. | + diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionastexpressionbuilder.toast.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionastexpressionbuilder.toast.md new file mode 100644 index 0000000000000..e0b10033f6f3a --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionastexpressionbuilder.toast.md @@ -0,0 +1,15 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionAstExpressionBuilder](./kibana-plugin-plugins-expressions-public.expressionastexpressionbuilder.md) > [toAst](./kibana-plugin-plugins-expressions-public.expressionastexpressionbuilder.toast.md) + +## ExpressionAstExpressionBuilder.toAst property + +Converts expression to an AST. + + `ExpressionAstExpression` + +Signature: + +```typescript +toAst: () => ExpressionAstExpression; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionastexpressionbuilder.tostring.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionastexpressionbuilder.tostring.md new file mode 100644 index 0000000000000..6a9a25256c0a3 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionastexpressionbuilder.tostring.md @@ -0,0 +1,15 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionAstExpressionBuilder](./kibana-plugin-plugins-expressions-public.expressionastexpressionbuilder.md) > [toString](./kibana-plugin-plugins-expressions-public.expressionastexpressionbuilder.tostring.md) + +## ExpressionAstExpressionBuilder.toString property + +Converts expression to an expression string. + + `string` + +Signature: + +```typescript +toString: () => string; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionastexpressionbuilder.type.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionastexpressionbuilder.type.md new file mode 100644 index 0000000000000..2aa8d5089aa29 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionastexpressionbuilder.type.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionAstExpressionBuilder](./kibana-plugin-plugins-expressions-public.expressionastexpressionbuilder.md) > [type](./kibana-plugin-plugins-expressions-public.expressionastexpressionbuilder.type.md) + +## ExpressionAstExpressionBuilder.type property + +Used to identify expression builder objects. + +Signature: + +```typescript +type: 'expression_builder'; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionastfunction.arguments.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionastfunction.arguments.md new file mode 100644 index 0000000000000..72b44e8319542 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionastfunction.arguments.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionAstFunction](./kibana-plugin-plugins-expressions-public.expressionastfunction.md) > [arguments](./kibana-plugin-plugins-expressions-public.expressionastfunction.arguments.md) + +## ExpressionAstFunction.arguments property + +Signature: + +```typescript +arguments: Record; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionastfunction.debug.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionastfunction.debug.md new file mode 100644 index 0000000000000..36101a110979a --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionastfunction.debug.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionAstFunction](./kibana-plugin-plugins-expressions-public.expressionastfunction.md) > [debug](./kibana-plugin-plugins-expressions-public.expressionastfunction.debug.md) + +## ExpressionAstFunction.debug property + +Debug information added to each function when expression is executed in \*debug mode\*. + +Signature: + +```typescript +debug?: ExpressionAstFunctionDebug; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionastfunction.function.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionastfunction.function.md new file mode 100644 index 0000000000000..1840fff4b625f --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionastfunction.function.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionAstFunction](./kibana-plugin-plugins-expressions-public.expressionastfunction.md) > [function](./kibana-plugin-plugins-expressions-public.expressionastfunction.function.md) + +## ExpressionAstFunction.function property + +Signature: + +```typescript +function: string; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionastfunction.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionastfunction.md new file mode 100644 index 0000000000000..1004e58759806 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionastfunction.md @@ -0,0 +1,21 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionAstFunction](./kibana-plugin-plugins-expressions-public.expressionastfunction.md) + +## ExpressionAstFunction interface + +Signature: + +```typescript +export interface ExpressionAstFunction +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [arguments](./kibana-plugin-plugins-expressions-public.expressionastfunction.arguments.md) | Record<string, ExpressionAstArgument[]> | | +| [debug](./kibana-plugin-plugins-expressions-public.expressionastfunction.debug.md) | ExpressionAstFunctionDebug | Debug information added to each function when expression is executed in \*debug mode\*. | +| [function](./kibana-plugin-plugins-expressions-public.expressionastfunction.function.md) | string | | +| [type](./kibana-plugin-plugins-expressions-public.expressionastfunction.type.md) | 'function' | | + diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionastfunction.type.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionastfunction.type.md new file mode 100644 index 0000000000000..f7f8786430191 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionastfunction.type.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionAstFunction](./kibana-plugin-plugins-expressions-public.expressionastfunction.md) > [type](./kibana-plugin-plugins-expressions-public.expressionastfunction.type.md) + +## ExpressionAstFunction.type property + +Signature: + +```typescript +type: 'function'; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionastfunctionbuilder.addargument.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionastfunctionbuilder.addargument.md new file mode 100644 index 0000000000000..da7f0ebc826c1 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionastfunctionbuilder.addargument.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionAstFunctionBuilder](./kibana-plugin-plugins-expressions-public.expressionastfunctionbuilder.md) > [addArgument](./kibana-plugin-plugins-expressions-public.expressionastfunctionbuilder.addargument.md) + +## ExpressionAstFunctionBuilder.addArgument property + +Adds an additional argument to the function. For multi-args, this should be called once for each new arg. Note that TS will not enforce whether multi-args are available, so only use this to update an existing arg if you are certain it is a multi-arg. + +Signature: + +```typescript +addArgument:
    >(name: A, value: FunctionArgs[A] | ExpressionAstExpressionBuilder) => this; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionastfunctionbuilder.arguments.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionastfunctionbuilder.arguments.md new file mode 100644 index 0000000000000..4a95d20d6c983 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionastfunctionbuilder.arguments.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionAstFunctionBuilder](./kibana-plugin-plugins-expressions-public.expressionastfunctionbuilder.md) > [arguments](./kibana-plugin-plugins-expressions-public.expressionastfunctionbuilder.arguments.md) + +## ExpressionAstFunctionBuilder.arguments property + +Object of all args currently added to the function. This is structured similarly to `ExpressionAstFunction['arguments']`, however any subexpressions are returned as expression builder instances instead of expression ASTs. + +Signature: + +```typescript +arguments: FunctionBuilderArguments; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionastfunctionbuilder.getargument.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionastfunctionbuilder.getargument.md new file mode 100644 index 0000000000000..0df9c80c632b1 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionastfunctionbuilder.getargument.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionAstFunctionBuilder](./kibana-plugin-plugins-expressions-public.expressionastfunctionbuilder.md) > [getArgument](./kibana-plugin-plugins-expressions-public.expressionastfunctionbuilder.getargument.md) + +## ExpressionAstFunctionBuilder.getArgument property + +Retrieves an existing argument by name. Useful when you want to retrieve the current array of args and add something to it before calling `replaceArgument`. Any subexpression arguments will be returned as expression builder instances. + +Signature: + +```typescript +getArgument: >(name: A) => Array[A] | ExpressionAstExpressionBuilder> | undefined; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionastfunctionbuilder.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionastfunctionbuilder.md new file mode 100644 index 0000000000000..b05504af28d9b --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionastfunctionbuilder.md @@ -0,0 +1,26 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionAstFunctionBuilder](./kibana-plugin-plugins-expressions-public.expressionastfunctionbuilder.md) + +## ExpressionAstFunctionBuilder interface + +Signature: + +```typescript +export interface ExpressionAstFunctionBuilder +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [addArgument](./kibana-plugin-plugins-expressions-public.expressionastfunctionbuilder.addargument.md) | <A extends FunctionArgName<FnDef>>(name: A, value: FunctionArgs<FnDef>[A] | ExpressionAstExpressionBuilder) => this | Adds an additional argument to the function. For multi-args, this should be called once for each new arg. Note that TS will not enforce whether multi-args are available, so only use this to update an existing arg if you are certain it is a multi-arg. | +| [arguments](./kibana-plugin-plugins-expressions-public.expressionastfunctionbuilder.arguments.md) | FunctionBuilderArguments<FnDef> | Object of all args currently added to the function. This is structured similarly to ExpressionAstFunction['arguments'], however any subexpressions are returned as expression builder instances instead of expression ASTs. | +| [getArgument](./kibana-plugin-plugins-expressions-public.expressionastfunctionbuilder.getargument.md) | <A extends FunctionArgName<FnDef>>(name: A) => Array<FunctionArgs<FnDef>[A] | ExpressionAstExpressionBuilder> | undefined | Retrieves an existing argument by name. Useful when you want to retrieve the current array of args and add something to it before calling replaceArgument. Any subexpression arguments will be returned as expression builder instances. | +| [name](./kibana-plugin-plugins-expressions-public.expressionastfunctionbuilder.name.md) | InferFunctionDefinition<FnDef>['name'] | Name of this expression function. | +| [removeArgument](./kibana-plugin-plugins-expressions-public.expressionastfunctionbuilder.removeargument.md) | <A extends OptionalKeys<FunctionArgs<FnDef>>>(name: A) => this | Removes an (optional) argument from the function.TypeScript will enforce that you only remove optional arguments. For manipulating required args, use replaceArgument. | +| [replaceArgument](./kibana-plugin-plugins-expressions-public.expressionastfunctionbuilder.replaceargument.md) | <A extends FunctionArgName<FnDef>>(name: A, value: Array<FunctionArgs<FnDef>[A] | ExpressionAstExpressionBuilder>) => this | Overwrites an existing argument with a new value. In order to support multi-args, the value given must always be an array. | +| [toAst](./kibana-plugin-plugins-expressions-public.expressionastfunctionbuilder.toast.md) | () => ExpressionAstFunction | Converts function to an AST. ExpressionAstFunction | +| [toString](./kibana-plugin-plugins-expressions-public.expressionastfunctionbuilder.tostring.md) | () => string | Converts function to an expression string. string | +| [type](./kibana-plugin-plugins-expressions-public.expressionastfunctionbuilder.type.md) | 'expression_function_builder' | Used to identify expression function builder objects. | + diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionastfunctionbuilder.name.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionastfunctionbuilder.name.md new file mode 100644 index 0000000000000..5bcf965426dbd --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionastfunctionbuilder.name.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionAstFunctionBuilder](./kibana-plugin-plugins-expressions-public.expressionastfunctionbuilder.md) > [name](./kibana-plugin-plugins-expressions-public.expressionastfunctionbuilder.name.md) + +## ExpressionAstFunctionBuilder.name property + +Name of this expression function. + +Signature: + +```typescript +name: InferFunctionDefinition['name']; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionastfunctionbuilder.removeargument.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionastfunctionbuilder.removeargument.md new file mode 100644 index 0000000000000..1883618c96d53 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionastfunctionbuilder.removeargument.md @@ -0,0 +1,15 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionAstFunctionBuilder](./kibana-plugin-plugins-expressions-public.expressionastfunctionbuilder.md) > [removeArgument](./kibana-plugin-plugins-expressions-public.expressionastfunctionbuilder.removeargument.md) + +## ExpressionAstFunctionBuilder.removeArgument property + +Removes an (optional) argument from the function. + +TypeScript will enforce that you only remove optional arguments. For manipulating required args, use `replaceArgument`. + +Signature: + +```typescript +removeArgument: >>(name: A) => this; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionastfunctionbuilder.replaceargument.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionastfunctionbuilder.replaceargument.md new file mode 100644 index 0000000000000..81709f6e94f0a --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionastfunctionbuilder.replaceargument.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionAstFunctionBuilder](./kibana-plugin-plugins-expressions-public.expressionastfunctionbuilder.md) > [replaceArgument](./kibana-plugin-plugins-expressions-public.expressionastfunctionbuilder.replaceargument.md) + +## ExpressionAstFunctionBuilder.replaceArgument property + +Overwrites an existing argument with a new value. In order to support multi-args, the value given must always be an array. + +Signature: + +```typescript +replaceArgument: >(name: A, value: Array[A] | ExpressionAstExpressionBuilder>) => this; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionastfunctionbuilder.toast.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionastfunctionbuilder.toast.md new file mode 100644 index 0000000000000..bf79726c881ae --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionastfunctionbuilder.toast.md @@ -0,0 +1,15 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionAstFunctionBuilder](./kibana-plugin-plugins-expressions-public.expressionastfunctionbuilder.md) > [toAst](./kibana-plugin-plugins-expressions-public.expressionastfunctionbuilder.toast.md) + +## ExpressionAstFunctionBuilder.toAst property + +Converts function to an AST. + + `ExpressionAstFunction` + +Signature: + +```typescript +toAst: () => ExpressionAstFunction; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionastfunctionbuilder.tostring.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionastfunctionbuilder.tostring.md new file mode 100644 index 0000000000000..5c8d0c806d372 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionastfunctionbuilder.tostring.md @@ -0,0 +1,15 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionAstFunctionBuilder](./kibana-plugin-plugins-expressions-public.expressionastfunctionbuilder.md) > [toString](./kibana-plugin-plugins-expressions-public.expressionastfunctionbuilder.tostring.md) + +## ExpressionAstFunctionBuilder.toString property + +Converts function to an expression string. + + `string` + +Signature: + +```typescript +toString: () => string; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionastfunctionbuilder.type.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionastfunctionbuilder.type.md new file mode 100644 index 0000000000000..b88876b14f367 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionastfunctionbuilder.type.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionAstFunctionBuilder](./kibana-plugin-plugins-expressions-public.expressionastfunctionbuilder.md) > [type](./kibana-plugin-plugins-expressions-public.expressionastfunctionbuilder.type.md) + +## ExpressionAstFunctionBuilder.type property + +Used to identify expression function builder objects. + +Signature: + +```typescript +type: 'expression_function_builder'; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionastnode.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionastnode.md new file mode 100644 index 0000000000000..4e05b6a18374c --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionastnode.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionAstNode](./kibana-plugin-plugins-expressions-public.expressionastnode.md) + +## ExpressionAstNode type + +Signature: + +```typescript +export declare type ExpressionAstNode = ExpressionAstExpression | ExpressionAstFunction | ExpressionAstArgument; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionexecutor.interpreter.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionexecutor.interpreter.md new file mode 100644 index 0000000000000..6741634379dc1 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionexecutor.interpreter.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionExecutor](./kibana-plugin-plugins-expressions-public.expressionexecutor.md) > [interpreter](./kibana-plugin-plugins-expressions-public.expressionexecutor.interpreter.md) + +## ExpressionExecutor.interpreter property + +Signature: + +```typescript +interpreter: ExpressionInterpreter; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionexecutor.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionexecutor.md new file mode 100644 index 0000000000000..f0c457af52d22 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionexecutor.md @@ -0,0 +1,23 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionExecutor](./kibana-plugin-plugins-expressions-public.expressionexecutor.md) + +## ExpressionExecutor interface + +> Warning: This API is now obsolete. +> +> This type if remainder from legacy platform, will be deleted going further. +> + +Signature: + +```typescript +export interface ExpressionExecutor +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [interpreter](./kibana-plugin-plugins-expressions-public.expressionexecutor.interpreter.md) | ExpressionInterpreter | | + diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunction._constructor_.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunction._constructor_.md new file mode 100644 index 0000000000000..9c711b47c89d0 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunction._constructor_.md @@ -0,0 +1,20 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionFunction](./kibana-plugin-plugins-expressions-public.expressionfunction.md) > [(constructor)](./kibana-plugin-plugins-expressions-public.expressionfunction._constructor_.md) + +## ExpressionFunction.(constructor) + +Constructs a new instance of the `ExpressionFunction` class + +Signature: + +```typescript +constructor(functionDefinition: AnyExpressionFunctionDefinition); +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| functionDefinition | AnyExpressionFunctionDefinition | | + diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunction.accepts.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunction.accepts.md new file mode 100644 index 0000000000000..7a65878cd5a2d --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunction.accepts.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionFunction](./kibana-plugin-plugins-expressions-public.expressionfunction.md) > [accepts](./kibana-plugin-plugins-expressions-public.expressionfunction.accepts.md) + +## ExpressionFunction.accepts property + +Signature: + +```typescript +accepts: (type: string) => boolean; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunction.aliases.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunction.aliases.md new file mode 100644 index 0000000000000..550620386a892 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunction.aliases.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionFunction](./kibana-plugin-plugins-expressions-public.expressionfunction.md) > [aliases](./kibana-plugin-plugins-expressions-public.expressionfunction.aliases.md) + +## ExpressionFunction.aliases property + +Aliases that can be used instead of `name`. + +Signature: + +```typescript +aliases: string[]; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunction.args.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunction.args.md new file mode 100644 index 0000000000000..e14c08b8b7079 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunction.args.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionFunction](./kibana-plugin-plugins-expressions-public.expressionfunction.md) > [args](./kibana-plugin-plugins-expressions-public.expressionfunction.args.md) + +## ExpressionFunction.args property + +Specification of expression function parameters. + +Signature: + +```typescript +args: Record; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunction.fn.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunction.fn.md new file mode 100644 index 0000000000000..d94d9af9bf0f9 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunction.fn.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionFunction](./kibana-plugin-plugins-expressions-public.expressionfunction.md) > [fn](./kibana-plugin-plugins-expressions-public.expressionfunction.fn.md) + +## ExpressionFunction.fn property + +Function to run function (context, args) + +Signature: + +```typescript +fn: (input: ExpressionValue, params: Record, handlers: object) => ExpressionValue; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunction.help.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunction.help.md new file mode 100644 index 0000000000000..bbf70e11192eb --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunction.help.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionFunction](./kibana-plugin-plugins-expressions-public.expressionfunction.md) > [help](./kibana-plugin-plugins-expressions-public.expressionfunction.help.md) + +## ExpressionFunction.help property + +A short help text. + +Signature: + +```typescript +help: string; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunction.inputtypes.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunction.inputtypes.md new file mode 100644 index 0000000000000..865c856746062 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunction.inputtypes.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionFunction](./kibana-plugin-plugins-expressions-public.expressionfunction.md) > [inputTypes](./kibana-plugin-plugins-expressions-public.expressionfunction.inputtypes.md) + +## ExpressionFunction.inputTypes property + +Type of inputs that this function supports. + +Signature: + +```typescript +inputTypes: string[] | undefined; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunction.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunction.md new file mode 100644 index 0000000000000..5ca67e40c93ec --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunction.md @@ -0,0 +1,31 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionFunction](./kibana-plugin-plugins-expressions-public.expressionfunction.md) + +## ExpressionFunction class + +Signature: + +```typescript +export declare class ExpressionFunction +``` + +## Constructors + +| Constructor | Modifiers | Description | +| --- | --- | --- | +| [(constructor)(functionDefinition)](./kibana-plugin-plugins-expressions-public.expressionfunction._constructor_.md) | | Constructs a new instance of the ExpressionFunction class | + +## Properties + +| Property | Modifiers | Type | Description | +| --- | --- | --- | --- | +| [accepts](./kibana-plugin-plugins-expressions-public.expressionfunction.accepts.md) | | (type: string) => boolean | | +| [aliases](./kibana-plugin-plugins-expressions-public.expressionfunction.aliases.md) | | string[] | Aliases that can be used instead of name. | +| [args](./kibana-plugin-plugins-expressions-public.expressionfunction.args.md) | | Record<string, ExpressionFunctionParameter> | Specification of expression function parameters. | +| [fn](./kibana-plugin-plugins-expressions-public.expressionfunction.fn.md) | | (input: ExpressionValue, params: Record<string, any>, handlers: object) => ExpressionValue | Function to run function (context, args) | +| [help](./kibana-plugin-plugins-expressions-public.expressionfunction.help.md) | | string | A short help text. | +| [inputTypes](./kibana-plugin-plugins-expressions-public.expressionfunction.inputtypes.md) | | string[] | undefined | Type of inputs that this function supports. | +| [name](./kibana-plugin-plugins-expressions-public.expressionfunction.name.md) | | string | Name of function | +| [type](./kibana-plugin-plugins-expressions-public.expressionfunction.type.md) | | string | Return type of function. This SHOULD be supplied. We use it for UI and autocomplete hinting. We may also use it for optimizations in the future. | + diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunction.name.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunction.name.md new file mode 100644 index 0000000000000..2858089ea67de --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunction.name.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionFunction](./kibana-plugin-plugins-expressions-public.expressionfunction.md) > [name](./kibana-plugin-plugins-expressions-public.expressionfunction.name.md) + +## ExpressionFunction.name property + +Name of function + +Signature: + +```typescript +name: string; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunction.type.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunction.type.md new file mode 100644 index 0000000000000..7a7bc129a1719 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunction.type.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionFunction](./kibana-plugin-plugins-expressions-public.expressionfunction.md) > [type](./kibana-plugin-plugins-expressions-public.expressionfunction.type.md) + +## ExpressionFunction.type property + +Return type of function. This SHOULD be supplied. We use it for UI and autocomplete hinting. We may also use it for optimizations in the future. + +Signature: + +```typescript +type: string; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunctiondefinition.aliases.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunctiondefinition.aliases.md new file mode 100644 index 0000000000000..bca3600b6d416 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunctiondefinition.aliases.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionFunctionDefinition](./kibana-plugin-plugins-expressions-public.expressionfunctiondefinition.md) > [aliases](./kibana-plugin-plugins-expressions-public.expressionfunctiondefinition.aliases.md) + +## ExpressionFunctionDefinition.aliases property + + What is this? + +Signature: + +```typescript +aliases?: string[]; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunctiondefinition.args.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunctiondefinition.args.md new file mode 100644 index 0000000000000..65ead35adf0d6 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunctiondefinition.args.md @@ -0,0 +1,15 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionFunctionDefinition](./kibana-plugin-plugins-expressions-public.expressionfunctiondefinition.md) > [args](./kibana-plugin-plugins-expressions-public.expressionfunctiondefinition.args.md) + +## ExpressionFunctionDefinition.args property + +Specification of arguments that function supports. This list will also be used for autocomplete functionality when your function is being edited. + +Signature: + +```typescript +args: { + [key in keyof Arguments]: ArgumentType; + }; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunctiondefinition.context.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunctiondefinition.context.md new file mode 100644 index 0000000000000..34bbfc7976007 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunctiondefinition.context.md @@ -0,0 +1,18 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionFunctionDefinition](./kibana-plugin-plugins-expressions-public.expressionfunctiondefinition.md) > [context](./kibana-plugin-plugins-expressions-public.expressionfunctiondefinition.context.md) + +## ExpressionFunctionDefinition.context property + +> Warning: This API is now obsolete. +> +> Use `inputTypes` instead. +> + +Signature: + +```typescript +context?: { + types: AnyExpressionFunctionDefinition['inputTypes']; + }; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunctiondefinition.fn.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunctiondefinition.fn.md new file mode 100644 index 0000000000000..a2180c0cee665 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunctiondefinition.fn.md @@ -0,0 +1,26 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionFunctionDefinition](./kibana-plugin-plugins-expressions-public.expressionfunctiondefinition.md) > [fn](./kibana-plugin-plugins-expressions-public.expressionfunctiondefinition.fn.md) + +## ExpressionFunctionDefinition.fn() method + +The actual implementation of the function. + +Signature: + +```typescript +fn(input: Input, args: Arguments, context: Context): Output; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| input | Input | | +| args | Arguments | | +| context | Context | | + +Returns: + +`Output` + diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunctiondefinition.help.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunctiondefinition.help.md new file mode 100644 index 0000000000000..ad99bb3a14a0b --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunctiondefinition.help.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionFunctionDefinition](./kibana-plugin-plugins-expressions-public.expressionfunctiondefinition.md) > [help](./kibana-plugin-plugins-expressions-public.expressionfunctiondefinition.help.md) + +## ExpressionFunctionDefinition.help property + +Help text displayed in the Expression editor. This text should be internationalized. + +Signature: + +```typescript +help: string; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunctiondefinition.inputtypes.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunctiondefinition.inputtypes.md new file mode 100644 index 0000000000000..06c15dba514c2 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunctiondefinition.inputtypes.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionFunctionDefinition](./kibana-plugin-plugins-expressions-public.expressionfunctiondefinition.md) > [inputTypes](./kibana-plugin-plugins-expressions-public.expressionfunctiondefinition.inputtypes.md) + +## ExpressionFunctionDefinition.inputTypes property + +List of allowed type names for input value of this function. If this property is set the input of function will be cast to the first possible type in this list. If this property is missing the input will be provided to the function as-is. + +Signature: + +```typescript +inputTypes?: Array>; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunctiondefinition.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunctiondefinition.md new file mode 100644 index 0000000000000..bc801542f81ac --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunctiondefinition.md @@ -0,0 +1,32 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionFunctionDefinition](./kibana-plugin-plugins-expressions-public.expressionfunctiondefinition.md) + +## ExpressionFunctionDefinition interface + +`ExpressionFunctionDefinition` is the interface plugins have to implement to register a function in `expressions` plugin. + +Signature: + +```typescript +export interface ExpressionFunctionDefinition, Output, Context extends ExecutionContext = ExecutionContext> +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [aliases](./kibana-plugin-plugins-expressions-public.expressionfunctiondefinition.aliases.md) | string[] | What is this? | +| [args](./kibana-plugin-plugins-expressions-public.expressionfunctiondefinition.args.md) | {
    [key in keyof Arguments]: ArgumentType<Arguments[key]>;
    } | Specification of arguments that function supports. This list will also be used for autocomplete functionality when your function is being edited. | +| [context](./kibana-plugin-plugins-expressions-public.expressionfunctiondefinition.context.md) | {
    types: AnyExpressionFunctionDefinition['inputTypes'];
    } | | +| [help](./kibana-plugin-plugins-expressions-public.expressionfunctiondefinition.help.md) | string | Help text displayed in the Expression editor. This text should be internationalized. | +| [inputTypes](./kibana-plugin-plugins-expressions-public.expressionfunctiondefinition.inputtypes.md) | Array<TypeToString<Input>> | List of allowed type names for input value of this function. If this property is set the input of function will be cast to the first possible type in this list. If this property is missing the input will be provided to the function as-is. | +| [name](./kibana-plugin-plugins-expressions-public.expressionfunctiondefinition.name.md) | Name | The name of the function, as will be used in expression. | +| [type](./kibana-plugin-plugins-expressions-public.expressionfunctiondefinition.type.md) | TypeToString<UnwrapPromiseOrReturn<Output>> | Name of type of value this function outputs. | + +## Methods + +| Method | Description | +| --- | --- | +| [fn(input, args, context)](./kibana-plugin-plugins-expressions-public.expressionfunctiondefinition.fn.md) | The actual implementation of the function. | + diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunctiondefinition.name.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunctiondefinition.name.md new file mode 100644 index 0000000000000..1c74a25851c96 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunctiondefinition.name.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionFunctionDefinition](./kibana-plugin-plugins-expressions-public.expressionfunctiondefinition.md) > [name](./kibana-plugin-plugins-expressions-public.expressionfunctiondefinition.name.md) + +## ExpressionFunctionDefinition.name property + +The name of the function, as will be used in expression. + +Signature: + +```typescript +name: Name; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunctiondefinition.type.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunctiondefinition.type.md new file mode 100644 index 0000000000000..4831f24a418bc --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunctiondefinition.type.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionFunctionDefinition](./kibana-plugin-plugins-expressions-public.expressionfunctiondefinition.md) > [type](./kibana-plugin-plugins-expressions-public.expressionfunctiondefinition.type.md) + +## ExpressionFunctionDefinition.type property + +Name of type of value this function outputs. + +Signature: + +```typescript +type?: TypeToString>; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunctiondefinitions.clog.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunctiondefinitions.clog.md new file mode 100644 index 0000000000000..3b3b5520ab3ab --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunctiondefinitions.clog.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionFunctionDefinitions](./kibana-plugin-plugins-expressions-public.expressionfunctiondefinitions.md) > [clog](./kibana-plugin-plugins-expressions-public.expressionfunctiondefinitions.clog.md) + +## ExpressionFunctionDefinitions.clog property + +Signature: + +```typescript +clog: ExpressionFunctionClog; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunctiondefinitions.font.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunctiondefinitions.font.md new file mode 100644 index 0000000000000..06674eeaf9d7a --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunctiondefinitions.font.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionFunctionDefinitions](./kibana-plugin-plugins-expressions-public.expressionfunctiondefinitions.md) > [font](./kibana-plugin-plugins-expressions-public.expressionfunctiondefinitions.font.md) + +## ExpressionFunctionDefinitions.font property + +Signature: + +```typescript +font: ExpressionFunctionFont; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunctiondefinitions.kibana.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunctiondefinitions.kibana.md new file mode 100644 index 0000000000000..abe8e0ae161ad --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunctiondefinitions.kibana.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionFunctionDefinitions](./kibana-plugin-plugins-expressions-public.expressionfunctiondefinitions.md) > [kibana](./kibana-plugin-plugins-expressions-public.expressionfunctiondefinitions.kibana.md) + +## ExpressionFunctionDefinitions.kibana property + +Signature: + +```typescript +kibana: ExpressionFunctionKibana; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunctiondefinitions.kibana_context.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunctiondefinitions.kibana_context.md new file mode 100644 index 0000000000000..4b58fd84e160d --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunctiondefinitions.kibana_context.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionFunctionDefinitions](./kibana-plugin-plugins-expressions-public.expressionfunctiondefinitions.md) > [kibana\_context](./kibana-plugin-plugins-expressions-public.expressionfunctiondefinitions.kibana_context.md) + +## ExpressionFunctionDefinitions.kibana\_context property + +Signature: + +```typescript +kibana_context: ExpressionFunctionKibanaContext; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunctiondefinitions.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunctiondefinitions.md new file mode 100644 index 0000000000000..914c5d6ebe2f6 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunctiondefinitions.md @@ -0,0 +1,26 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionFunctionDefinitions](./kibana-plugin-plugins-expressions-public.expressionfunctiondefinitions.md) + +## ExpressionFunctionDefinitions interface + +A mapping of `ExpressionFunctionDefinition`s for functions which the Expressions services provides out-of-the-box. Any new functions registered by the Expressions plugin should have their types added here. + +Signature: + +```typescript +export interface ExpressionFunctionDefinitions +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [clog](./kibana-plugin-plugins-expressions-public.expressionfunctiondefinitions.clog.md) | ExpressionFunctionClog | | +| [font](./kibana-plugin-plugins-expressions-public.expressionfunctiondefinitions.font.md) | ExpressionFunctionFont | | +| [kibana\_context](./kibana-plugin-plugins-expressions-public.expressionfunctiondefinitions.kibana_context.md) | ExpressionFunctionKibanaContext | | +| [kibana](./kibana-plugin-plugins-expressions-public.expressionfunctiondefinitions.kibana.md) | ExpressionFunctionKibana | | +| [theme](./kibana-plugin-plugins-expressions-public.expressionfunctiondefinitions.theme.md) | ExpressionFunctionTheme | | +| [var\_set](./kibana-plugin-plugins-expressions-public.expressionfunctiondefinitions.var_set.md) | ExpressionFunctionVarSet | | +| [var](./kibana-plugin-plugins-expressions-public.expressionfunctiondefinitions.var.md) | ExpressionFunctionVar | | + diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunctiondefinitions.theme.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunctiondefinitions.theme.md new file mode 100644 index 0000000000000..766aee8f80809 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunctiondefinitions.theme.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionFunctionDefinitions](./kibana-plugin-plugins-expressions-public.expressionfunctiondefinitions.md) > [theme](./kibana-plugin-plugins-expressions-public.expressionfunctiondefinitions.theme.md) + +## ExpressionFunctionDefinitions.theme property + +Signature: + +```typescript +theme: ExpressionFunctionTheme; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunctiondefinitions.var.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunctiondefinitions.var.md new file mode 100644 index 0000000000000..4c3f4bb98a51e --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunctiondefinitions.var.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionFunctionDefinitions](./kibana-plugin-plugins-expressions-public.expressionfunctiondefinitions.md) > [var](./kibana-plugin-plugins-expressions-public.expressionfunctiondefinitions.var.md) + +## ExpressionFunctionDefinitions.var property + +Signature: + +```typescript +var: ExpressionFunctionVar; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunctiondefinitions.var_set.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunctiondefinitions.var_set.md new file mode 100644 index 0000000000000..a45d58242e4f3 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunctiondefinitions.var_set.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionFunctionDefinitions](./kibana-plugin-plugins-expressions-public.expressionfunctiondefinitions.md) > [var\_set](./kibana-plugin-plugins-expressions-public.expressionfunctiondefinitions.var_set.md) + +## ExpressionFunctionDefinitions.var\_set property + +Signature: + +```typescript +var_set: ExpressionFunctionVarSet; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunctionkibana.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunctionkibana.md new file mode 100644 index 0000000000000..8ccf48ba28527 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunctionkibana.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionFunctionKibana](./kibana-plugin-plugins-expressions-public.expressionfunctionkibana.md) + +## ExpressionFunctionKibana type + +Signature: + +```typescript +export declare type ExpressionFunctionKibana = ExpressionFunctionDefinition<'kibana', ExpressionValueSearchContext | null, object, ExpressionValueSearchContext>; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunctionparameter._constructor_.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunctionparameter._constructor_.md new file mode 100644 index 0000000000000..476ae51dd50f7 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunctionparameter._constructor_.md @@ -0,0 +1,21 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionFunctionParameter](./kibana-plugin-plugins-expressions-public.expressionfunctionparameter.md) > [(constructor)](./kibana-plugin-plugins-expressions-public.expressionfunctionparameter._constructor_.md) + +## ExpressionFunctionParameter.(constructor) + +Constructs a new instance of the `ExpressionFunctionParameter` class + +Signature: + +```typescript +constructor(name: string, arg: ArgumentType); +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| name | string | | +| arg | ArgumentType<any> | | + diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunctionparameter.accepts.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunctionparameter.accepts.md new file mode 100644 index 0000000000000..13b658d86855e --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunctionparameter.accepts.md @@ -0,0 +1,22 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionFunctionParameter](./kibana-plugin-plugins-expressions-public.expressionfunctionparameter.md) > [accepts](./kibana-plugin-plugins-expressions-public.expressionfunctionparameter.accepts.md) + +## ExpressionFunctionParameter.accepts() method + +Signature: + +```typescript +accepts(type: string): boolean; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| type | string | | + +Returns: + +`boolean` + diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunctionparameter.aliases.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunctionparameter.aliases.md new file mode 100644 index 0000000000000..03d6daac044b8 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunctionparameter.aliases.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionFunctionParameter](./kibana-plugin-plugins-expressions-public.expressionfunctionparameter.md) > [aliases](./kibana-plugin-plugins-expressions-public.expressionfunctionparameter.aliases.md) + +## ExpressionFunctionParameter.aliases property + +Signature: + +```typescript +aliases: string[]; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunctionparameter.default.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunctionparameter.default.md new file mode 100644 index 0000000000000..20cb697c182ae --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunctionparameter.default.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionFunctionParameter](./kibana-plugin-plugins-expressions-public.expressionfunctionparameter.md) > [default](./kibana-plugin-plugins-expressions-public.expressionfunctionparameter.default.md) + +## ExpressionFunctionParameter.default property + +Signature: + +```typescript +default: any; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunctionparameter.help.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunctionparameter.help.md new file mode 100644 index 0000000000000..102715264d5a9 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunctionparameter.help.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionFunctionParameter](./kibana-plugin-plugins-expressions-public.expressionfunctionparameter.md) > [help](./kibana-plugin-plugins-expressions-public.expressionfunctionparameter.help.md) + +## ExpressionFunctionParameter.help property + +Signature: + +```typescript +help: string; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunctionparameter.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunctionparameter.md new file mode 100644 index 0000000000000..eb99255b09328 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunctionparameter.md @@ -0,0 +1,38 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionFunctionParameter](./kibana-plugin-plugins-expressions-public.expressionfunctionparameter.md) + +## ExpressionFunctionParameter class + +Signature: + +```typescript +export declare class ExpressionFunctionParameter +``` + +## Constructors + +| Constructor | Modifiers | Description | +| --- | --- | --- | +| [(constructor)(name, arg)](./kibana-plugin-plugins-expressions-public.expressionfunctionparameter._constructor_.md) | | Constructs a new instance of the ExpressionFunctionParameter class | + +## Properties + +| Property | Modifiers | Type | Description | +| --- | --- | --- | --- | +| [aliases](./kibana-plugin-plugins-expressions-public.expressionfunctionparameter.aliases.md) | | string[] | | +| [default](./kibana-plugin-plugins-expressions-public.expressionfunctionparameter.default.md) | | any | | +| [help](./kibana-plugin-plugins-expressions-public.expressionfunctionparameter.help.md) | | string | | +| [multi](./kibana-plugin-plugins-expressions-public.expressionfunctionparameter.multi.md) | | boolean | | +| [name](./kibana-plugin-plugins-expressions-public.expressionfunctionparameter.name.md) | | string | | +| [options](./kibana-plugin-plugins-expressions-public.expressionfunctionparameter.options.md) | | any[] | | +| [required](./kibana-plugin-plugins-expressions-public.expressionfunctionparameter.required.md) | | boolean | | +| [resolve](./kibana-plugin-plugins-expressions-public.expressionfunctionparameter.resolve.md) | | boolean | | +| [types](./kibana-plugin-plugins-expressions-public.expressionfunctionparameter.types.md) | | string[] | | + +## Methods + +| Method | Modifiers | Description | +| --- | --- | --- | +| [accepts(type)](./kibana-plugin-plugins-expressions-public.expressionfunctionparameter.accepts.md) | | | + diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunctionparameter.multi.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunctionparameter.multi.md new file mode 100644 index 0000000000000..cc0bfbaac05a1 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunctionparameter.multi.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionFunctionParameter](./kibana-plugin-plugins-expressions-public.expressionfunctionparameter.md) > [multi](./kibana-plugin-plugins-expressions-public.expressionfunctionparameter.multi.md) + +## ExpressionFunctionParameter.multi property + +Signature: + +```typescript +multi: boolean; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunctionparameter.name.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunctionparameter.name.md new file mode 100644 index 0000000000000..6a7d120a169dc --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunctionparameter.name.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionFunctionParameter](./kibana-plugin-plugins-expressions-public.expressionfunctionparameter.md) > [name](./kibana-plugin-plugins-expressions-public.expressionfunctionparameter.name.md) + +## ExpressionFunctionParameter.name property + +Signature: + +```typescript +name: string; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunctionparameter.options.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunctionparameter.options.md new file mode 100644 index 0000000000000..c1596becd2f5b --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunctionparameter.options.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionFunctionParameter](./kibana-plugin-plugins-expressions-public.expressionfunctionparameter.md) > [options](./kibana-plugin-plugins-expressions-public.expressionfunctionparameter.options.md) + +## ExpressionFunctionParameter.options property + +Signature: + +```typescript +options: any[]; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunctionparameter.required.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunctionparameter.required.md new file mode 100644 index 0000000000000..b4c494704edd7 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunctionparameter.required.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionFunctionParameter](./kibana-plugin-plugins-expressions-public.expressionfunctionparameter.md) > [required](./kibana-plugin-plugins-expressions-public.expressionfunctionparameter.required.md) + +## ExpressionFunctionParameter.required property + +Signature: + +```typescript +required: boolean; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunctionparameter.resolve.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunctionparameter.resolve.md new file mode 100644 index 0000000000000..a5689aa2d4226 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunctionparameter.resolve.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionFunctionParameter](./kibana-plugin-plugins-expressions-public.expressionfunctionparameter.md) > [resolve](./kibana-plugin-plugins-expressions-public.expressionfunctionparameter.resolve.md) + +## ExpressionFunctionParameter.resolve property + +Signature: + +```typescript +resolve: boolean; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunctionparameter.types.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunctionparameter.types.md new file mode 100644 index 0000000000000..63d73001b7285 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunctionparameter.types.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionFunctionParameter](./kibana-plugin-plugins-expressions-public.expressionfunctionparameter.md) > [types](./kibana-plugin-plugins-expressions-public.expressionfunctionparameter.types.md) + +## ExpressionFunctionParameter.types property + +Signature: + +```typescript +types: string[]; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionimage.dataurl.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionimage.dataurl.md new file mode 100644 index 0000000000000..b6b34720a7dd8 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionimage.dataurl.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionImage](./kibana-plugin-plugins-expressions-public.expressionimage.md) > [dataurl](./kibana-plugin-plugins-expressions-public.expressionimage.dataurl.md) + +## ExpressionImage.dataurl property + +Signature: + +```typescript +dataurl: string; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionimage.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionimage.md new file mode 100644 index 0000000000000..430273cca7edd --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionimage.md @@ -0,0 +1,20 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionImage](./kibana-plugin-plugins-expressions-public.expressionimage.md) + +## ExpressionImage interface + +Signature: + +```typescript +export interface ExpressionImage +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [dataurl](./kibana-plugin-plugins-expressions-public.expressionimage.dataurl.md) | string | | +| [mode](./kibana-plugin-plugins-expressions-public.expressionimage.mode.md) | string | | +| [type](./kibana-plugin-plugins-expressions-public.expressionimage.type.md) | 'image' | | + diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionimage.mode.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionimage.mode.md new file mode 100644 index 0000000000000..f56a58ee71e98 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionimage.mode.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionImage](./kibana-plugin-plugins-expressions-public.expressionimage.md) > [mode](./kibana-plugin-plugins-expressions-public.expressionimage.mode.md) + +## ExpressionImage.mode property + +Signature: + +```typescript +mode: string; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionimage.type.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionimage.type.md new file mode 100644 index 0000000000000..e3b6e135233ef --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionimage.type.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionImage](./kibana-plugin-plugins-expressions-public.expressionimage.md) > [type](./kibana-plugin-plugins-expressions-public.expressionimage.type.md) + +## ExpressionImage.type property + +Signature: + +```typescript +type: 'image'; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionrenderdefinition.displayname.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionrenderdefinition.displayname.md new file mode 100644 index 0000000000000..a957ecd63f043 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionrenderdefinition.displayname.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionRenderDefinition](./kibana-plugin-plugins-expressions-public.expressionrenderdefinition.md) > [displayName](./kibana-plugin-plugins-expressions-public.expressionrenderdefinition.displayname.md) + +## ExpressionRenderDefinition.displayName property + +A user friendly name of the renderer as will be displayed to user in UI. + +Signature: + +```typescript +displayName?: string; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionrenderdefinition.help.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionrenderdefinition.help.md new file mode 100644 index 0000000000000..ca67f18c0591f --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionrenderdefinition.help.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionRenderDefinition](./kibana-plugin-plugins-expressions-public.expressionrenderdefinition.md) > [help](./kibana-plugin-plugins-expressions-public.expressionrenderdefinition.help.md) + +## ExpressionRenderDefinition.help property + +Help text as will be displayed to user. A sentence or few about what this element does. + +Signature: + +```typescript +help?: string; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionrenderdefinition.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionrenderdefinition.md new file mode 100644 index 0000000000000..3c3322914cebe --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionrenderdefinition.md @@ -0,0 +1,23 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionRenderDefinition](./kibana-plugin-plugins-expressions-public.expressionrenderdefinition.md) + +## ExpressionRenderDefinition interface + +Signature: + +```typescript +export interface ExpressionRenderDefinition +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [displayName](./kibana-plugin-plugins-expressions-public.expressionrenderdefinition.displayname.md) | string | A user friendly name of the renderer as will be displayed to user in UI. | +| [help](./kibana-plugin-plugins-expressions-public.expressionrenderdefinition.help.md) | string | Help text as will be displayed to user. A sentence or few about what this element does. | +| [name](./kibana-plugin-plugins-expressions-public.expressionrenderdefinition.name.md) | string | Technical name of the renderer, used as ID to identify renderer in expression renderer registry. This must match the name of the expression function that is used to create the type: render object. | +| [render](./kibana-plugin-plugins-expressions-public.expressionrenderdefinition.render.md) | (domNode: HTMLElement, config: Config, handlers: IInterpreterRenderHandlers) => void | Promise<void> | The function called to render the output data of an expression. | +| [reuseDomNode](./kibana-plugin-plugins-expressions-public.expressionrenderdefinition.reusedomnode.md) | boolean | Tell the renderer if the dom node should be reused, it's recreated each time by default. | +| [validate](./kibana-plugin-plugins-expressions-public.expressionrenderdefinition.validate.md) | () => undefined | Error | Used to validate the data before calling the render function. | + diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionrenderdefinition.name.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionrenderdefinition.name.md new file mode 100644 index 0000000000000..25b782549fe7b --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionrenderdefinition.name.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionRenderDefinition](./kibana-plugin-plugins-expressions-public.expressionrenderdefinition.md) > [name](./kibana-plugin-plugins-expressions-public.expressionrenderdefinition.name.md) + +## ExpressionRenderDefinition.name property + +Technical name of the renderer, used as ID to identify renderer in expression renderer registry. This must match the name of the expression function that is used to create the `type: render` object. + +Signature: + +```typescript +name: string; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionrenderdefinition.render.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionrenderdefinition.render.md new file mode 100644 index 0000000000000..d476ae15d4237 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionrenderdefinition.render.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionRenderDefinition](./kibana-plugin-plugins-expressions-public.expressionrenderdefinition.md) > [render](./kibana-plugin-plugins-expressions-public.expressionrenderdefinition.render.md) + +## ExpressionRenderDefinition.render property + +The function called to render the output data of an expression. + +Signature: + +```typescript +render: (domNode: HTMLElement, config: Config, handlers: IInterpreterRenderHandlers) => void | Promise; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionrenderdefinition.reusedomnode.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionrenderdefinition.reusedomnode.md new file mode 100644 index 0000000000000..515cb2c1c078d --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionrenderdefinition.reusedomnode.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionRenderDefinition](./kibana-plugin-plugins-expressions-public.expressionrenderdefinition.md) > [reuseDomNode](./kibana-plugin-plugins-expressions-public.expressionrenderdefinition.reusedomnode.md) + +## ExpressionRenderDefinition.reuseDomNode property + +Tell the renderer if the dom node should be reused, it's recreated each time by default. + +Signature: + +```typescript +reuseDomNode: boolean; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionrenderdefinition.validate.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionrenderdefinition.validate.md new file mode 100644 index 0000000000000..616a0dcc0a94f --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionrenderdefinition.validate.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionRenderDefinition](./kibana-plugin-plugins-expressions-public.expressionrenderdefinition.md) > [validate](./kibana-plugin-plugins-expressions-public.expressionrenderdefinition.validate.md) + +## ExpressionRenderDefinition.validate property + +Used to validate the data before calling the render function. + +Signature: + +```typescript +validate?: () => undefined | Error; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionrenderer._constructor_.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionrenderer._constructor_.md new file mode 100644 index 0000000000000..de74ee631fcf1 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionrenderer._constructor_.md @@ -0,0 +1,20 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionRenderer](./kibana-plugin-plugins-expressions-public.expressionrenderer.md) > [(constructor)](./kibana-plugin-plugins-expressions-public.expressionrenderer._constructor_.md) + +## ExpressionRenderer.(constructor) + +Constructs a new instance of the `ExpressionRenderer` class + +Signature: + +```typescript +constructor(config: ExpressionRenderDefinition); +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| config | ExpressionRenderDefinition<Config> | | + diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionrenderer.displayname.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionrenderer.displayname.md new file mode 100644 index 0000000000000..710bcc60a47e7 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionrenderer.displayname.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionRenderer](./kibana-plugin-plugins-expressions-public.expressionrenderer.md) > [displayName](./kibana-plugin-plugins-expressions-public.expressionrenderer.displayname.md) + +## ExpressionRenderer.displayName property + +Signature: + +```typescript +readonly displayName: string; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionrenderer.help.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionrenderer.help.md new file mode 100644 index 0000000000000..f5b3f248e71fe --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionrenderer.help.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionRenderer](./kibana-plugin-plugins-expressions-public.expressionrenderer.md) > [help](./kibana-plugin-plugins-expressions-public.expressionrenderer.help.md) + +## ExpressionRenderer.help property + +Signature: + +```typescript +readonly help: string; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionrenderer.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionrenderer.md new file mode 100644 index 0000000000000..017d88c0cda69 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionrenderer.md @@ -0,0 +1,29 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionRenderer](./kibana-plugin-plugins-expressions-public.expressionrenderer.md) + +## ExpressionRenderer class + +Signature: + +```typescript +export declare class ExpressionRenderer +``` + +## Constructors + +| Constructor | Modifiers | Description | +| --- | --- | --- | +| [(constructor)(config)](./kibana-plugin-plugins-expressions-public.expressionrenderer._constructor_.md) | | Constructs a new instance of the ExpressionRenderer class | + +## Properties + +| Property | Modifiers | Type | Description | +| --- | --- | --- | --- | +| [displayName](./kibana-plugin-plugins-expressions-public.expressionrenderer.displayname.md) | | string | | +| [help](./kibana-plugin-plugins-expressions-public.expressionrenderer.help.md) | | string | | +| [name](./kibana-plugin-plugins-expressions-public.expressionrenderer.name.md) | | string | | +| [render](./kibana-plugin-plugins-expressions-public.expressionrenderer.render.md) | | ExpressionRenderDefinition<Config>['render'] | | +| [reuseDomNode](./kibana-plugin-plugins-expressions-public.expressionrenderer.reusedomnode.md) | | boolean | | +| [validate](./kibana-plugin-plugins-expressions-public.expressionrenderer.validate.md) | | () => void | Error | | + diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionrenderer.name.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionrenderer.name.md new file mode 100644 index 0000000000000..2ed6677cf6ec4 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionrenderer.name.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionRenderer](./kibana-plugin-plugins-expressions-public.expressionrenderer.md) > [name](./kibana-plugin-plugins-expressions-public.expressionrenderer.name.md) + +## ExpressionRenderer.name property + +Signature: + +```typescript +readonly name: string; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionrenderer.render.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionrenderer.render.md new file mode 100644 index 0000000000000..2491cb31d7659 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionrenderer.render.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionRenderer](./kibana-plugin-plugins-expressions-public.expressionrenderer.md) > [render](./kibana-plugin-plugins-expressions-public.expressionrenderer.render.md) + +## ExpressionRenderer.render property + +Signature: + +```typescript +readonly render: ExpressionRenderDefinition['render']; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionrenderer.reusedomnode.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionrenderer.reusedomnode.md new file mode 100644 index 0000000000000..b5c3a89cc3ed1 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionrenderer.reusedomnode.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionRenderer](./kibana-plugin-plugins-expressions-public.expressionrenderer.md) > [reuseDomNode](./kibana-plugin-plugins-expressions-public.expressionrenderer.reusedomnode.md) + +## ExpressionRenderer.reuseDomNode property + +Signature: + +```typescript +readonly reuseDomNode: boolean; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionrenderer.validate.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionrenderer.validate.md new file mode 100644 index 0000000000000..7c1a7ac65809f --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionrenderer.validate.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionRenderer](./kibana-plugin-plugins-expressions-public.expressionrenderer.md) > [validate](./kibana-plugin-plugins-expressions-public.expressionrenderer.validate.md) + +## ExpressionRenderer.validate property + +Signature: + +```typescript +readonly validate: () => void | Error; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionrenderercomponent.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionrenderercomponent.md new file mode 100644 index 0000000000000..c49a74abe57f3 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionrenderercomponent.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionRendererComponent](./kibana-plugin-plugins-expressions-public.expressionrenderercomponent.md) + +## ExpressionRendererComponent type + +Signature: + +```typescript +export declare type ExpressionRendererComponent = React.FC; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionrendererevent.data.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionrendererevent.data.md new file mode 100644 index 0000000000000..537a3f278863d --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionrendererevent.data.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionRendererEvent](./kibana-plugin-plugins-expressions-public.expressionrendererevent.md) > [data](./kibana-plugin-plugins-expressions-public.expressionrendererevent.data.md) + +## ExpressionRendererEvent.data property + +Signature: + +```typescript +data: any; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionrendererevent.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionrendererevent.md new file mode 100644 index 0000000000000..952d2f92496c3 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionrendererevent.md @@ -0,0 +1,19 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionRendererEvent](./kibana-plugin-plugins-expressions-public.expressionrendererevent.md) + +## ExpressionRendererEvent interface + +Signature: + +```typescript +export interface ExpressionRendererEvent +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [data](./kibana-plugin-plugins-expressions-public.expressionrendererevent.data.md) | any | | +| [name](./kibana-plugin-plugins-expressions-public.expressionrendererevent.name.md) | string | | + diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionrendererevent.name.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionrendererevent.name.md new file mode 100644 index 0000000000000..bbff92108358a --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionrendererevent.name.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionRendererEvent](./kibana-plugin-plugins-expressions-public.expressionrendererevent.md) > [name](./kibana-plugin-plugins-expressions-public.expressionrendererevent.name.md) + +## ExpressionRendererEvent.name property + +Signature: + +```typescript +name: string; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionrendererregistry.get.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionrendererregistry.get.md new file mode 100644 index 0000000000000..cff44001f0a1f --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionrendererregistry.get.md @@ -0,0 +1,22 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionRendererRegistry](./kibana-plugin-plugins-expressions-public.expressionrendererregistry.md) > [get](./kibana-plugin-plugins-expressions-public.expressionrendererregistry.get.md) + +## ExpressionRendererRegistry.get() method + +Signature: + +```typescript +get(id: string): ExpressionRenderer | null; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| id | string | | + +Returns: + +`ExpressionRenderer | null` + diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionrendererregistry.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionrendererregistry.md new file mode 100644 index 0000000000000..e53f2a7970723 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionrendererregistry.md @@ -0,0 +1,21 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionRendererRegistry](./kibana-plugin-plugins-expressions-public.expressionrendererregistry.md) + +## ExpressionRendererRegistry class + +Signature: + +```typescript +export declare class ExpressionRendererRegistry implements IRegistry +``` + +## Methods + +| Method | Modifiers | Description | +| --- | --- | --- | +| [get(id)](./kibana-plugin-plugins-expressions-public.expressionrendererregistry.get.md) | | | +| [register(definition)](./kibana-plugin-plugins-expressions-public.expressionrendererregistry.register.md) | | | +| [toArray()](./kibana-plugin-plugins-expressions-public.expressionrendererregistry.toarray.md) | | | +| [toJS()](./kibana-plugin-plugins-expressions-public.expressionrendererregistry.tojs.md) | | | + diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionrendererregistry.register.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionrendererregistry.register.md new file mode 100644 index 0000000000000..13cabb0410861 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionrendererregistry.register.md @@ -0,0 +1,22 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionRendererRegistry](./kibana-plugin-plugins-expressions-public.expressionrendererregistry.md) > [register](./kibana-plugin-plugins-expressions-public.expressionrendererregistry.register.md) + +## ExpressionRendererRegistry.register() method + +Signature: + +```typescript +register(definition: AnyExpressionRenderDefinition | (() => AnyExpressionRenderDefinition)): void; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| definition | AnyExpressionRenderDefinition | (() => AnyExpressionRenderDefinition) | | + +Returns: + +`void` + diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionrendererregistry.toarray.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionrendererregistry.toarray.md new file mode 100644 index 0000000000000..b29fd46265d16 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionrendererregistry.toarray.md @@ -0,0 +1,15 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionRendererRegistry](./kibana-plugin-plugins-expressions-public.expressionrendererregistry.md) > [toArray](./kibana-plugin-plugins-expressions-public.expressionrendererregistry.toarray.md) + +## ExpressionRendererRegistry.toArray() method + +Signature: + +```typescript +toArray(): ExpressionRenderer[]; +``` +Returns: + +`ExpressionRenderer[]` + diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionrendererregistry.tojs.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionrendererregistry.tojs.md new file mode 100644 index 0000000000000..930ef7f8d89d2 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionrendererregistry.tojs.md @@ -0,0 +1,15 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionRendererRegistry](./kibana-plugin-plugins-expressions-public.expressionrendererregistry.md) > [toJS](./kibana-plugin-plugins-expressions-public.expressionrendererregistry.tojs.md) + +## ExpressionRendererRegistry.toJS() method + +Signature: + +```typescript +toJS(): Record; +``` +Returns: + +`Record` + diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionrendererror.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionrendererror.md new file mode 100644 index 0000000000000..3b3c1644adbef --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionrendererror.md @@ -0,0 +1,18 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionRenderError](./kibana-plugin-plugins-expressions-public.expressionrendererror.md) + +## ExpressionRenderError interface + +Signature: + +```typescript +export interface ExpressionRenderError extends Error +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [type](./kibana-plugin-plugins-expressions-public.expressionrendererror.type.md) | string | | + diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionrendererror.type.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionrendererror.type.md new file mode 100644 index 0000000000000..b1939299a9d37 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionrendererror.type.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionRenderError](./kibana-plugin-plugins-expressions-public.expressionrendererror.md) > [type](./kibana-plugin-plugins-expressions-public.expressionrendererror.type.md) + +## ExpressionRenderError.type property + +Signature: + +```typescript +type?: string; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionrenderhandler._constructor_.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionrenderhandler._constructor_.md new file mode 100644 index 0000000000000..fb6ba7ee2621c --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionrenderhandler._constructor_.md @@ -0,0 +1,21 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionRenderHandler](./kibana-plugin-plugins-expressions-public.expressionrenderhandler.md) > [(constructor)](./kibana-plugin-plugins-expressions-public.expressionrenderhandler._constructor_.md) + +## ExpressionRenderHandler.(constructor) + +Constructs a new instance of the `ExpressionRenderHandler` class + +Signature: + +```typescript +constructor(element: HTMLElement, { onRenderError }?: Partial); +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| element | HTMLElement | | +| { onRenderError } | Partial<ExpressionRenderHandlerParams> | | + diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionrenderhandler.destroy.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionrenderhandler.destroy.md new file mode 100644 index 0000000000000..df949324b3b45 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionrenderhandler.destroy.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionRenderHandler](./kibana-plugin-plugins-expressions-public.expressionrenderhandler.md) > [destroy](./kibana-plugin-plugins-expressions-public.expressionrenderhandler.destroy.md) + +## ExpressionRenderHandler.destroy property + +Signature: + +```typescript +destroy: () => void; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionrenderhandler.events_.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionrenderhandler.events_.md new file mode 100644 index 0000000000000..c462724a4fdd9 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionrenderhandler.events_.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionRenderHandler](./kibana-plugin-plugins-expressions-public.expressionrenderhandler.md) > [events$](./kibana-plugin-plugins-expressions-public.expressionrenderhandler.events_.md) + +## ExpressionRenderHandler.events$ property + +Signature: + +```typescript +events$: Observable; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionrenderhandler.getelement.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionrenderhandler.getelement.md new file mode 100644 index 0000000000000..42262938502d8 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionrenderhandler.getelement.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionRenderHandler](./kibana-plugin-plugins-expressions-public.expressionrenderhandler.md) > [getElement](./kibana-plugin-plugins-expressions-public.expressionrenderhandler.getelement.md) + +## ExpressionRenderHandler.getElement property + +Signature: + +```typescript +getElement: () => HTMLElement; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionrenderhandler.handlerendererror.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionrenderhandler.handlerendererror.md new file mode 100644 index 0000000000000..6a70cac98ef8a --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionrenderhandler.handlerendererror.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionRenderHandler](./kibana-plugin-plugins-expressions-public.expressionrenderhandler.md) > [handleRenderError](./kibana-plugin-plugins-expressions-public.expressionrenderhandler.handlerendererror.md) + +## ExpressionRenderHandler.handleRenderError property + +Signature: + +```typescript +handleRenderError: (error: ExpressionRenderError) => void; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionrenderhandler.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionrenderhandler.md new file mode 100644 index 0000000000000..7f7d5792ba684 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionrenderhandler.md @@ -0,0 +1,30 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionRenderHandler](./kibana-plugin-plugins-expressions-public.expressionrenderhandler.md) + +## ExpressionRenderHandler class + +Signature: + +```typescript +export declare class ExpressionRenderHandler +``` + +## Constructors + +| Constructor | Modifiers | Description | +| --- | --- | --- | +| [(constructor)(element, { onRenderError })](./kibana-plugin-plugins-expressions-public.expressionrenderhandler._constructor_.md) | | Constructs a new instance of the ExpressionRenderHandler class | + +## Properties + +| Property | Modifiers | Type | Description | +| --- | --- | --- | --- | +| [destroy](./kibana-plugin-plugins-expressions-public.expressionrenderhandler.destroy.md) | | () => void | | +| [events$](./kibana-plugin-plugins-expressions-public.expressionrenderhandler.events_.md) | | Observable<ExpressionRendererEvent> | | +| [getElement](./kibana-plugin-plugins-expressions-public.expressionrenderhandler.getelement.md) | | () => HTMLElement | | +| [handleRenderError](./kibana-plugin-plugins-expressions-public.expressionrenderhandler.handlerendererror.md) | | (error: ExpressionRenderError) => void | | +| [render](./kibana-plugin-plugins-expressions-public.expressionrenderhandler.render.md) | | (data: any, uiState?: any) => Promise<void> | | +| [render$](./kibana-plugin-plugins-expressions-public.expressionrenderhandler.render_.md) | | Observable<number> | | +| [update$](./kibana-plugin-plugins-expressions-public.expressionrenderhandler.update_.md) | | Observable<UpdateValue | null> | | + diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionrenderhandler.render.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionrenderhandler.render.md new file mode 100644 index 0000000000000..dec17d60ffd14 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionrenderhandler.render.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionRenderHandler](./kibana-plugin-plugins-expressions-public.expressionrenderhandler.md) > [render](./kibana-plugin-plugins-expressions-public.expressionrenderhandler.render.md) + +## ExpressionRenderHandler.render property + +Signature: + +```typescript +render: (data: any, uiState?: any) => Promise; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionrenderhandler.render_.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionrenderhandler.render_.md new file mode 100644 index 0000000000000..631dcbfcf89c1 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionrenderhandler.render_.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionRenderHandler](./kibana-plugin-plugins-expressions-public.expressionrenderhandler.md) > [render$](./kibana-plugin-plugins-expressions-public.expressionrenderhandler.render_.md) + +## ExpressionRenderHandler.render$ property + +Signature: + +```typescript +render$: Observable; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionrenderhandler.update_.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionrenderhandler.update_.md new file mode 100644 index 0000000000000..527e64f8e4815 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionrenderhandler.update_.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionRenderHandler](./kibana-plugin-plugins-expressions-public.expressionrenderhandler.md) > [update$](./kibana-plugin-plugins-expressions-public.expressionrenderhandler.update_.md) + +## ExpressionRenderHandler.update$ property + +Signature: + +```typescript +update$: Observable; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionspublicplugin._constructor_.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionspublicplugin._constructor_.md new file mode 100644 index 0000000000000..f49ae9b8166e7 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionspublicplugin._constructor_.md @@ -0,0 +1,20 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionsPublicPlugin](./kibana-plugin-plugins-expressions-public.expressionspublicplugin.md) > [(constructor)](./kibana-plugin-plugins-expressions-public.expressionspublicplugin._constructor_.md) + +## ExpressionsPublicPlugin.(constructor) + +Constructs a new instance of the `ExpressionsPublicPlugin` class + +Signature: + +```typescript +constructor(initializerContext: PluginInitializerContext); +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| initializerContext | PluginInitializerContext | | + diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionspublicplugin.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionspublicplugin.md new file mode 100644 index 0000000000000..dc8c961ceecc4 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionspublicplugin.md @@ -0,0 +1,26 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionsPublicPlugin](./kibana-plugin-plugins-expressions-public.expressionspublicplugin.md) + +## ExpressionsPublicPlugin class + +Signature: + +```typescript +export declare class ExpressionsPublicPlugin implements Plugin +``` + +## Constructors + +| Constructor | Modifiers | Description | +| --- | --- | --- | +| [(constructor)(initializerContext)](./kibana-plugin-plugins-expressions-public.expressionspublicplugin._constructor_.md) | | Constructs a new instance of the ExpressionsPublicPlugin class | + +## Methods + +| Method | Modifiers | Description | +| --- | --- | --- | +| [setup(core)](./kibana-plugin-plugins-expressions-public.expressionspublicplugin.setup.md) | | | +| [start(core)](./kibana-plugin-plugins-expressions-public.expressionspublicplugin.start.md) | | | +| [stop()](./kibana-plugin-plugins-expressions-public.expressionspublicplugin.stop.md) | | | + diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionspublicplugin.setup.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionspublicplugin.setup.md new file mode 100644 index 0000000000000..11f72a737aa44 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionspublicplugin.setup.md @@ -0,0 +1,22 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionsPublicPlugin](./kibana-plugin-plugins-expressions-public.expressionspublicplugin.md) > [setup](./kibana-plugin-plugins-expressions-public.expressionspublicplugin.setup.md) + +## ExpressionsPublicPlugin.setup() method + +Signature: + +```typescript +setup(core: CoreSetup): ExpressionsSetup; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| core | CoreSetup | | + +Returns: + +`ExpressionsSetup` + diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionspublicplugin.start.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionspublicplugin.start.md new file mode 100644 index 0000000000000..75599e2575809 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionspublicplugin.start.md @@ -0,0 +1,22 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionsPublicPlugin](./kibana-plugin-plugins-expressions-public.expressionspublicplugin.md) > [start](./kibana-plugin-plugins-expressions-public.expressionspublicplugin.start.md) + +## ExpressionsPublicPlugin.start() method + +Signature: + +```typescript +start(core: CoreStart): ExpressionsStart; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| core | CoreStart | | + +Returns: + +`ExpressionsStart` + diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionspublicplugin.stop.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionspublicplugin.stop.md new file mode 100644 index 0000000000000..2de33ef166b96 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionspublicplugin.stop.md @@ -0,0 +1,15 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionsPublicPlugin](./kibana-plugin-plugins-expressions-public.expressionspublicplugin.md) > [stop](./kibana-plugin-plugins-expressions-public.expressionspublicplugin.stop.md) + +## ExpressionsPublicPlugin.stop() method + +Signature: + +```typescript +stop(): void; +``` +Returns: + +`void` + diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsservice._constructor_.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsservice._constructor_.md new file mode 100644 index 0000000000000..695adad8cbeaf --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsservice._constructor_.md @@ -0,0 +1,20 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionsService](./kibana-plugin-plugins-expressions-public.expressionsservice.md) > [(constructor)](./kibana-plugin-plugins-expressions-public.expressionsservice._constructor_.md) + +## ExpressionsService.(constructor) + +Constructs a new instance of the `ExpressionsService` class + +Signature: + +```typescript +constructor({ executor, renderers, }?: ExpressionServiceParams); +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| { executor, renderers, } | ExpressionServiceParams | | + diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsservice.execute.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsservice.execute.md new file mode 100644 index 0000000000000..e4ab0aa32516c --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsservice.execute.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionsService](./kibana-plugin-plugins-expressions-public.expressionsservice.md) > [execute](./kibana-plugin-plugins-expressions-public.expressionsservice.execute.md) + +## ExpressionsService.execute property + +Signature: + +```typescript +readonly execute: ExpressionsServiceStart['execute']; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsservice.executor.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsservice.executor.md new file mode 100644 index 0000000000000..f206a0a5c4bb3 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsservice.executor.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionsService](./kibana-plugin-plugins-expressions-public.expressionsservice.md) > [executor](./kibana-plugin-plugins-expressions-public.expressionsservice.executor.md) + +## ExpressionsService.executor property + +Signature: + +```typescript +readonly executor: Executor; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsservice.fork.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsservice.fork.md new file mode 100644 index 0000000000000..5273f8d79f5cf --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsservice.fork.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionsService](./kibana-plugin-plugins-expressions-public.expressionsservice.md) > [fork](./kibana-plugin-plugins-expressions-public.expressionsservice.fork.md) + +## ExpressionsService.fork property + +Signature: + +```typescript +readonly fork: () => ExpressionsService; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsservice.getfunction.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsservice.getfunction.md new file mode 100644 index 0000000000000..7d79a1e407a46 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsservice.getfunction.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionsService](./kibana-plugin-plugins-expressions-public.expressionsservice.md) > [getFunction](./kibana-plugin-plugins-expressions-public.expressionsservice.getfunction.md) + +## ExpressionsService.getFunction property + +Signature: + +```typescript +readonly getFunction: ExpressionsServiceStart['getFunction']; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsservice.getfunctions.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsservice.getfunctions.md new file mode 100644 index 0000000000000..6e1b1ca3e1c6d --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsservice.getfunctions.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionsService](./kibana-plugin-plugins-expressions-public.expressionsservice.md) > [getFunctions](./kibana-plugin-plugins-expressions-public.expressionsservice.getfunctions.md) + +## ExpressionsService.getFunctions property + +Returns POJO map of all registered expression functions, where keys are names of the functions and values are `ExpressionFunction` instances. + +Signature: + +```typescript +readonly getFunctions: () => ReturnType; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsservice.getrenderer.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsservice.getrenderer.md new file mode 100644 index 0000000000000..5821654cf8ec5 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsservice.getrenderer.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionsService](./kibana-plugin-plugins-expressions-public.expressionsservice.md) > [getRenderer](./kibana-plugin-plugins-expressions-public.expressionsservice.getrenderer.md) + +## ExpressionsService.getRenderer property + +Signature: + +```typescript +readonly getRenderer: ExpressionsServiceStart['getRenderer']; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsservice.getrenderers.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsservice.getrenderers.md new file mode 100644 index 0000000000000..3258717759c90 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsservice.getrenderers.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionsService](./kibana-plugin-plugins-expressions-public.expressionsservice.md) > [getRenderers](./kibana-plugin-plugins-expressions-public.expressionsservice.getrenderers.md) + +## ExpressionsService.getRenderers property + +Returns POJO map of all registered expression renderers, where keys are names of the renderers and values are `ExpressionRenderer` instances. + +Signature: + +```typescript +readonly getRenderers: () => ReturnType; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsservice.gettype.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsservice.gettype.md new file mode 100644 index 0000000000000..e8c451ab88e9f --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsservice.gettype.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionsService](./kibana-plugin-plugins-expressions-public.expressionsservice.md) > [getType](./kibana-plugin-plugins-expressions-public.expressionsservice.gettype.md) + +## ExpressionsService.getType property + +Signature: + +```typescript +readonly getType: ExpressionsServiceStart['getType']; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsservice.gettypes.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsservice.gettypes.md new file mode 100644 index 0000000000000..844f581240d45 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsservice.gettypes.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionsService](./kibana-plugin-plugins-expressions-public.expressionsservice.md) > [getTypes](./kibana-plugin-plugins-expressions-public.expressionsservice.gettypes.md) + +## ExpressionsService.getTypes property + +Returns POJO map of all registered expression types, where keys are names of the types and values are `ExpressionType` instances. + +Signature: + +```typescript +readonly getTypes: () => ReturnType; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsservice.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsservice.md new file mode 100644 index 0000000000000..fa93435bffc38 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsservice.md @@ -0,0 +1,72 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionsService](./kibana-plugin-plugins-expressions-public.expressionsservice.md) + +## ExpressionsService class + +`ExpressionsService` class is used for multiple purposes: + +1. It implements the same Expressions service that can be used on both: (1) server-side and (2) browser-side. 2. It implements the same Expressions service that users can fork/clone, thus have their own instance of the Expressions plugin. 3. `ExpressionsService` defines the public contracts of \*setup\* and \*start\* Kibana Platform life-cycles for ease-of-use on server-side and browser-side. 4. `ExpressionsService` creates a bound version of all exported contract functions. 5. Functions are bound the way there are: + +\`\`\`ts registerFunction = (...args: Parameters<Executor\['registerFunction'\]> ): ReturnType<Executor\['registerFunction'\]> => this.executor.registerFunction(...args); \`\`\` + +so that JSDoc appears in developers IDE when they use those `plugins.expressions.registerFunction(`. + +Signature: + +```typescript +export declare class ExpressionsService +``` + +## Constructors + +| Constructor | Modifiers | Description | +| --- | --- | --- | +| [(constructor)({ executor, renderers, })](./kibana-plugin-plugins-expressions-public.expressionsservice._constructor_.md) | | Constructs a new instance of the ExpressionsService class | + +## Properties + +| Property | Modifiers | Type | Description | +| --- | --- | --- | --- | +| [execute](./kibana-plugin-plugins-expressions-public.expressionsservice.execute.md) | | ExpressionsServiceStart['execute'] | | +| [executor](./kibana-plugin-plugins-expressions-public.expressionsservice.executor.md) | | Executor | | +| [fork](./kibana-plugin-plugins-expressions-public.expressionsservice.fork.md) | | () => ExpressionsService | | +| [getFunction](./kibana-plugin-plugins-expressions-public.expressionsservice.getfunction.md) | | ExpressionsServiceStart['getFunction'] | | +| [getFunctions](./kibana-plugin-plugins-expressions-public.expressionsservice.getfunctions.md) | | () => ReturnType<Executor['getFunctions']> | Returns POJO map of all registered expression functions, where keys are names of the functions and values are ExpressionFunction instances. | +| [getRenderer](./kibana-plugin-plugins-expressions-public.expressionsservice.getrenderer.md) | | ExpressionsServiceStart['getRenderer'] | | +| [getRenderers](./kibana-plugin-plugins-expressions-public.expressionsservice.getrenderers.md) | | () => ReturnType<ExpressionRendererRegistry['toJS']> | Returns POJO map of all registered expression renderers, where keys are names of the renderers and values are ExpressionRenderer instances. | +| [getType](./kibana-plugin-plugins-expressions-public.expressionsservice.gettype.md) | | ExpressionsServiceStart['getType'] | | +| [getTypes](./kibana-plugin-plugins-expressions-public.expressionsservice.gettypes.md) | | () => ReturnType<Executor['getTypes']> | Returns POJO map of all registered expression types, where keys are names of the types and values are ExpressionType instances. | +| [registerFunction](./kibana-plugin-plugins-expressions-public.expressionsservice.registerfunction.md) | | (functionDefinition: AnyExpressionFunctionDefinition | (() => AnyExpressionFunctionDefinition)) => void | Register an expression function, which will be possible to execute as part of the expression pipeline.Below we register a function which simply sleeps for given number of milliseconds to delay the execution and outputs its input as-is. +```ts +expressions.registerFunction({ + name: 'sleep', + args: { + time: { + aliases: ['_'], + help: 'Time in milliseconds for how long to sleep', + types: ['number'], + }, + }, + help: '', + fn: async (input, args, context) => { + await new Promise(r => setTimeout(r, args.time)); + return input; + }, +} + +``` +The actual function is defined in the fn key. The function can be \*async\*. It receives three arguments: (1) input is the output of the previous function or the initial input of the expression if the function is first in chain; (2) args are function arguments as defined in expression string, that can be edited by user (e.g in case of Canvas); (3) context is a shared object passed to all functions that can be used for side-effects. | +| [registerRenderer](./kibana-plugin-plugins-expressions-public.expressionsservice.registerrenderer.md) | | (definition: AnyExpressionRenderDefinition | (() => AnyExpressionRenderDefinition)) => void | | +| [registerType](./kibana-plugin-plugins-expressions-public.expressionsservice.registertype.md) | | (typeDefinition: AnyExpressionTypeDefinition | (() => AnyExpressionTypeDefinition)) => void | | +| [renderers](./kibana-plugin-plugins-expressions-public.expressionsservice.renderers.md) | | ExpressionRendererRegistry | | +| [run](./kibana-plugin-plugins-expressions-public.expressionsservice.run.md) | | ExpressionsServiceStart['run'] | | + +## Methods + +| Method | Modifiers | Description | +| --- | --- | --- | +| [setup()](./kibana-plugin-plugins-expressions-public.expressionsservice.setup.md) | | Returns Kibana Platform \*setup\* life-cycle contract. Useful to return the same contract on server-side and browser-side. | +| [start()](./kibana-plugin-plugins-expressions-public.expressionsservice.start.md) | | Returns Kibana Platform \*start\* life-cycle contract. Useful to return the same contract on server-side and browser-side. | +| [stop()](./kibana-plugin-plugins-expressions-public.expressionsservice.stop.md) | | | + diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsservice.registerfunction.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsservice.registerfunction.md new file mode 100644 index 0000000000000..0653e68bb4837 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsservice.registerfunction.md @@ -0,0 +1,35 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionsService](./kibana-plugin-plugins-expressions-public.expressionsservice.md) > [registerFunction](./kibana-plugin-plugins-expressions-public.expressionsservice.registerfunction.md) + +## ExpressionsService.registerFunction property + +Register an expression function, which will be possible to execute as part of the expression pipeline. + +Below we register a function which simply sleeps for given number of milliseconds to delay the execution and outputs its input as-is. + +```ts +expressions.registerFunction({ + name: 'sleep', + args: { + time: { + aliases: ['_'], + help: 'Time in milliseconds for how long to sleep', + types: ['number'], + }, + }, + help: '', + fn: async (input, args, context) => { + await new Promise(r => setTimeout(r, args.time)); + return input; + }, +} + +``` +The actual function is defined in the `fn` key. The function can be \*async\*. It receives three arguments: (1) `input` is the output of the previous function or the initial input of the expression if the function is first in chain; (2) `args` are function arguments as defined in expression string, that can be edited by user (e.g in case of Canvas); (3) `context` is a shared object passed to all functions that can be used for side-effects. + +Signature: + +```typescript +readonly registerFunction: (functionDefinition: AnyExpressionFunctionDefinition | (() => AnyExpressionFunctionDefinition)) => void; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsservice.registerrenderer.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsservice.registerrenderer.md new file mode 100644 index 0000000000000..7aff36e7fd817 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsservice.registerrenderer.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionsService](./kibana-plugin-plugins-expressions-public.expressionsservice.md) > [registerRenderer](./kibana-plugin-plugins-expressions-public.expressionsservice.registerrenderer.md) + +## ExpressionsService.registerRenderer property + +Signature: + +```typescript +readonly registerRenderer: (definition: AnyExpressionRenderDefinition | (() => AnyExpressionRenderDefinition)) => void; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsservice.registertype.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsservice.registertype.md new file mode 100644 index 0000000000000..e6e71e5e7e7e9 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsservice.registertype.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionsService](./kibana-plugin-plugins-expressions-public.expressionsservice.md) > [registerType](./kibana-plugin-plugins-expressions-public.expressionsservice.registertype.md) + +## ExpressionsService.registerType property + +Signature: + +```typescript +readonly registerType: (typeDefinition: AnyExpressionTypeDefinition | (() => AnyExpressionTypeDefinition)) => void; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsservice.renderers.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsservice.renderers.md new file mode 100644 index 0000000000000..e43e9a21050ea --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsservice.renderers.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionsService](./kibana-plugin-plugins-expressions-public.expressionsservice.md) > [renderers](./kibana-plugin-plugins-expressions-public.expressionsservice.renderers.md) + +## ExpressionsService.renderers property + +Signature: + +```typescript +readonly renderers: ExpressionRendererRegistry; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsservice.run.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsservice.run.md new file mode 100644 index 0000000000000..47469167f6360 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsservice.run.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionsService](./kibana-plugin-plugins-expressions-public.expressionsservice.md) > [run](./kibana-plugin-plugins-expressions-public.expressionsservice.run.md) + +## ExpressionsService.run property + +Signature: + +```typescript +readonly run: ExpressionsServiceStart['run']; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsservice.setup.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsservice.setup.md new file mode 100644 index 0000000000000..a51f3f073d518 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsservice.setup.md @@ -0,0 +1,17 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionsService](./kibana-plugin-plugins-expressions-public.expressionsservice.md) > [setup](./kibana-plugin-plugins-expressions-public.expressionsservice.setup.md) + +## ExpressionsService.setup() method + +Returns Kibana Platform \*setup\* life-cycle contract. Useful to return the same contract on server-side and browser-side. + +Signature: + +```typescript +setup(): ExpressionsServiceSetup; +``` +Returns: + +`ExpressionsServiceSetup` + diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsservice.start.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsservice.start.md new file mode 100644 index 0000000000000..766d703a0729d --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsservice.start.md @@ -0,0 +1,17 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionsService](./kibana-plugin-plugins-expressions-public.expressionsservice.md) > [start](./kibana-plugin-plugins-expressions-public.expressionsservice.start.md) + +## ExpressionsService.start() method + +Returns Kibana Platform \*start\* life-cycle contract. Useful to return the same contract on server-side and browser-side. + +Signature: + +```typescript +start(): ExpressionsServiceStart; +``` +Returns: + +`ExpressionsServiceStart` + diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsservice.stop.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsservice.stop.md new file mode 100644 index 0000000000000..a32bb4a8bb009 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsservice.stop.md @@ -0,0 +1,15 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionsService](./kibana-plugin-plugins-expressions-public.expressionsservice.md) > [stop](./kibana-plugin-plugins-expressions-public.expressionsservice.stop.md) + +## ExpressionsService.stop() method + +Signature: + +```typescript +stop(): void; +``` +Returns: + +`void` + diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsservicesetup.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsservicesetup.md new file mode 100644 index 0000000000000..4cf3fb9b53978 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsservicesetup.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionsServiceSetup](./kibana-plugin-plugins-expressions-public.expressionsservicesetup.md) + +## ExpressionsServiceSetup type + +The public contract that `ExpressionsService` provides to other plugins in Kibana Platform in \*setup\* life-cycle. + +Signature: + +```typescript +export declare type ExpressionsServiceSetup = Pick; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsservicestart.execute.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsservicestart.execute.md new file mode 100644 index 0000000000000..b8211a6bff27c --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsservicestart.execute.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionsServiceStart](./kibana-plugin-plugins-expressions-public.expressionsservicestart.md) > [execute](./kibana-plugin-plugins-expressions-public.expressionsservicestart.execute.md) + +## ExpressionsServiceStart.execute property + +Starts expression execution and immediately returns `ExecutionContract` instance that tracks the progress of the execution and can be used to interact with the execution. + +Signature: + +```typescript +execute: = Record>(ast: string | ExpressionAstExpression, input: Input, context?: ExtraContext) => ExecutionContract; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsservicestart.fork.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsservicestart.fork.md new file mode 100644 index 0000000000000..dd18daceb9539 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsservicestart.fork.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionsServiceStart](./kibana-plugin-plugins-expressions-public.expressionsservicestart.md) > [fork](./kibana-plugin-plugins-expressions-public.expressionsservicestart.fork.md) + +## ExpressionsServiceStart.fork property + +Create a new instance of `ExpressionsService`. The new instance inherits all state of the original `ExpressionsService`, including all expression types, expression functions and context. Also, all new types and functions registered in the original services AFTER the forking event will be available in the forked instance. However, all new types and functions registered in the forked instances will NOT be available to the original service. + +Signature: + +```typescript +fork: () => ExpressionsService; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsservicestart.getfunction.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsservicestart.getfunction.md new file mode 100644 index 0000000000000..d1a9bbce2a27e --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsservicestart.getfunction.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionsServiceStart](./kibana-plugin-plugins-expressions-public.expressionsservicestart.md) > [getFunction](./kibana-plugin-plugins-expressions-public.expressionsservicestart.getfunction.md) + +## ExpressionsServiceStart.getFunction property + +Get a registered `ExpressionFunction` by its name, which was registered using the `registerFunction` method. The returned `ExpressionFunction` instance is an internal representation of the function in Expressions service - do not mutate that object. + +Signature: + +```typescript +getFunction: (name: string) => ReturnType; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsservicestart.getrenderer.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsservicestart.getrenderer.md new file mode 100644 index 0000000000000..ef98fd633cb0c --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsservicestart.getrenderer.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionsServiceStart](./kibana-plugin-plugins-expressions-public.expressionsservicestart.md) > [getRenderer](./kibana-plugin-plugins-expressions-public.expressionsservicestart.getrenderer.md) + +## ExpressionsServiceStart.getRenderer property + +Get a registered `ExpressionRenderer` by its name, which was registered using the `registerRenderer` method. The returned `ExpressionRenderer` instance is an internal representation of the renderer in Expressions service - do not mutate that object. + +Signature: + +```typescript +getRenderer: (name: string) => ReturnType; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsservicestart.gettype.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsservicestart.gettype.md new file mode 100644 index 0000000000000..e9ec1733513ba --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsservicestart.gettype.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionsServiceStart](./kibana-plugin-plugins-expressions-public.expressionsservicestart.md) > [getType](./kibana-plugin-plugins-expressions-public.expressionsservicestart.gettype.md) + +## ExpressionsServiceStart.getType property + +Get a registered `ExpressionType` by its name, which was registered using the `registerType` method. The returned `ExpressionType` instance is an internal representation of the type in Expressions service - do not mutate that object. + +Signature: + +```typescript +getType: (name: string) => ReturnType; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsservicestart.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsservicestart.md new file mode 100644 index 0000000000000..34bf16c121326 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsservicestart.md @@ -0,0 +1,35 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionsServiceStart](./kibana-plugin-plugins-expressions-public.expressionsservicestart.md) + +## ExpressionsServiceStart interface + +The public contract that `ExpressionsService` provides to other plugins in Kibana Platform in \*start\* life-cycle. + +Signature: + +```typescript +export interface ExpressionsServiceStart +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [execute](./kibana-plugin-plugins-expressions-public.expressionsservicestart.execute.md) | <Input = unknown, Output = unknown, ExtraContext extends Record<string, unknown> = Record<string, unknown>>(ast: string | ExpressionAstExpression, input: Input, context?: ExtraContext) => ExecutionContract<ExtraContext, Input, Output> | Starts expression execution and immediately returns ExecutionContract instance that tracks the progress of the execution and can be used to interact with the execution. | +| [fork](./kibana-plugin-plugins-expressions-public.expressionsservicestart.fork.md) | () => ExpressionsService | Create a new instance of ExpressionsService. The new instance inherits all state of the original ExpressionsService, including all expression types, expression functions and context. Also, all new types and functions registered in the original services AFTER the forking event will be available in the forked instance. However, all new types and functions registered in the forked instances will NOT be available to the original service. | +| [getFunction](./kibana-plugin-plugins-expressions-public.expressionsservicestart.getfunction.md) | (name: string) => ReturnType<Executor['getFunction']> | Get a registered ExpressionFunction by its name, which was registered using the registerFunction method. The returned ExpressionFunction instance is an internal representation of the function in Expressions service - do not mutate that object. | +| [getRenderer](./kibana-plugin-plugins-expressions-public.expressionsservicestart.getrenderer.md) | (name: string) => ReturnType<ExpressionRendererRegistry['get']> | Get a registered ExpressionRenderer by its name, which was registered using the registerRenderer method. The returned ExpressionRenderer instance is an internal representation of the renderer in Expressions service - do not mutate that object. | +| [getType](./kibana-plugin-plugins-expressions-public.expressionsservicestart.gettype.md) | (name: string) => ReturnType<Executor['getType']> | Get a registered ExpressionType by its name, which was registered using the registerType method. The returned ExpressionType instance is an internal representation of the type in Expressions service - do not mutate that object. | +| [run](./kibana-plugin-plugins-expressions-public.expressionsservicestart.run.md) | <Input, Output, ExtraContext extends Record<string, unknown> = Record<string, unknown>>(ast: string | ExpressionAstExpression, input: Input, context?: ExtraContext) => Promise<Output> | Executes expression string or a parsed expression AST and immediately returns the result.Below example will execute sleep 100 | clog expression with 123 initial input to the first function. +```ts +expressions.run('sleep 100 | clog', 123); + +``` +- sleep 100 will delay execution by 100 milliseconds and pass the 123 input as its output. - clog will print to console 123 and pass it as its output. - The final result of the execution will be 123.Optionally, you can pass an object as the third argument which will be used to extend the ExecutionContext&mdash;an object passed to each function as the third argument, that allows functions to perform side-effects. +```ts +expressions.run('...', null, { elasticsearchClient }); + +``` + | + diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsservicestart.run.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsservicestart.run.md new file mode 100644 index 0000000000000..578c583624ad0 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsservicestart.run.md @@ -0,0 +1,28 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionsServiceStart](./kibana-plugin-plugins-expressions-public.expressionsservicestart.md) > [run](./kibana-plugin-plugins-expressions-public.expressionsservicestart.run.md) + +## ExpressionsServiceStart.run property + +Executes expression string or a parsed expression AST and immediately returns the result. + +Below example will execute `sleep 100 | clog` expression with `123` initial input to the first function. + +```ts +expressions.run('sleep 100 | clog', 123); + +``` +- `sleep 100` will delay execution by 100 milliseconds and pass the `123` input as its output. - `clog` will print to console `123` and pass it as its output. - The final result of the execution will be `123`. + +Optionally, you can pass an object as the third argument which will be used to extend the `ExecutionContext`&mdash;an object passed to each function as the third argument, that allows functions to perform side-effects. + +```ts +expressions.run('...', null, { elasticsearchClient }); + +``` + +Signature: + +```typescript +run: = Record>(ast: string | ExpressionAstExpression, input: Input, context?: ExtraContext) => Promise; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionssetup.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionssetup.md new file mode 100644 index 0000000000000..01a894ae8fba6 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionssetup.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionsSetup](./kibana-plugin-plugins-expressions-public.expressionssetup.md) + +## ExpressionsSetup type + +Expressions public setup contract, extends [ExpressionsServiceSetup](./kibana-plugin-plugins-expressions-public.expressionsservicesetup.md) + +Signature: + +```typescript +export declare type ExpressionsSetup = ExpressionsServiceSetup; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsstart.expressionloader.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsstart.expressionloader.md new file mode 100644 index 0000000000000..b7226b12b0d2b --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsstart.expressionloader.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionsStart](./kibana-plugin-plugins-expressions-public.expressionsstart.md) > [ExpressionLoader](./kibana-plugin-plugins-expressions-public.expressionsstart.expressionloader.md) + +## ExpressionsStart.ExpressionLoader property + +Signature: + +```typescript +ExpressionLoader: typeof ExpressionLoader; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsstart.expressionrenderhandler.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsstart.expressionrenderhandler.md new file mode 100644 index 0000000000000..a78bb6f154c46 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsstart.expressionrenderhandler.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionsStart](./kibana-plugin-plugins-expressions-public.expressionsstart.md) > [ExpressionRenderHandler](./kibana-plugin-plugins-expressions-public.expressionsstart.expressionrenderhandler.md) + +## ExpressionsStart.ExpressionRenderHandler property + +Signature: + +```typescript +ExpressionRenderHandler: typeof ExpressionRenderHandler; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsstart.loader.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsstart.loader.md new file mode 100644 index 0000000000000..109d8e8bcab66 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsstart.loader.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionsStart](./kibana-plugin-plugins-expressions-public.expressionsstart.md) > [loader](./kibana-plugin-plugins-expressions-public.expressionsstart.loader.md) + +## ExpressionsStart.loader property + +Signature: + +```typescript +loader: IExpressionLoader; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsstart.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsstart.md new file mode 100644 index 0000000000000..ac4004590b5a6 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsstart.md @@ -0,0 +1,24 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionsStart](./kibana-plugin-plugins-expressions-public.expressionsstart.md) + +## ExpressionsStart interface + +Expressions public start contrect, extends + +Signature: + +```typescript +export interface ExpressionsStart extends ExpressionsServiceStart +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [ExpressionLoader](./kibana-plugin-plugins-expressions-public.expressionsstart.expressionloader.md) | typeof ExpressionLoader | | +| [ExpressionRenderHandler](./kibana-plugin-plugins-expressions-public.expressionsstart.expressionrenderhandler.md) | typeof ExpressionRenderHandler | | +| [loader](./kibana-plugin-plugins-expressions-public.expressionsstart.loader.md) | IExpressionLoader | | +| [ReactExpressionRenderer](./kibana-plugin-plugins-expressions-public.expressionsstart.reactexpressionrenderer.md) | typeof ReactExpressionRenderer | | +| [render](./kibana-plugin-plugins-expressions-public.expressionsstart.render.md) | typeof render | | + diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsstart.reactexpressionrenderer.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsstart.reactexpressionrenderer.md new file mode 100644 index 0000000000000..bbd7253a747c4 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsstart.reactexpressionrenderer.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionsStart](./kibana-plugin-plugins-expressions-public.expressionsstart.md) > [ReactExpressionRenderer](./kibana-plugin-plugins-expressions-public.expressionsstart.reactexpressionrenderer.md) + +## ExpressionsStart.ReactExpressionRenderer property + +Signature: + +```typescript +ReactExpressionRenderer: typeof ReactExpressionRenderer; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsstart.render.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsstart.render.md new file mode 100644 index 0000000000000..fcf279206119e --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsstart.render.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionsStart](./kibana-plugin-plugins-expressions-public.expressionsstart.md) > [render](./kibana-plugin-plugins-expressions-public.expressionsstart.render.md) + +## ExpressionsStart.render property + +Signature: + +```typescript +render: typeof render; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressiontype._constructor_.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressiontype._constructor_.md new file mode 100644 index 0000000000000..2302be5643722 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressiontype._constructor_.md @@ -0,0 +1,20 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionType](./kibana-plugin-plugins-expressions-public.expressiontype.md) > [(constructor)](./kibana-plugin-plugins-expressions-public.expressiontype._constructor_.md) + +## ExpressionType.(constructor) + +Constructs a new instance of the `ExpressionType` class + +Signature: + +```typescript +constructor(definition: AnyExpressionTypeDefinition); +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| definition | AnyExpressionTypeDefinition | | + diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressiontype.castsfrom.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressiontype.castsfrom.md new file mode 100644 index 0000000000000..e238db1b45086 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressiontype.castsfrom.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionType](./kibana-plugin-plugins-expressions-public.expressiontype.md) > [castsFrom](./kibana-plugin-plugins-expressions-public.expressiontype.castsfrom.md) + +## ExpressionType.castsFrom property + +Signature: + +```typescript +castsFrom: (value: ExpressionValue) => boolean; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressiontype.caststo.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressiontype.caststo.md new file mode 100644 index 0000000000000..36e03e6f3d53f --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressiontype.caststo.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionType](./kibana-plugin-plugins-expressions-public.expressiontype.md) > [castsTo](./kibana-plugin-plugins-expressions-public.expressiontype.caststo.md) + +## ExpressionType.castsTo property + +Signature: + +```typescript +castsTo: (value: ExpressionValue) => boolean; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressiontype.create.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressiontype.create.md new file mode 100644 index 0000000000000..e2da70b50b0d4 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressiontype.create.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionType](./kibana-plugin-plugins-expressions-public.expressiontype.md) > [create](./kibana-plugin-plugins-expressions-public.expressiontype.create.md) + +## ExpressionType.create property + +Signature: + +```typescript +create: unknown; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressiontype.deserialize.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressiontype.deserialize.md new file mode 100644 index 0000000000000..d47056817358c --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressiontype.deserialize.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionType](./kibana-plugin-plugins-expressions-public.expressiontype.md) > [deserialize](./kibana-plugin-plugins-expressions-public.expressiontype.deserialize.md) + +## ExpressionType.deserialize property + +Signature: + +```typescript +deserialize?: (serialized: any) => ExpressionValue; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressiontype.from.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressiontype.from.md new file mode 100644 index 0000000000000..51a36f614fbbf --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressiontype.from.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionType](./kibana-plugin-plugins-expressions-public.expressiontype.md) > [from](./kibana-plugin-plugins-expressions-public.expressiontype.from.md) + +## ExpressionType.from property + +Signature: + +```typescript +from: (value: ExpressionValue, types: Record) => any; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressiontype.getfromfn.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressiontype.getfromfn.md new file mode 100644 index 0000000000000..10d7bb4331916 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressiontype.getfromfn.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionType](./kibana-plugin-plugins-expressions-public.expressiontype.md) > [getFromFn](./kibana-plugin-plugins-expressions-public.expressiontype.getfromfn.md) + +## ExpressionType.getFromFn property + +Signature: + +```typescript +getFromFn: (typeName: string) => undefined | ExpressionValueConverter; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressiontype.gettofn.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressiontype.gettofn.md new file mode 100644 index 0000000000000..25b71163e5709 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressiontype.gettofn.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionType](./kibana-plugin-plugins-expressions-public.expressiontype.md) > [getToFn](./kibana-plugin-plugins-expressions-public.expressiontype.gettofn.md) + +## ExpressionType.getToFn property + +Signature: + +```typescript +getToFn: (typeName: string) => undefined | ExpressionValueConverter; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressiontype.help.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressiontype.help.md new file mode 100644 index 0000000000000..e27e1dea2a872 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressiontype.help.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionType](./kibana-plugin-plugins-expressions-public.expressiontype.md) > [help](./kibana-plugin-plugins-expressions-public.expressiontype.help.md) + +## ExpressionType.help property + +A short help text. + +Signature: + +```typescript +help: string; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressiontype.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressiontype.md new file mode 100644 index 0000000000000..acb72b796cf1d --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressiontype.md @@ -0,0 +1,35 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionType](./kibana-plugin-plugins-expressions-public.expressiontype.md) + +## ExpressionType class + +Signature: + +```typescript +export declare class ExpressionType +``` + +## Constructors + +| Constructor | Modifiers | Description | +| --- | --- | --- | +| [(constructor)(definition)](./kibana-plugin-plugins-expressions-public.expressiontype._constructor_.md) | | Constructs a new instance of the ExpressionType class | + +## Properties + +| Property | Modifiers | Type | Description | +| --- | --- | --- | --- | +| [castsFrom](./kibana-plugin-plugins-expressions-public.expressiontype.castsfrom.md) | | (value: ExpressionValue) => boolean | | +| [castsTo](./kibana-plugin-plugins-expressions-public.expressiontype.caststo.md) | | (value: ExpressionValue) => boolean | | +| [create](./kibana-plugin-plugins-expressions-public.expressiontype.create.md) | | unknown | | +| [deserialize](./kibana-plugin-plugins-expressions-public.expressiontype.deserialize.md) | | (serialized: any) => ExpressionValue | | +| [from](./kibana-plugin-plugins-expressions-public.expressiontype.from.md) | | (value: ExpressionValue, types: Record<string, ExpressionType>) => any | | +| [getFromFn](./kibana-plugin-plugins-expressions-public.expressiontype.getfromfn.md) | | (typeName: string) => undefined | ExpressionValueConverter<ExpressionValue, ExpressionValue> | | +| [getToFn](./kibana-plugin-plugins-expressions-public.expressiontype.gettofn.md) | | (typeName: string) => undefined | ExpressionValueConverter<ExpressionValue, ExpressionValue> | | +| [help](./kibana-plugin-plugins-expressions-public.expressiontype.help.md) | | string | A short help text. | +| [name](./kibana-plugin-plugins-expressions-public.expressiontype.name.md) | | string | | +| [serialize](./kibana-plugin-plugins-expressions-public.expressiontype.serialize.md) | | (value: ExpressionValue) => any | Optional serialization (used when passing context around client/server). | +| [to](./kibana-plugin-plugins-expressions-public.expressiontype.to.md) | | (value: ExpressionValue, toTypeName: string, types: Record<string, ExpressionType>) => any | | +| [validate](./kibana-plugin-plugins-expressions-public.expressiontype.validate.md) | | (type: any) => void | Error | Type validation, useful for checking function output. | + diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressiontype.name.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressiontype.name.md new file mode 100644 index 0000000000000..8d14f6e4f6bd8 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressiontype.name.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionType](./kibana-plugin-plugins-expressions-public.expressiontype.md) > [name](./kibana-plugin-plugins-expressions-public.expressiontype.name.md) + +## ExpressionType.name property + +Signature: + +```typescript +name: string; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressiontype.serialize.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressiontype.serialize.md new file mode 100644 index 0000000000000..cb4821b97e022 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressiontype.serialize.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionType](./kibana-plugin-plugins-expressions-public.expressiontype.md) > [serialize](./kibana-plugin-plugins-expressions-public.expressiontype.serialize.md) + +## ExpressionType.serialize property + +Optional serialization (used when passing context around client/server). + +Signature: + +```typescript +serialize?: (value: ExpressionValue) => any; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressiontype.to.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressiontype.to.md new file mode 100644 index 0000000000000..8045c5df638b0 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressiontype.to.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionType](./kibana-plugin-plugins-expressions-public.expressiontype.md) > [to](./kibana-plugin-plugins-expressions-public.expressiontype.to.md) + +## ExpressionType.to property + +Signature: + +```typescript +to: (value: ExpressionValue, toTypeName: string, types: Record) => any; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressiontype.validate.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressiontype.validate.md new file mode 100644 index 0000000000000..7214467b2b444 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressiontype.validate.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionType](./kibana-plugin-plugins-expressions-public.expressiontype.md) > [validate](./kibana-plugin-plugins-expressions-public.expressiontype.validate.md) + +## ExpressionType.validate property + +Type validation, useful for checking function output. + +Signature: + +```typescript +validate: (type: any) => void | Error; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressiontypedefinition.deserialize.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressiontypedefinition.deserialize.md new file mode 100644 index 0000000000000..75dac1e991f65 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressiontypedefinition.deserialize.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionTypeDefinition](./kibana-plugin-plugins-expressions-public.expressiontypedefinition.md) > [deserialize](./kibana-plugin-plugins-expressions-public.expressiontypedefinition.deserialize.md) + +## ExpressionTypeDefinition.deserialize property + +Signature: + +```typescript +deserialize?: (type: SerializedType) => Value; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressiontypedefinition.from.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressiontypedefinition.from.md new file mode 100644 index 0000000000000..ac8920066eda7 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressiontypedefinition.from.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionTypeDefinition](./kibana-plugin-plugins-expressions-public.expressiontypedefinition.md) > [from](./kibana-plugin-plugins-expressions-public.expressiontypedefinition.from.md) + +## ExpressionTypeDefinition.from property + +Signature: + +```typescript +from?: { + [type: string]: ExpressionValueConverter; + }; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressiontypedefinition.help.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressiontypedefinition.help.md new file mode 100644 index 0000000000000..ad5e5eb38fa72 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressiontypedefinition.help.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionTypeDefinition](./kibana-plugin-plugins-expressions-public.expressiontypedefinition.md) > [help](./kibana-plugin-plugins-expressions-public.expressiontypedefinition.help.md) + +## ExpressionTypeDefinition.help property + +Signature: + +```typescript +help?: string; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressiontypedefinition.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressiontypedefinition.md new file mode 100644 index 0000000000000..8c183e9a6de80 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressiontypedefinition.md @@ -0,0 +1,26 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionTypeDefinition](./kibana-plugin-plugins-expressions-public.expressiontypedefinition.md) + +## ExpressionTypeDefinition interface + +A generic type which represents a custom Expression Type Definition that's registered to the Interpreter. + +Signature: + +```typescript +export interface ExpressionTypeDefinition +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [deserialize](./kibana-plugin-plugins-expressions-public.expressiontypedefinition.deserialize.md) | (type: SerializedType) => Value | | +| [from](./kibana-plugin-plugins-expressions-public.expressiontypedefinition.from.md) | {
    [type: string]: ExpressionValueConverter<any, Value>;
    } | | +| [help](./kibana-plugin-plugins-expressions-public.expressiontypedefinition.help.md) | string | | +| [name](./kibana-plugin-plugins-expressions-public.expressiontypedefinition.name.md) | Name | | +| [serialize](./kibana-plugin-plugins-expressions-public.expressiontypedefinition.serialize.md) | (type: Value) => SerializedType | | +| [to](./kibana-plugin-plugins-expressions-public.expressiontypedefinition.to.md) | {
    [type: string]: ExpressionValueConverter<Value, any>;
    } | | +| [validate](./kibana-plugin-plugins-expressions-public.expressiontypedefinition.validate.md) | (type: any) => void | Error | | + diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressiontypedefinition.name.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressiontypedefinition.name.md new file mode 100644 index 0000000000000..eb79d01040373 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressiontypedefinition.name.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionTypeDefinition](./kibana-plugin-plugins-expressions-public.expressiontypedefinition.md) > [name](./kibana-plugin-plugins-expressions-public.expressiontypedefinition.name.md) + +## ExpressionTypeDefinition.name property + +Signature: + +```typescript +name: Name; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressiontypedefinition.serialize.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressiontypedefinition.serialize.md new file mode 100644 index 0000000000000..5881ddbe5a6c4 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressiontypedefinition.serialize.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionTypeDefinition](./kibana-plugin-plugins-expressions-public.expressiontypedefinition.md) > [serialize](./kibana-plugin-plugins-expressions-public.expressiontypedefinition.serialize.md) + +## ExpressionTypeDefinition.serialize property + +Signature: + +```typescript +serialize?: (type: Value) => SerializedType; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressiontypedefinition.to.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressiontypedefinition.to.md new file mode 100644 index 0000000000000..282cdcdfb342d --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressiontypedefinition.to.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionTypeDefinition](./kibana-plugin-plugins-expressions-public.expressiontypedefinition.md) > [to](./kibana-plugin-plugins-expressions-public.expressiontypedefinition.to.md) + +## ExpressionTypeDefinition.to property + +Signature: + +```typescript +to?: { + [type: string]: ExpressionValueConverter; + }; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressiontypedefinition.validate.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressiontypedefinition.validate.md new file mode 100644 index 0000000000000..67d5e832c6284 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressiontypedefinition.validate.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionTypeDefinition](./kibana-plugin-plugins-expressions-public.expressiontypedefinition.md) > [validate](./kibana-plugin-plugins-expressions-public.expressiontypedefinition.validate.md) + +## ExpressionTypeDefinition.validate property + +Signature: + +```typescript +validate?: (type: any) => void | Error; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressiontypestyle.css.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressiontypestyle.css.md new file mode 100644 index 0000000000000..ca8e881ef7e46 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressiontypestyle.css.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionTypeStyle](./kibana-plugin-plugins-expressions-public.expressiontypestyle.md) > [css](./kibana-plugin-plugins-expressions-public.expressiontypestyle.css.md) + +## ExpressionTypeStyle.css property + +Signature: + +```typescript +css: string; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressiontypestyle.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressiontypestyle.md new file mode 100644 index 0000000000000..4e1cc86699f2d --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressiontypestyle.md @@ -0,0 +1,22 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionTypeStyle](./kibana-plugin-plugins-expressions-public.expressiontypestyle.md) + +## ExpressionTypeStyle interface + +An object that represents style information, typically CSS. + +Signature: + +```typescript +export interface ExpressionTypeStyle +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [css](./kibana-plugin-plugins-expressions-public.expressiontypestyle.css.md) | string | | +| [spec](./kibana-plugin-plugins-expressions-public.expressiontypestyle.spec.md) | CSSStyle | | +| [type](./kibana-plugin-plugins-expressions-public.expressiontypestyle.type.md) | 'style' | | + diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressiontypestyle.spec.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressiontypestyle.spec.md new file mode 100644 index 0000000000000..e732893366a36 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressiontypestyle.spec.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionTypeStyle](./kibana-plugin-plugins-expressions-public.expressiontypestyle.md) > [spec](./kibana-plugin-plugins-expressions-public.expressiontypestyle.spec.md) + +## ExpressionTypeStyle.spec property + +Signature: + +```typescript +spec: CSSStyle; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressiontypestyle.type.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressiontypestyle.type.md new file mode 100644 index 0000000000000..01dd9b0da1072 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressiontypestyle.type.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionTypeStyle](./kibana-plugin-plugins-expressions-public.expressiontypestyle.md) > [type](./kibana-plugin-plugins-expressions-public.expressiontypestyle.type.md) + +## ExpressionTypeStyle.type property + +Signature: + +```typescript +type: 'style'; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionvalue.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionvalue.md new file mode 100644 index 0000000000000..53ab339df902a --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionvalue.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionValue](./kibana-plugin-plugins-expressions-public.expressionvalue.md) + +## ExpressionValue type + +Signature: + +```typescript +export declare type ExpressionValue = ExpressionValueUnboxed | ExpressionValueBoxed; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionvalueboxed.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionvalueboxed.md new file mode 100644 index 0000000000000..6d8f060d4f91f --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionvalueboxed.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionValueBoxed](./kibana-plugin-plugins-expressions-public.expressionvalueboxed.md) + +## ExpressionValueBoxed type + +Signature: + +```typescript +export declare type ExpressionValueBoxed = { + type: Type; +} & Value; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionvalueconverter.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionvalueconverter.md new file mode 100644 index 0000000000000..95e69645b53ee --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionvalueconverter.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionValueConverter](./kibana-plugin-plugins-expressions-public.expressionvalueconverter.md) + +## ExpressionValueConverter type + +Signature: + +```typescript +export declare type ExpressionValueConverter = (input: I, availableTypes: Record) => O; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionvalueerror.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionvalueerror.md new file mode 100644 index 0000000000000..4a714fe62424f --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionvalueerror.md @@ -0,0 +1,20 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionValueError](./kibana-plugin-plugins-expressions-public.expressionvalueerror.md) + +## ExpressionValueError type + +Signature: + +```typescript +export declare type ExpressionValueError = ExpressionValueBoxed<'error', { + error: { + message: string; + type?: string; + name?: string; + stack?: string; + original?: Error; + }; + info?: unknown; +}>; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionvaluefilter.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionvaluefilter.md new file mode 100644 index 0000000000000..07c1bfe9a96d6 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionvaluefilter.md @@ -0,0 +1,21 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionValueFilter](./kibana-plugin-plugins-expressions-public.expressionvaluefilter.md) + +## ExpressionValueFilter type + +Represents an object that is a Filter. + +Signature: + +```typescript +export declare type ExpressionValueFilter = ExpressionValueBoxed<'filter', { + filterType?: string; + value?: string; + column?: string; + and: ExpressionValueFilter[]; + to?: string; + from?: string; + query?: string | null; +}>; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionvaluenum.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionvaluenum.md new file mode 100644 index 0000000000000..fc92777ffd5b6 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionvaluenum.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionValueNum](./kibana-plugin-plugins-expressions-public.expressionvaluenum.md) + +## ExpressionValueNum type + +Signature: + +```typescript +export declare type ExpressionValueNum = ExpressionValueBoxed<'num', { + value: number; +}>; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionvaluerender.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionvaluerender.md new file mode 100644 index 0000000000000..be9e7f859daec --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionvaluerender.md @@ -0,0 +1,16 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionValueRender](./kibana-plugin-plugins-expressions-public.expressionvaluerender.md) + +## ExpressionValueRender type + +Represents an object that is intended to be rendered. + +Signature: + +```typescript +export declare type ExpressionValueRender = ExpressionValueBoxed; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionvaluesearchcontext.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionvaluesearchcontext.md new file mode 100644 index 0000000000000..bf64dfe4c86f7 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionvaluesearchcontext.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionValueSearchContext](./kibana-plugin-plugins-expressions-public.expressionvaluesearchcontext.md) + +## ExpressionValueSearchContext type + +Signature: + +```typescript +export declare type ExpressionValueSearchContext = ExpressionValueBoxed<'kibana_context', ExecutionContextSearch>; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionvalueunboxed.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionvalueunboxed.md new file mode 100644 index 0000000000000..fbc37fe667d5e --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionvalueunboxed.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionValueUnboxed](./kibana-plugin-plugins-expressions-public.expressionvalueunboxed.md) + +## ExpressionValueUnboxed type + +Signature: + +```typescript +export declare type ExpressionValueUnboxed = any; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.font.label.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.font.label.md new file mode 100644 index 0000000000000..87294ce59feb6 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.font.label.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [Font](./kibana-plugin-plugins-expressions-public.font.md) > [label](./kibana-plugin-plugins-expressions-public.font.label.md) + +## Font.label property + +Signature: + +```typescript +label: FontLabel; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.font.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.font.md new file mode 100644 index 0000000000000..ef63d28fe6fba --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.font.md @@ -0,0 +1,21 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [Font](./kibana-plugin-plugins-expressions-public.font.md) + +## Font interface + +An interface representing a font in Canvas, with a textual label and the CSS `font-value`. + +Signature: + +```typescript +export interface Font +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [label](./kibana-plugin-plugins-expressions-public.font.label.md) | FontLabel | | +| [value](./kibana-plugin-plugins-expressions-public.font.value.md) | FontValue | | + diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.font.value.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.font.value.md new file mode 100644 index 0000000000000..cada244174785 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.font.value.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [Font](./kibana-plugin-plugins-expressions-public.font.md) > [value](./kibana-plugin-plugins-expressions-public.font.value.md) + +## Font.value property + +Signature: + +```typescript +value: FontValue; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.fontlabel.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.fontlabel.md new file mode 100644 index 0000000000000..5af3427730ad1 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.fontlabel.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [FontLabel](./kibana-plugin-plugins-expressions-public.fontlabel.md) + +## FontLabel type + +This type contains a unions of all supported font labels, or the the name of the font the user would see in a UI. + +Signature: + +```typescript +export declare type FontLabel = typeof fonts[number]['label']; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.fontstyle.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.fontstyle.md new file mode 100644 index 0000000000000..9f70d91c7ac9b --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.fontstyle.md @@ -0,0 +1,21 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [FontStyle](./kibana-plugin-plugins-expressions-public.fontstyle.md) + +## FontStyle enum + +Enum of supported CSS `font-style` properties. + +Signature: + +```typescript +export declare enum FontStyle +``` + +## Enumeration Members + +| Member | Value | Description | +| --- | --- | --- | +| ITALIC | "italic" | | +| NORMAL | "normal" | | + diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.fontvalue.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.fontvalue.md new file mode 100644 index 0000000000000..f03c9b61cb733 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.fontvalue.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [FontValue](./kibana-plugin-plugins-expressions-public.fontvalue.md) + +## FontValue type + +This type contains a union of all supported font values, equivalent to the CSS `font-value` property. + +Signature: + +```typescript +export declare type FontValue = typeof fonts[number]['value']; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.fontweight.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.fontweight.md new file mode 100644 index 0000000000000..43388a3de11cc --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.fontweight.md @@ -0,0 +1,32 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [FontWeight](./kibana-plugin-plugins-expressions-public.fontweight.md) + +## FontWeight enum + +Enum of supported CSS `font-weight` properties. + +Signature: + +```typescript +export declare enum FontWeight +``` + +## Enumeration Members + +| Member | Value | Description | +| --- | --- | --- | +| BOLD | "bold" | | +| BOLDER | "bolder" | | +| EIGHT | "800" | | +| FIVE | "500" | | +| FOUR | "400" | | +| LIGHTER | "lighter" | | +| NINE | "900" | | +| NORMAL | "normal" | | +| ONE | "100" | | +| SEVEN | "700" | | +| SIX | "600" | | +| THREE | "300" | | +| TWO | "200" | | + diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.format.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.format.md new file mode 100644 index 0000000000000..27a9690e6fb0d --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.format.md @@ -0,0 +1,23 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [format](./kibana-plugin-plugins-expressions-public.format.md) + +## format() function + +Signature: + +```typescript +export declare function format(ast: T, type: T extends ExpressionAstExpression ? 'expression' : 'argument'): string; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| ast | T | | +| type | T extends ExpressionAstExpression ? 'expression' : 'argument' | | + +Returns: + +`string` + diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.formatexpression.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.formatexpression.md new file mode 100644 index 0000000000000..425aa9c6171fc --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.formatexpression.md @@ -0,0 +1,24 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [formatExpression](./kibana-plugin-plugins-expressions-public.formatexpression.md) + +## formatExpression() function + +Given expression pipeline AST, returns formatted string. + +Signature: + +```typescript +export declare function formatExpression(ast: ExpressionAstExpression): string; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| ast | ExpressionAstExpression | | + +Returns: + +`string` + diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.functionsregistry._constructor_.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.functionsregistry._constructor_.md new file mode 100644 index 0000000000000..2ab299e3d32f4 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.functionsregistry._constructor_.md @@ -0,0 +1,20 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [FunctionsRegistry](./kibana-plugin-plugins-expressions-public.functionsregistry.md) > [(constructor)](./kibana-plugin-plugins-expressions-public.functionsregistry._constructor_.md) + +## FunctionsRegistry.(constructor) + +Constructs a new instance of the `FunctionsRegistry` class + +Signature: + +```typescript +constructor(executor: Executor); +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| executor | Executor<any> | | + diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.functionsregistry.get.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.functionsregistry.get.md new file mode 100644 index 0000000000000..3ed2807028299 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.functionsregistry.get.md @@ -0,0 +1,22 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [FunctionsRegistry](./kibana-plugin-plugins-expressions-public.functionsregistry.md) > [get](./kibana-plugin-plugins-expressions-public.functionsregistry.get.md) + +## FunctionsRegistry.get() method + +Signature: + +```typescript +get(id: string): ExpressionFunction | null; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| id | string | | + +Returns: + +`ExpressionFunction | null` + diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.functionsregistry.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.functionsregistry.md new file mode 100644 index 0000000000000..b32623934ee92 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.functionsregistry.md @@ -0,0 +1,27 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [FunctionsRegistry](./kibana-plugin-plugins-expressions-public.functionsregistry.md) + +## FunctionsRegistry class + +Signature: + +```typescript +export declare class FunctionsRegistry implements IRegistry +``` + +## Constructors + +| Constructor | Modifiers | Description | +| --- | --- | --- | +| [(constructor)(executor)](./kibana-plugin-plugins-expressions-public.functionsregistry._constructor_.md) | | Constructs a new instance of the FunctionsRegistry class | + +## Methods + +| Method | Modifiers | Description | +| --- | --- | --- | +| [get(id)](./kibana-plugin-plugins-expressions-public.functionsregistry.get.md) | | | +| [register(functionDefinition)](./kibana-plugin-plugins-expressions-public.functionsregistry.register.md) | | | +| [toArray()](./kibana-plugin-plugins-expressions-public.functionsregistry.toarray.md) | | | +| [toJS()](./kibana-plugin-plugins-expressions-public.functionsregistry.tojs.md) | | | + diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.functionsregistry.register.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.functionsregistry.register.md new file mode 100644 index 0000000000000..32f7f389e8958 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.functionsregistry.register.md @@ -0,0 +1,22 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [FunctionsRegistry](./kibana-plugin-plugins-expressions-public.functionsregistry.md) > [register](./kibana-plugin-plugins-expressions-public.functionsregistry.register.md) + +## FunctionsRegistry.register() method + +Signature: + +```typescript +register(functionDefinition: AnyExpressionFunctionDefinition | (() => AnyExpressionFunctionDefinition)): void; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| functionDefinition | AnyExpressionFunctionDefinition | (() => AnyExpressionFunctionDefinition) | | + +Returns: + +`void` + diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.functionsregistry.toarray.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.functionsregistry.toarray.md new file mode 100644 index 0000000000000..5bc482097a175 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.functionsregistry.toarray.md @@ -0,0 +1,15 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [FunctionsRegistry](./kibana-plugin-plugins-expressions-public.functionsregistry.md) > [toArray](./kibana-plugin-plugins-expressions-public.functionsregistry.toarray.md) + +## FunctionsRegistry.toArray() method + +Signature: + +```typescript +toArray(): ExpressionFunction[]; +``` +Returns: + +`ExpressionFunction[]` + diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.functionsregistry.tojs.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.functionsregistry.tojs.md new file mode 100644 index 0000000000000..d6790fb8f726e --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.functionsregistry.tojs.md @@ -0,0 +1,15 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [FunctionsRegistry](./kibana-plugin-plugins-expressions-public.functionsregistry.md) > [toJS](./kibana-plugin-plugins-expressions-public.functionsregistry.tojs.md) + +## FunctionsRegistry.toJS() method + +Signature: + +```typescript +toJS(): Record; +``` +Returns: + +`Record` + diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.iexpressionloaderparams.context.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.iexpressionloaderparams.context.md new file mode 100644 index 0000000000000..40dcf07667b1b --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.iexpressionloaderparams.context.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [IExpressionLoaderParams](./kibana-plugin-plugins-expressions-public.iexpressionloaderparams.md) > [context](./kibana-plugin-plugins-expressions-public.iexpressionloaderparams.context.md) + +## IExpressionLoaderParams.context property + +Signature: + +```typescript +context?: ExpressionValue; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.iexpressionloaderparams.customfunctions.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.iexpressionloaderparams.customfunctions.md new file mode 100644 index 0000000000000..00ff3d498eb5c --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.iexpressionloaderparams.customfunctions.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [IExpressionLoaderParams](./kibana-plugin-plugins-expressions-public.iexpressionloaderparams.md) > [customFunctions](./kibana-plugin-plugins-expressions-public.iexpressionloaderparams.customfunctions.md) + +## IExpressionLoaderParams.customFunctions property + +Signature: + +```typescript +customFunctions?: []; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.iexpressionloaderparams.customrenderers.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.iexpressionloaderparams.customrenderers.md new file mode 100644 index 0000000000000..72b82e2d41b05 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.iexpressionloaderparams.customrenderers.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [IExpressionLoaderParams](./kibana-plugin-plugins-expressions-public.iexpressionloaderparams.md) > [customRenderers](./kibana-plugin-plugins-expressions-public.iexpressionloaderparams.customrenderers.md) + +## IExpressionLoaderParams.customRenderers property + +Signature: + +```typescript +customRenderers?: []; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.iexpressionloaderparams.disablecaching.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.iexpressionloaderparams.disablecaching.md new file mode 100644 index 0000000000000..62483016d3aee --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.iexpressionloaderparams.disablecaching.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [IExpressionLoaderParams](./kibana-plugin-plugins-expressions-public.iexpressionloaderparams.md) > [disableCaching](./kibana-plugin-plugins-expressions-public.iexpressionloaderparams.disablecaching.md) + +## IExpressionLoaderParams.disableCaching property + +Signature: + +```typescript +disableCaching?: boolean; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.iexpressionloaderparams.inspectoradapters.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.iexpressionloaderparams.inspectoradapters.md new file mode 100644 index 0000000000000..52f2a6e56d133 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.iexpressionloaderparams.inspectoradapters.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [IExpressionLoaderParams](./kibana-plugin-plugins-expressions-public.iexpressionloaderparams.md) > [inspectorAdapters](./kibana-plugin-plugins-expressions-public.iexpressionloaderparams.inspectoradapters.md) + +## IExpressionLoaderParams.inspectorAdapters property + +Signature: + +```typescript +inspectorAdapters?: Adapters; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.iexpressionloaderparams.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.iexpressionloaderparams.md new file mode 100644 index 0000000000000..b8a174f93fb99 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.iexpressionloaderparams.md @@ -0,0 +1,26 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [IExpressionLoaderParams](./kibana-plugin-plugins-expressions-public.iexpressionloaderparams.md) + +## IExpressionLoaderParams interface + +Signature: + +```typescript +export interface IExpressionLoaderParams +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [context](./kibana-plugin-plugins-expressions-public.iexpressionloaderparams.context.md) | ExpressionValue | | +| [customFunctions](./kibana-plugin-plugins-expressions-public.iexpressionloaderparams.customfunctions.md) | [] | | +| [customRenderers](./kibana-plugin-plugins-expressions-public.iexpressionloaderparams.customrenderers.md) | [] | | +| [disableCaching](./kibana-plugin-plugins-expressions-public.iexpressionloaderparams.disablecaching.md) | boolean | | +| [inspectorAdapters](./kibana-plugin-plugins-expressions-public.iexpressionloaderparams.inspectoradapters.md) | Adapters | | +| [onRenderError](./kibana-plugin-plugins-expressions-public.iexpressionloaderparams.onrendererror.md) | RenderErrorHandlerFnType | | +| [searchContext](./kibana-plugin-plugins-expressions-public.iexpressionloaderparams.searchcontext.md) | ExecutionContextSearch | | +| [uiState](./kibana-plugin-plugins-expressions-public.iexpressionloaderparams.uistate.md) | unknown | | +| [variables](./kibana-plugin-plugins-expressions-public.iexpressionloaderparams.variables.md) | Record<string, any> | | + diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.iexpressionloaderparams.onrendererror.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.iexpressionloaderparams.onrendererror.md new file mode 100644 index 0000000000000..f45a9c76242c4 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.iexpressionloaderparams.onrendererror.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [IExpressionLoaderParams](./kibana-plugin-plugins-expressions-public.iexpressionloaderparams.md) > [onRenderError](./kibana-plugin-plugins-expressions-public.iexpressionloaderparams.onrendererror.md) + +## IExpressionLoaderParams.onRenderError property + +Signature: + +```typescript +onRenderError?: RenderErrorHandlerFnType; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.iexpressionloaderparams.searchcontext.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.iexpressionloaderparams.searchcontext.md new file mode 100644 index 0000000000000..523d0c562f7ca --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.iexpressionloaderparams.searchcontext.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [IExpressionLoaderParams](./kibana-plugin-plugins-expressions-public.iexpressionloaderparams.md) > [searchContext](./kibana-plugin-plugins-expressions-public.iexpressionloaderparams.searchcontext.md) + +## IExpressionLoaderParams.searchContext property + +Signature: + +```typescript +searchContext?: ExecutionContextSearch; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.iexpressionloaderparams.uistate.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.iexpressionloaderparams.uistate.md new file mode 100644 index 0000000000000..dca5032dabc78 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.iexpressionloaderparams.uistate.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [IExpressionLoaderParams](./kibana-plugin-plugins-expressions-public.iexpressionloaderparams.md) > [uiState](./kibana-plugin-plugins-expressions-public.iexpressionloaderparams.uistate.md) + +## IExpressionLoaderParams.uiState property + +Signature: + +```typescript +uiState?: unknown; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.iexpressionloaderparams.variables.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.iexpressionloaderparams.variables.md new file mode 100644 index 0000000000000..0a04671919bd0 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.iexpressionloaderparams.variables.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [IExpressionLoaderParams](./kibana-plugin-plugins-expressions-public.iexpressionloaderparams.md) > [variables](./kibana-plugin-plugins-expressions-public.iexpressionloaderparams.variables.md) + +## IExpressionLoaderParams.variables property + +Signature: + +```typescript +variables?: Record; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.iinterpreterrenderhandlers.done.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.iinterpreterrenderhandlers.done.md new file mode 100644 index 0000000000000..533cf498d72cf --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.iinterpreterrenderhandlers.done.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [IInterpreterRenderHandlers](./kibana-plugin-plugins-expressions-public.iinterpreterrenderhandlers.md) > [done](./kibana-plugin-plugins-expressions-public.iinterpreterrenderhandlers.done.md) + +## IInterpreterRenderHandlers.done property + +Done increments the number of rendering successes + +Signature: + +```typescript +done: () => void; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.iinterpreterrenderhandlers.event.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.iinterpreterrenderhandlers.event.md new file mode 100644 index 0000000000000..476167965927d --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.iinterpreterrenderhandlers.event.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [IInterpreterRenderHandlers](./kibana-plugin-plugins-expressions-public.iinterpreterrenderhandlers.md) > [event](./kibana-plugin-plugins-expressions-public.iinterpreterrenderhandlers.event.md) + +## IInterpreterRenderHandlers.event property + +Signature: + +```typescript +event: (event: any) => void; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.iinterpreterrenderhandlers.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.iinterpreterrenderhandlers.md new file mode 100644 index 0000000000000..ab0273be71402 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.iinterpreterrenderhandlers.md @@ -0,0 +1,23 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [IInterpreterRenderHandlers](./kibana-plugin-plugins-expressions-public.iinterpreterrenderhandlers.md) + +## IInterpreterRenderHandlers interface + +Signature: + +```typescript +export interface IInterpreterRenderHandlers +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [done](./kibana-plugin-plugins-expressions-public.iinterpreterrenderhandlers.done.md) | () => void | Done increments the number of rendering successes | +| [event](./kibana-plugin-plugins-expressions-public.iinterpreterrenderhandlers.event.md) | (event: any) => void | | +| [onDestroy](./kibana-plugin-plugins-expressions-public.iinterpreterrenderhandlers.ondestroy.md) | (fn: () => void) => void | | +| [reload](./kibana-plugin-plugins-expressions-public.iinterpreterrenderhandlers.reload.md) | () => void | | +| [uiState](./kibana-plugin-plugins-expressions-public.iinterpreterrenderhandlers.uistate.md) | PersistedState | | +| [update](./kibana-plugin-plugins-expressions-public.iinterpreterrenderhandlers.update.md) | (params: any) => void | | + diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.iinterpreterrenderhandlers.ondestroy.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.iinterpreterrenderhandlers.ondestroy.md new file mode 100644 index 0000000000000..b68c2023fdc8a --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.iinterpreterrenderhandlers.ondestroy.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [IInterpreterRenderHandlers](./kibana-plugin-plugins-expressions-public.iinterpreterrenderhandlers.md) > [onDestroy](./kibana-plugin-plugins-expressions-public.iinterpreterrenderhandlers.ondestroy.md) + +## IInterpreterRenderHandlers.onDestroy property + +Signature: + +```typescript +onDestroy: (fn: () => void) => void; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.iinterpreterrenderhandlers.reload.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.iinterpreterrenderhandlers.reload.md new file mode 100644 index 0000000000000..0acd440e84f12 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.iinterpreterrenderhandlers.reload.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [IInterpreterRenderHandlers](./kibana-plugin-plugins-expressions-public.iinterpreterrenderhandlers.md) > [reload](./kibana-plugin-plugins-expressions-public.iinterpreterrenderhandlers.reload.md) + +## IInterpreterRenderHandlers.reload property + +Signature: + +```typescript +reload: () => void; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.iinterpreterrenderhandlers.uistate.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.iinterpreterrenderhandlers.uistate.md new file mode 100644 index 0000000000000..8d74c8e555fee --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.iinterpreterrenderhandlers.uistate.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [IInterpreterRenderHandlers](./kibana-plugin-plugins-expressions-public.iinterpreterrenderhandlers.md) > [uiState](./kibana-plugin-plugins-expressions-public.iinterpreterrenderhandlers.uistate.md) + +## IInterpreterRenderHandlers.uiState property + +Signature: + +```typescript +uiState?: PersistedState; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.iinterpreterrenderhandlers.update.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.iinterpreterrenderhandlers.update.md new file mode 100644 index 0000000000000..28fcb58fb3c10 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.iinterpreterrenderhandlers.update.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [IInterpreterRenderHandlers](./kibana-plugin-plugins-expressions-public.iinterpreterrenderhandlers.md) > [update](./kibana-plugin-plugins-expressions-public.iinterpreterrenderhandlers.update.md) + +## IInterpreterRenderHandlers.update property + +Signature: + +```typescript +update: (params: any) => void; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.interpretererrortype.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.interpretererrortype.md new file mode 100644 index 0000000000000..8cb346eda4d74 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.interpretererrortype.md @@ -0,0 +1,16 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [InterpreterErrorType](./kibana-plugin-plugins-expressions-public.interpretererrortype.md) + +## InterpreterErrorType type + +> Warning: This API is now obsolete. +> +> Exported for backwards compatibility. +> + +Signature: + +```typescript +export declare type InterpreterErrorType = ExpressionValueError; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.iregistry.get.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.iregistry.get.md new file mode 100644 index 0000000000000..9aa696869eaa3 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.iregistry.get.md @@ -0,0 +1,22 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [IRegistry](./kibana-plugin-plugins-expressions-public.iregistry.md) > [get](./kibana-plugin-plugins-expressions-public.iregistry.get.md) + +## IRegistry.get() method + +Signature: + +```typescript +get(id: string): T | null; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| id | string | | + +Returns: + +`T | null` + diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.iregistry.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.iregistry.md new file mode 100644 index 0000000000000..64991d90f2ae0 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.iregistry.md @@ -0,0 +1,20 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [IRegistry](./kibana-plugin-plugins-expressions-public.iregistry.md) + +## IRegistry interface + +Signature: + +```typescript +export interface IRegistry +``` + +## Methods + +| Method | Description | +| --- | --- | +| [get(id)](./kibana-plugin-plugins-expressions-public.iregistry.get.md) | | +| [toArray()](./kibana-plugin-plugins-expressions-public.iregistry.toarray.md) | | +| [toJS()](./kibana-plugin-plugins-expressions-public.iregistry.tojs.md) | | + diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.iregistry.toarray.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.iregistry.toarray.md new file mode 100644 index 0000000000000..36b16ca48323f --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.iregistry.toarray.md @@ -0,0 +1,15 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [IRegistry](./kibana-plugin-plugins-expressions-public.iregistry.md) > [toArray](./kibana-plugin-plugins-expressions-public.iregistry.toarray.md) + +## IRegistry.toArray() method + +Signature: + +```typescript +toArray(): T[]; +``` +Returns: + +`T[]` + diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.iregistry.tojs.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.iregistry.tojs.md new file mode 100644 index 0000000000000..2f7a3597c1f02 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.iregistry.tojs.md @@ -0,0 +1,15 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [IRegistry](./kibana-plugin-plugins-expressions-public.iregistry.md) > [toJS](./kibana-plugin-plugins-expressions-public.iregistry.tojs.md) + +## IRegistry.toJS() method + +Signature: + +```typescript +toJS(): Record; +``` +Returns: + +`Record` + diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.isexpressionastbuilder.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.isexpressionastbuilder.md new file mode 100644 index 0000000000000..f35e7122caeb5 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.isexpressionastbuilder.md @@ -0,0 +1,28 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [isExpressionAstBuilder](./kibana-plugin-plugins-expressions-public.isexpressionastbuilder.md) + +## isExpressionAstBuilder() function + +Type guard that checks whether a given value is an `ExpressionAstExpressionBuilder`. This is useful when working with subexpressions, where you might be retrieving a function argument, and need to know whether it is an expression builder instance which you can perform operations on. + +Signature: + +```typescript +export declare function isExpressionAstBuilder(val: any): val is ExpressionAstExpressionBuilder; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| val | any | | + +Returns: + +`val is ExpressionAstExpressionBuilder` + +## Example + +const arg = myFunction.getArgument('foo'); if (isExpressionAstBuilder(foo)) { foo.toAst(); } + diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.kibana_context_name.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.kibana_context_name.md new file mode 100644 index 0000000000000..e568db84f383d --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.kibana_context_name.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [KIBANA\_CONTEXT\_NAME](./kibana-plugin-plugins-expressions-public.kibana_context_name.md) + +## KIBANA\_CONTEXT\_NAME type + +Signature: + +```typescript +export declare type KIBANA_CONTEXT_NAME = 'kibana_context'; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.kibanacontext.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.kibanacontext.md new file mode 100644 index 0000000000000..108533e8de357 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.kibanacontext.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [KibanaContext](./kibana-plugin-plugins-expressions-public.kibanacontext.md) + +## KibanaContext type + +Signature: + +```typescript +export declare type KibanaContext = ExpressionValueSearchContext; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.kibanadatatable.columns.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.kibanadatatable.columns.md new file mode 100644 index 0000000000000..c8aa768a883d6 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.kibanadatatable.columns.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [KibanaDatatable](./kibana-plugin-plugins-expressions-public.kibanadatatable.md) > [columns](./kibana-plugin-plugins-expressions-public.kibanadatatable.columns.md) + +## KibanaDatatable.columns property + +Signature: + +```typescript +columns: KibanaDatatableColumn[]; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.kibanadatatable.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.kibanadatatable.md new file mode 100644 index 0000000000000..4ea1d6f42b66d --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.kibanadatatable.md @@ -0,0 +1,20 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [KibanaDatatable](./kibana-plugin-plugins-expressions-public.kibanadatatable.md) + +## KibanaDatatable interface + +Signature: + +```typescript +export interface KibanaDatatable +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [columns](./kibana-plugin-plugins-expressions-public.kibanadatatable.columns.md) | KibanaDatatableColumn[] | | +| [rows](./kibana-plugin-plugins-expressions-public.kibanadatatable.rows.md) | KibanaDatatableRow[] | | +| [type](./kibana-plugin-plugins-expressions-public.kibanadatatable.type.md) | typeof name | | + diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.kibanadatatable.rows.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.kibanadatatable.rows.md new file mode 100644 index 0000000000000..43f3243dc4fa7 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.kibanadatatable.rows.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [KibanaDatatable](./kibana-plugin-plugins-expressions-public.kibanadatatable.md) > [rows](./kibana-plugin-plugins-expressions-public.kibanadatatable.rows.md) + +## KibanaDatatable.rows property + +Signature: + +```typescript +rows: KibanaDatatableRow[]; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.kibanadatatable.type.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.kibanadatatable.type.md new file mode 100644 index 0000000000000..996f59cbb77a1 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.kibanadatatable.type.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [KibanaDatatable](./kibana-plugin-plugins-expressions-public.kibanadatatable.md) > [type](./kibana-plugin-plugins-expressions-public.kibanadatatable.type.md) + +## KibanaDatatable.type property + +Signature: + +```typescript +type: typeof name; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.kibanadatatablecolumn.formathint.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.kibanadatatablecolumn.formathint.md new file mode 100644 index 0000000000000..b517c1610261b --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.kibanadatatablecolumn.formathint.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [KibanaDatatableColumn](./kibana-plugin-plugins-expressions-public.kibanadatatablecolumn.md) > [formatHint](./kibana-plugin-plugins-expressions-public.kibanadatatablecolumn.formathint.md) + +## KibanaDatatableColumn.formatHint property + +Signature: + +```typescript +formatHint?: SerializedFieldFormat; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.kibanadatatablecolumn.id.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.kibanadatatablecolumn.id.md new file mode 100644 index 0000000000000..e7d43190589a7 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.kibanadatatablecolumn.id.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [KibanaDatatableColumn](./kibana-plugin-plugins-expressions-public.kibanadatatablecolumn.md) > [id](./kibana-plugin-plugins-expressions-public.kibanadatatablecolumn.id.md) + +## KibanaDatatableColumn.id property + +Signature: + +```typescript +id: string; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.kibanadatatablecolumn.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.kibanadatatablecolumn.md new file mode 100644 index 0000000000000..138c19f0ec7bd --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.kibanadatatablecolumn.md @@ -0,0 +1,21 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [KibanaDatatableColumn](./kibana-plugin-plugins-expressions-public.kibanadatatablecolumn.md) + +## KibanaDatatableColumn interface + +Signature: + +```typescript +export interface KibanaDatatableColumn +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [formatHint](./kibana-plugin-plugins-expressions-public.kibanadatatablecolumn.formathint.md) | SerializedFieldFormat | | +| [id](./kibana-plugin-plugins-expressions-public.kibanadatatablecolumn.id.md) | string | | +| [meta](./kibana-plugin-plugins-expressions-public.kibanadatatablecolumn.meta.md) | KibanaDatatableColumnMeta | | +| [name](./kibana-plugin-plugins-expressions-public.kibanadatatablecolumn.name.md) | string | | + diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.kibanadatatablecolumn.meta.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.kibanadatatablecolumn.meta.md new file mode 100644 index 0000000000000..df2d09bf3cc55 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.kibanadatatablecolumn.meta.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [KibanaDatatableColumn](./kibana-plugin-plugins-expressions-public.kibanadatatablecolumn.md) > [meta](./kibana-plugin-plugins-expressions-public.kibanadatatablecolumn.meta.md) + +## KibanaDatatableColumn.meta property + +Signature: + +```typescript +meta?: KibanaDatatableColumnMeta; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.kibanadatatablecolumn.name.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.kibanadatatablecolumn.name.md new file mode 100644 index 0000000000000..841ad67f3f521 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.kibanadatatablecolumn.name.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [KibanaDatatableColumn](./kibana-plugin-plugins-expressions-public.kibanadatatablecolumn.md) > [name](./kibana-plugin-plugins-expressions-public.kibanadatatablecolumn.name.md) + +## KibanaDatatableColumn.name property + +Signature: + +```typescript +name: string; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.kibanadatatablecolumnmeta.aggconfigparams.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.kibanadatatablecolumnmeta.aggconfigparams.md new file mode 100644 index 0000000000000..2ec6edda4cbca --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.kibanadatatablecolumnmeta.aggconfigparams.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [KibanaDatatableColumnMeta](./kibana-plugin-plugins-expressions-public.kibanadatatablecolumnmeta.md) > [aggConfigParams](./kibana-plugin-plugins-expressions-public.kibanadatatablecolumnmeta.aggconfigparams.md) + +## KibanaDatatableColumnMeta.aggConfigParams property + +Signature: + +```typescript +aggConfigParams?: Record; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.kibanadatatablecolumnmeta.indexpatternid.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.kibanadatatablecolumnmeta.indexpatternid.md new file mode 100644 index 0000000000000..2287c28398f7f --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.kibanadatatablecolumnmeta.indexpatternid.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [KibanaDatatableColumnMeta](./kibana-plugin-plugins-expressions-public.kibanadatatablecolumnmeta.md) > [indexPatternId](./kibana-plugin-plugins-expressions-public.kibanadatatablecolumnmeta.indexpatternid.md) + +## KibanaDatatableColumnMeta.indexPatternId property + +Signature: + +```typescript +indexPatternId?: string; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.kibanadatatablecolumnmeta.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.kibanadatatablecolumnmeta.md new file mode 100644 index 0000000000000..b2f8c9d06a727 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.kibanadatatablecolumnmeta.md @@ -0,0 +1,20 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [KibanaDatatableColumnMeta](./kibana-plugin-plugins-expressions-public.kibanadatatablecolumnmeta.md) + +## KibanaDatatableColumnMeta interface + +Signature: + +```typescript +export interface KibanaDatatableColumnMeta +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [aggConfigParams](./kibana-plugin-plugins-expressions-public.kibanadatatablecolumnmeta.aggconfigparams.md) | Record<string, any> | | +| [indexPatternId](./kibana-plugin-plugins-expressions-public.kibanadatatablecolumnmeta.indexpatternid.md) | string | | +| [type](./kibana-plugin-plugins-expressions-public.kibanadatatablecolumnmeta.type.md) | string | | + diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.kibanadatatablecolumnmeta.type.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.kibanadatatablecolumnmeta.type.md new file mode 100644 index 0000000000000..98d4a0c2d43c3 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.kibanadatatablecolumnmeta.type.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [KibanaDatatableColumnMeta](./kibana-plugin-plugins-expressions-public.kibanadatatablecolumnmeta.md) > [type](./kibana-plugin-plugins-expressions-public.kibanadatatablecolumnmeta.type.md) + +## KibanaDatatableColumnMeta.type property + +Signature: + +```typescript +type: string; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.kibanadatatablerow.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.kibanadatatablerow.md new file mode 100644 index 0000000000000..cb5f1ad70f628 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.kibanadatatablerow.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [KibanaDatatableRow](./kibana-plugin-plugins-expressions-public.kibanadatatablerow.md) + +## KibanaDatatableRow interface + +Signature: + +```typescript +export interface KibanaDatatableRow +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.knowntypetostring.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.knowntypetostring.md new file mode 100644 index 0000000000000..39c24760ca6ca --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.knowntypetostring.md @@ -0,0 +1,17 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [KnownTypeToString](./kibana-plugin-plugins-expressions-public.knowntypetostring.md) + +## KnownTypeToString type + +Map the type of the generic to a string-based representation of the type. + +If the provided generic is its own type interface, we use the value of the `type` key as a string literal type for it. + +Signature: + +```typescript +export declare type KnownTypeToString = T extends string ? 'string' : T extends boolean ? 'boolean' : T extends number ? 'number' : T extends null ? 'null' : T extends { + type: string; +} ? T['type'] : never; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.md new file mode 100644 index 0000000000000..ead6f14e0d1d7 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.md @@ -0,0 +1,134 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) + +## kibana-plugin-plugins-expressions-public package + +## Classes + +| Class | Description | +| --- | --- | +| [Execution](./kibana-plugin-plugins-expressions-public.execution.md) | | +| [ExecutionContract](./kibana-plugin-plugins-expressions-public.executioncontract.md) | ExecutionContract is a wrapper around Execution class. It provides the same functionality but does not expose Expressions plugin internals. | +| [Executor](./kibana-plugin-plugins-expressions-public.executor.md) | | +| [ExpressionFunction](./kibana-plugin-plugins-expressions-public.expressionfunction.md) | | +| [ExpressionFunctionParameter](./kibana-plugin-plugins-expressions-public.expressionfunctionparameter.md) | | +| [ExpressionRenderer](./kibana-plugin-plugins-expressions-public.expressionrenderer.md) | | +| [ExpressionRendererRegistry](./kibana-plugin-plugins-expressions-public.expressionrendererregistry.md) | | +| [ExpressionRenderHandler](./kibana-plugin-plugins-expressions-public.expressionrenderhandler.md) | | +| [ExpressionsPublicPlugin](./kibana-plugin-plugins-expressions-public.expressionspublicplugin.md) | | +| [ExpressionsService](./kibana-plugin-plugins-expressions-public.expressionsservice.md) | ExpressionsService class is used for multiple purposes:1. It implements the same Expressions service that can be used on both: (1) server-side and (2) browser-side. 2. It implements the same Expressions service that users can fork/clone, thus have their own instance of the Expressions plugin. 3. ExpressionsService defines the public contracts of \*setup\* and \*start\* Kibana Platform life-cycles for ease-of-use on server-side and browser-side. 4. ExpressionsService creates a bound version of all exported contract functions. 5. Functions are bound the way there are:\`\`\`ts registerFunction = (...args: Parameters<Executor\['registerFunction'\]> ): ReturnType<Executor\['registerFunction'\]> => this.executor.registerFunction(...args); \`\`\`so that JSDoc appears in developers IDE when they use those plugins.expressions.registerFunction(. | +| [ExpressionType](./kibana-plugin-plugins-expressions-public.expressiontype.md) | | +| [FunctionsRegistry](./kibana-plugin-plugins-expressions-public.functionsregistry.md) | | +| [TypesRegistry](./kibana-plugin-plugins-expressions-public.typesregistry.md) | | + +## Enumerations + +| Enumeration | Description | +| --- | --- | +| [FontStyle](./kibana-plugin-plugins-expressions-public.fontstyle.md) | Enum of supported CSS font-style properties. | +| [FontWeight](./kibana-plugin-plugins-expressions-public.fontweight.md) | Enum of supported CSS font-weight properties. | +| [Overflow](./kibana-plugin-plugins-expressions-public.overflow.md) | Enum of supported CSS overflow properties. | +| [TextAlignment](./kibana-plugin-plugins-expressions-public.textalignment.md) | Enum of supported CSS text-align properties. | +| [TextDecoration](./kibana-plugin-plugins-expressions-public.textdecoration.md) | Enum of supported CSS text-decoration properties. | + +## Functions + +| Function | Description | +| --- | --- | +| [buildExpression(initialState)](./kibana-plugin-plugins-expressions-public.buildexpression.md) | Makes it easy to progressively build, update, and traverse an expression AST. You can either start with an empty AST, or provide an expression string, AST, or array of expression function builders to use as initial state. | +| [buildExpressionFunction(fnName, initialArgs)](./kibana-plugin-plugins-expressions-public.buildexpressionfunction.md) | Manages an AST for a single expression function. The return value can be provided to buildExpression to add this function to an expression.Note that to preserve type safety and ensure no args are missing, all required arguments for the specified function must be provided up front. If desired, they can be changed or removed later. | +| [format(ast, type)](./kibana-plugin-plugins-expressions-public.format.md) | | +| [formatExpression(ast)](./kibana-plugin-plugins-expressions-public.formatexpression.md) | Given expression pipeline AST, returns formatted string. | +| [isExpressionAstBuilder(val)](./kibana-plugin-plugins-expressions-public.isexpressionastbuilder.md) | Type guard that checks whether a given value is an ExpressionAstExpressionBuilder. This is useful when working with subexpressions, where you might be retrieving a function argument, and need to know whether it is an expression builder instance which you can perform operations on. | +| [parse(expression, startRule)](./kibana-plugin-plugins-expressions-public.parse.md) | | +| [parseExpression(expression)](./kibana-plugin-plugins-expressions-public.parseexpression.md) | Given expression pipeline string, returns parsed AST. | +| [plugin(initializerContext)](./kibana-plugin-plugins-expressions-public.plugin.md) | | + +## Interfaces + +| Interface | Description | +| --- | --- | +| [Datatable](./kibana-plugin-plugins-expressions-public.datatable.md) | A Datatable in Canvas is a unique structure that represents tabulated data. | +| [DatatableColumn](./kibana-plugin-plugins-expressions-public.datatablecolumn.md) | This type represents the shape of a column in a Datatable. | +| [ExecutionContext](./kibana-plugin-plugins-expressions-public.executioncontext.md) | ExecutionContext is an object available to all functions during a single execution; it provides various methods to perform side-effects. | +| [ExecutionParams](./kibana-plugin-plugins-expressions-public.executionparams.md) | | +| [ExecutionState](./kibana-plugin-plugins-expressions-public.executionstate.md) | | +| [ExecutorState](./kibana-plugin-plugins-expressions-public.executorstate.md) | | +| [ExpressionAstExpression](./kibana-plugin-plugins-expressions-public.expressionastexpression.md) | | +| [ExpressionAstExpressionBuilder](./kibana-plugin-plugins-expressions-public.expressionastexpressionbuilder.md) | | +| [ExpressionAstFunction](./kibana-plugin-plugins-expressions-public.expressionastfunction.md) | | +| [ExpressionAstFunctionBuilder](./kibana-plugin-plugins-expressions-public.expressionastfunctionbuilder.md) | | +| [ExpressionExecutor](./kibana-plugin-plugins-expressions-public.expressionexecutor.md) | | +| [ExpressionFunctionDefinition](./kibana-plugin-plugins-expressions-public.expressionfunctiondefinition.md) | ExpressionFunctionDefinition is the interface plugins have to implement to register a function in expressions plugin. | +| [ExpressionFunctionDefinitions](./kibana-plugin-plugins-expressions-public.expressionfunctiondefinitions.md) | A mapping of ExpressionFunctionDefinitions for functions which the Expressions services provides out-of-the-box. Any new functions registered by the Expressions plugin should have their types added here. | +| [ExpressionImage](./kibana-plugin-plugins-expressions-public.expressionimage.md) | | +| [ExpressionRenderDefinition](./kibana-plugin-plugins-expressions-public.expressionrenderdefinition.md) | | +| [ExpressionRendererEvent](./kibana-plugin-plugins-expressions-public.expressionrendererevent.md) | | +| [ExpressionRenderError](./kibana-plugin-plugins-expressions-public.expressionrendererror.md) | | +| [ExpressionsServiceStart](./kibana-plugin-plugins-expressions-public.expressionsservicestart.md) | The public contract that ExpressionsService provides to other plugins in Kibana Platform in \*start\* life-cycle. | +| [ExpressionsStart](./kibana-plugin-plugins-expressions-public.expressionsstart.md) | Expressions public start contrect, extends | +| [ExpressionTypeDefinition](./kibana-plugin-plugins-expressions-public.expressiontypedefinition.md) | A generic type which represents a custom Expression Type Definition that's registered to the Interpreter. | +| [ExpressionTypeStyle](./kibana-plugin-plugins-expressions-public.expressiontypestyle.md) | An object that represents style information, typically CSS. | +| [Font](./kibana-plugin-plugins-expressions-public.font.md) | An interface representing a font in Canvas, with a textual label and the CSS font-value. | +| [IExpressionLoaderParams](./kibana-plugin-plugins-expressions-public.iexpressionloaderparams.md) | | +| [IInterpreterRenderHandlers](./kibana-plugin-plugins-expressions-public.iinterpreterrenderhandlers.md) | | +| [IRegistry](./kibana-plugin-plugins-expressions-public.iregistry.md) | | +| [KibanaDatatable](./kibana-plugin-plugins-expressions-public.kibanadatatable.md) | | +| [KibanaDatatableColumn](./kibana-plugin-plugins-expressions-public.kibanadatatablecolumn.md) | | +| [KibanaDatatableColumnMeta](./kibana-plugin-plugins-expressions-public.kibanadatatablecolumnmeta.md) | | +| [KibanaDatatableRow](./kibana-plugin-plugins-expressions-public.kibanadatatablerow.md) | | +| [PointSeriesColumn](./kibana-plugin-plugins-expressions-public.pointseriescolumn.md) | Column in a PointSeries | +| [Range](./kibana-plugin-plugins-expressions-public.range.md) | | +| [ReactExpressionRendererProps](./kibana-plugin-plugins-expressions-public.reactexpressionrendererprops.md) | | +| [SerializedDatatable](./kibana-plugin-plugins-expressions-public.serializeddatatable.md) | | +| [SerializedFieldFormat](./kibana-plugin-plugins-expressions-public.serializedfieldformat.md) | JSON representation of a field formatter configuration. Is used to carry information about how to format data in a data table as part of the column definition. | + +## Variables + +| Variable | Description | +| --- | --- | +| [ReactExpressionRenderer](./kibana-plugin-plugins-expressions-public.reactexpressionrenderer.md) | | + +## Type Aliases + +| Type Alias | Description | +| --- | --- | +| [AnyExpressionFunctionDefinition](./kibana-plugin-plugins-expressions-public.anyexpressionfunctiondefinition.md) | Type to capture every possible expression function definition. | +| [AnyExpressionTypeDefinition](./kibana-plugin-plugins-expressions-public.anyexpressiontypedefinition.md) | | +| [ArgumentType](./kibana-plugin-plugins-expressions-public.argumenttype.md) | This type represents all of the possible combinations of properties of an Argument in an Expression Function. The presence or absence of certain fields influence the shape and presence of others within each arg in the specification. | +| [DatatableColumnType](./kibana-plugin-plugins-expressions-public.datatablecolumntype.md) | This type represents the type of any DatatableColumn in a Datatable. | +| [DatatableRow](./kibana-plugin-plugins-expressions-public.datatablerow.md) | This type represents a row in a Datatable. | +| [ExecutionContainer](./kibana-plugin-plugins-expressions-public.executioncontainer.md) | | +| [ExecutorContainer](./kibana-plugin-plugins-expressions-public.executorcontainer.md) | | +| [ExpressionAstArgument](./kibana-plugin-plugins-expressions-public.expressionastargument.md) | | +| [ExpressionAstNode](./kibana-plugin-plugins-expressions-public.expressionastnode.md) | | +| [ExpressionFunctionKibana](./kibana-plugin-plugins-expressions-public.expressionfunctionkibana.md) | | +| [ExpressionRendererComponent](./kibana-plugin-plugins-expressions-public.expressionrenderercomponent.md) | | +| [ExpressionsServiceSetup](./kibana-plugin-plugins-expressions-public.expressionsservicesetup.md) | The public contract that ExpressionsService provides to other plugins in Kibana Platform in \*setup\* life-cycle. | +| [ExpressionsSetup](./kibana-plugin-plugins-expressions-public.expressionssetup.md) | Expressions public setup contract, extends [ExpressionsServiceSetup](./kibana-plugin-plugins-expressions-public.expressionsservicesetup.md) | +| [ExpressionValue](./kibana-plugin-plugins-expressions-public.expressionvalue.md) | | +| [ExpressionValueBoxed](./kibana-plugin-plugins-expressions-public.expressionvalueboxed.md) | | +| [ExpressionValueConverter](./kibana-plugin-plugins-expressions-public.expressionvalueconverter.md) | | +| [ExpressionValueError](./kibana-plugin-plugins-expressions-public.expressionvalueerror.md) | | +| [ExpressionValueFilter](./kibana-plugin-plugins-expressions-public.expressionvaluefilter.md) | Represents an object that is a Filter. | +| [ExpressionValueNum](./kibana-plugin-plugins-expressions-public.expressionvaluenum.md) | | +| [ExpressionValueRender](./kibana-plugin-plugins-expressions-public.expressionvaluerender.md) | Represents an object that is intended to be rendered. | +| [ExpressionValueSearchContext](./kibana-plugin-plugins-expressions-public.expressionvaluesearchcontext.md) | | +| [ExpressionValueUnboxed](./kibana-plugin-plugins-expressions-public.expressionvalueunboxed.md) | | +| [FontLabel](./kibana-plugin-plugins-expressions-public.fontlabel.md) | This type contains a unions of all supported font labels, or the the name of the font the user would see in a UI. | +| [FontValue](./kibana-plugin-plugins-expressions-public.fontvalue.md) | This type contains a union of all supported font values, equivalent to the CSS font-value property. | +| [InterpreterErrorType](./kibana-plugin-plugins-expressions-public.interpretererrortype.md) | | +| [KIBANA\_CONTEXT\_NAME](./kibana-plugin-plugins-expressions-public.kibana_context_name.md) | | +| [KibanaContext](./kibana-plugin-plugins-expressions-public.kibanacontext.md) | | +| [KnownTypeToString](./kibana-plugin-plugins-expressions-public.knowntypetostring.md) | Map the type of the generic to a string-based representation of the type.If the provided generic is its own type interface, we use the value of the type key as a string literal type for it. | +| [PointSeries](./kibana-plugin-plugins-expressions-public.pointseries.md) | A PointSeries is a unique structure that represents dots on a chart. | +| [PointSeriesColumnName](./kibana-plugin-plugins-expressions-public.pointseriescolumnname.md) | Allowed column names in a PointSeries | +| [PointSeriesColumns](./kibana-plugin-plugins-expressions-public.pointseriescolumns.md) | Represents a collection of valid Columns in a PointSeries | +| [PointSeriesRow](./kibana-plugin-plugins-expressions-public.pointseriesrow.md) | | +| [ReactExpressionRendererType](./kibana-plugin-plugins-expressions-public.reactexpressionrenderertype.md) | | +| [Style](./kibana-plugin-plugins-expressions-public.style.md) | | +| [TypeString](./kibana-plugin-plugins-expressions-public.typestring.md) | If the type extends a Promise, we still need to return the string representation:someArgument: Promise<boolean | string> results in types: ['boolean', 'string'] | +| [TypeToString](./kibana-plugin-plugins-expressions-public.typetostring.md) | This can convert a type into a known Expression string representation of that type. For example, TypeToString<Datatable> will resolve to 'datatable'. This allows Expression Functions to continue to specify their type in a simple string format. | +| [UnmappedTypeStrings](./kibana-plugin-plugins-expressions-public.unmappedtypestrings.md) | Types used in Expressions that don't map to a primitive cleanly:date is typed as a number or string, and represents a date | + diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.overflow.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.overflow.md new file mode 100644 index 0000000000000..e33f1554a23d3 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.overflow.md @@ -0,0 +1,23 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [Overflow](./kibana-plugin-plugins-expressions-public.overflow.md) + +## Overflow enum + +Enum of supported CSS `overflow` properties. + +Signature: + +```typescript +export declare enum Overflow +``` + +## Enumeration Members + +| Member | Value | Description | +| --- | --- | --- | +| AUTO | "auto" | | +| HIDDEN | "hidden" | | +| SCROLL | "scroll" | | +| VISIBLE | "visible" | | + diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.parse.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.parse.md new file mode 100644 index 0000000000000..0cbc2c15b6f54 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.parse.md @@ -0,0 +1,23 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [parse](./kibana-plugin-plugins-expressions-public.parse.md) + +## parse() function + +Signature: + +```typescript +export declare function parse(expression: E, startRule: S): S extends 'expression' ? ExpressionAstExpression : ExpressionAstArgument; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expression | E | | +| startRule | S | | + +Returns: + +`S extends 'expression' ? ExpressionAstExpression : ExpressionAstArgument` + diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.parseexpression.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.parseexpression.md new file mode 100644 index 0000000000000..c4474b150dcc2 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.parseexpression.md @@ -0,0 +1,24 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [parseExpression](./kibana-plugin-plugins-expressions-public.parseexpression.md) + +## parseExpression() function + +Given expression pipeline string, returns parsed AST. + +Signature: + +```typescript +export declare function parseExpression(expression: string): ExpressionAstExpression; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expression | string | | + +Returns: + +`ExpressionAstExpression` + diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.plugin.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.plugin.md new file mode 100644 index 0000000000000..ef707992a0a54 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.plugin.md @@ -0,0 +1,22 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [plugin](./kibana-plugin-plugins-expressions-public.plugin.md) + +## plugin() function + +Signature: + +```typescript +export declare function plugin(initializerContext: PluginInitializerContext): ExpressionsPublicPlugin; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| initializerContext | PluginInitializerContext | | + +Returns: + +`ExpressionsPublicPlugin` + diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.pointseries.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.pointseries.md new file mode 100644 index 0000000000000..14ba955ac2cc2 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.pointseries.md @@ -0,0 +1,16 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [PointSeries](./kibana-plugin-plugins-expressions-public.pointseries.md) + +## PointSeries type + +A `PointSeries` is a unique structure that represents dots on a chart. + +Signature: + +```typescript +export declare type PointSeries = ExpressionValueBoxed<'pointseries', { + columns: PointSeriesColumns; + rows: PointSeriesRow[]; +}>; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.pointseriescolumn.expression.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.pointseriescolumn.expression.md new file mode 100644 index 0000000000000..5c034265f4f94 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.pointseriescolumn.expression.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [PointSeriesColumn](./kibana-plugin-plugins-expressions-public.pointseriescolumn.md) > [expression](./kibana-plugin-plugins-expressions-public.pointseriescolumn.expression.md) + +## PointSeriesColumn.expression property + +Signature: + +```typescript +expression: string; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.pointseriescolumn.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.pointseriescolumn.md new file mode 100644 index 0000000000000..09ce5444caabf --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.pointseriescolumn.md @@ -0,0 +1,22 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [PointSeriesColumn](./kibana-plugin-plugins-expressions-public.pointseriescolumn.md) + +## PointSeriesColumn interface + +Column in a PointSeries + +Signature: + +```typescript +export interface PointSeriesColumn +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [expression](./kibana-plugin-plugins-expressions-public.pointseriescolumn.expression.md) | string | | +| [role](./kibana-plugin-plugins-expressions-public.pointseriescolumn.role.md) | 'measure' | 'dimension' | | +| [type](./kibana-plugin-plugins-expressions-public.pointseriescolumn.type.md) | 'number' | 'string' | | + diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.pointseriescolumn.role.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.pointseriescolumn.role.md new file mode 100644 index 0000000000000..715f66a43cd62 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.pointseriescolumn.role.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [PointSeriesColumn](./kibana-plugin-plugins-expressions-public.pointseriescolumn.md) > [role](./kibana-plugin-plugins-expressions-public.pointseriescolumn.role.md) + +## PointSeriesColumn.role property + +Signature: + +```typescript +role: 'measure' | 'dimension'; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.pointseriescolumn.type.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.pointseriescolumn.type.md new file mode 100644 index 0000000000000..36a8128967cdd --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.pointseriescolumn.type.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [PointSeriesColumn](./kibana-plugin-plugins-expressions-public.pointseriescolumn.md) > [type](./kibana-plugin-plugins-expressions-public.pointseriescolumn.type.md) + +## PointSeriesColumn.type property + +Signature: + +```typescript +type: 'number' | 'string'; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.pointseriescolumnname.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.pointseriescolumnname.md new file mode 100644 index 0000000000000..bc39c694307c0 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.pointseriescolumnname.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [PointSeriesColumnName](./kibana-plugin-plugins-expressions-public.pointseriescolumnname.md) + +## PointSeriesColumnName type + +Allowed column names in a PointSeries + +Signature: + +```typescript +export declare type PointSeriesColumnName = 'x' | 'y' | 'color' | 'size' | 'text'; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.pointseriescolumns.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.pointseriescolumns.md new file mode 100644 index 0000000000000..c920a254645bd --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.pointseriescolumns.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [PointSeriesColumns](./kibana-plugin-plugins-expressions-public.pointseriescolumns.md) + +## PointSeriesColumns type + +Represents a collection of valid Columns in a PointSeries + +Signature: + +```typescript +export declare type PointSeriesColumns = Record | {}; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.pointseriesrow.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.pointseriesrow.md new file mode 100644 index 0000000000000..6e3b29572b6f4 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.pointseriesrow.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [PointSeriesRow](./kibana-plugin-plugins-expressions-public.pointseriesrow.md) + +## PointSeriesRow type + +Signature: + +```typescript +export declare type PointSeriesRow = Record; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.range.from.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.range.from.md new file mode 100644 index 0000000000000..5113a798864e9 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.range.from.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [Range](./kibana-plugin-plugins-expressions-public.range.md) > [from](./kibana-plugin-plugins-expressions-public.range.from.md) + +## Range.from property + +Signature: + +```typescript +from: number; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.range.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.range.md new file mode 100644 index 0000000000000..cf0cf4cb50b71 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.range.md @@ -0,0 +1,20 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [Range](./kibana-plugin-plugins-expressions-public.range.md) + +## Range interface + +Signature: + +```typescript +export interface Range +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [from](./kibana-plugin-plugins-expressions-public.range.from.md) | number | | +| [to](./kibana-plugin-plugins-expressions-public.range.to.md) | number | | +| [type](./kibana-plugin-plugins-expressions-public.range.type.md) | typeof name | | + diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.range.to.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.range.to.md new file mode 100644 index 0000000000000..bd79997e65fc7 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.range.to.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [Range](./kibana-plugin-plugins-expressions-public.range.md) > [to](./kibana-plugin-plugins-expressions-public.range.to.md) + +## Range.to property + +Signature: + +```typescript +to: number; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.range.type.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.range.type.md new file mode 100644 index 0000000000000..4d5476516655d --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.range.type.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [Range](./kibana-plugin-plugins-expressions-public.range.md) > [type](./kibana-plugin-plugins-expressions-public.range.type.md) + +## Range.type property + +Signature: + +```typescript +type: typeof name; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.reactexpressionrenderer.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.reactexpressionrenderer.md new file mode 100644 index 0000000000000..66c2e1e3c0c8d --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.reactexpressionrenderer.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ReactExpressionRenderer](./kibana-plugin-plugins-expressions-public.reactexpressionrenderer.md) + +## ReactExpressionRenderer variable + +Signature: + +```typescript +ReactExpressionRenderer: ({ className, dataAttrs, padding, renderError, expression, onEvent, reload$, ...expressionLoaderOptions }: ReactExpressionRendererProps) => JSX.Element +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.reactexpressionrendererprops.classname.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.reactexpressionrendererprops.classname.md new file mode 100644 index 0000000000000..b5b1391ae72fd --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.reactexpressionrendererprops.classname.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ReactExpressionRendererProps](./kibana-plugin-plugins-expressions-public.reactexpressionrendererprops.md) > [className](./kibana-plugin-plugins-expressions-public.reactexpressionrendererprops.classname.md) + +## ReactExpressionRendererProps.className property + +Signature: + +```typescript +className?: string; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.reactexpressionrendererprops.dataattrs.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.reactexpressionrendererprops.dataattrs.md new file mode 100644 index 0000000000000..a0914ce37299f --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.reactexpressionrendererprops.dataattrs.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ReactExpressionRendererProps](./kibana-plugin-plugins-expressions-public.reactexpressionrendererprops.md) > [dataAttrs](./kibana-plugin-plugins-expressions-public.reactexpressionrendererprops.dataattrs.md) + +## ReactExpressionRendererProps.dataAttrs property + +Signature: + +```typescript +dataAttrs?: string[]; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.reactexpressionrendererprops.expression.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.reactexpressionrendererprops.expression.md new file mode 100644 index 0000000000000..21f4294db5aeb --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.reactexpressionrendererprops.expression.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ReactExpressionRendererProps](./kibana-plugin-plugins-expressions-public.reactexpressionrendererprops.md) > [expression](./kibana-plugin-plugins-expressions-public.reactexpressionrendererprops.expression.md) + +## ReactExpressionRendererProps.expression property + +Signature: + +```typescript +expression: string | ExpressionAstExpression; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.reactexpressionrendererprops.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.reactexpressionrendererprops.md new file mode 100644 index 0000000000000..bd6c8cba5f784 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.reactexpressionrendererprops.md @@ -0,0 +1,24 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ReactExpressionRendererProps](./kibana-plugin-plugins-expressions-public.reactexpressionrendererprops.md) + +## ReactExpressionRendererProps interface + +Signature: + +```typescript +export interface ReactExpressionRendererProps extends IExpressionLoaderParams +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [className](./kibana-plugin-plugins-expressions-public.reactexpressionrendererprops.classname.md) | string | | +| [dataAttrs](./kibana-plugin-plugins-expressions-public.reactexpressionrendererprops.dataattrs.md) | string[] | | +| [expression](./kibana-plugin-plugins-expressions-public.reactexpressionrendererprops.expression.md) | string | ExpressionAstExpression | | +| [onEvent](./kibana-plugin-plugins-expressions-public.reactexpressionrendererprops.onevent.md) | (event: ExpressionRendererEvent) => void | | +| [padding](./kibana-plugin-plugins-expressions-public.reactexpressionrendererprops.padding.md) | 'xs' | 's' | 'm' | 'l' | 'xl' | | +| [reload$](./kibana-plugin-plugins-expressions-public.reactexpressionrendererprops.reload_.md) | Observable<unknown> | An observable which can be used to re-run the expression without destroying the component | +| [renderError](./kibana-plugin-plugins-expressions-public.reactexpressionrendererprops.rendererror.md) | (error?: string | null) => React.ReactElement | React.ReactElement[] | | + diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.reactexpressionrendererprops.onevent.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.reactexpressionrendererprops.onevent.md new file mode 100644 index 0000000000000..4fe1e158df1b8 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.reactexpressionrendererprops.onevent.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ReactExpressionRendererProps](./kibana-plugin-plugins-expressions-public.reactexpressionrendererprops.md) > [onEvent](./kibana-plugin-plugins-expressions-public.reactexpressionrendererprops.onevent.md) + +## ReactExpressionRendererProps.onEvent property + +Signature: + +```typescript +onEvent?: (event: ExpressionRendererEvent) => void; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.reactexpressionrendererprops.padding.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.reactexpressionrendererprops.padding.md new file mode 100644 index 0000000000000..47a23f5c1088b --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.reactexpressionrendererprops.padding.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ReactExpressionRendererProps](./kibana-plugin-plugins-expressions-public.reactexpressionrendererprops.md) > [padding](./kibana-plugin-plugins-expressions-public.reactexpressionrendererprops.padding.md) + +## ReactExpressionRendererProps.padding property + +Signature: + +```typescript +padding?: 'xs' | 's' | 'm' | 'l' | 'xl'; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.reactexpressionrendererprops.reload_.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.reactexpressionrendererprops.reload_.md new file mode 100644 index 0000000000000..a7991d559377d --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.reactexpressionrendererprops.reload_.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ReactExpressionRendererProps](./kibana-plugin-plugins-expressions-public.reactexpressionrendererprops.md) > [reload$](./kibana-plugin-plugins-expressions-public.reactexpressionrendererprops.reload_.md) + +## ReactExpressionRendererProps.reload$ property + +An observable which can be used to re-run the expression without destroying the component + +Signature: + +```typescript +reload$?: Observable; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.reactexpressionrendererprops.rendererror.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.reactexpressionrendererprops.rendererror.md new file mode 100644 index 0000000000000..48bfe1ee5c7c7 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.reactexpressionrendererprops.rendererror.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ReactExpressionRendererProps](./kibana-plugin-plugins-expressions-public.reactexpressionrendererprops.md) > [renderError](./kibana-plugin-plugins-expressions-public.reactexpressionrendererprops.rendererror.md) + +## ReactExpressionRendererProps.renderError property + +Signature: + +```typescript +renderError?: (error?: string | null) => React.ReactElement | React.ReactElement[]; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.reactexpressionrenderertype.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.reactexpressionrenderertype.md new file mode 100644 index 0000000000000..4ca56d534b84a --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.reactexpressionrenderertype.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ReactExpressionRendererType](./kibana-plugin-plugins-expressions-public.reactexpressionrenderertype.md) + +## ReactExpressionRendererType type + +Signature: + +```typescript +export declare type ReactExpressionRendererType = React.ComponentType; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.serializeddatatable.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.serializeddatatable.md new file mode 100644 index 0000000000000..632cd1de2a0c2 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.serializeddatatable.md @@ -0,0 +1,18 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [SerializedDatatable](./kibana-plugin-plugins-expressions-public.serializeddatatable.md) + +## SerializedDatatable interface + +Signature: + +```typescript +export interface SerializedDatatable extends Datatable +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [rows](./kibana-plugin-plugins-expressions-public.serializeddatatable.rows.md) | string[][] | | + diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.serializeddatatable.rows.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.serializeddatatable.rows.md new file mode 100644 index 0000000000000..00d4323ae7025 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.serializeddatatable.rows.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [SerializedDatatable](./kibana-plugin-plugins-expressions-public.serializeddatatable.md) > [rows](./kibana-plugin-plugins-expressions-public.serializeddatatable.rows.md) + +## SerializedDatatable.rows property + +Signature: + +```typescript +rows: string[][]; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.serializedfieldformat.id.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.serializedfieldformat.id.md new file mode 100644 index 0000000000000..40a45d50e9b19 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.serializedfieldformat.id.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [SerializedFieldFormat](./kibana-plugin-plugins-expressions-public.serializedfieldformat.md) > [id](./kibana-plugin-plugins-expressions-public.serializedfieldformat.id.md) + +## SerializedFieldFormat.id property + +Signature: + +```typescript +id?: string; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.serializedfieldformat.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.serializedfieldformat.md new file mode 100644 index 0000000000000..74fa132ec1189 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.serializedfieldformat.md @@ -0,0 +1,21 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [SerializedFieldFormat](./kibana-plugin-plugins-expressions-public.serializedfieldformat.md) + +## SerializedFieldFormat interface + +JSON representation of a field formatter configuration. Is used to carry information about how to format data in a data table as part of the column definition. + +Signature: + +```typescript +export interface SerializedFieldFormat> +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [id](./kibana-plugin-plugins-expressions-public.serializedfieldformat.id.md) | string | | +| [params](./kibana-plugin-plugins-expressions-public.serializedfieldformat.params.md) | TParams | | + diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.serializedfieldformat.params.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.serializedfieldformat.params.md new file mode 100644 index 0000000000000..32d7e54cbc884 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.serializedfieldformat.params.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [SerializedFieldFormat](./kibana-plugin-plugins-expressions-public.serializedfieldformat.md) > [params](./kibana-plugin-plugins-expressions-public.serializedfieldformat.params.md) + +## SerializedFieldFormat.params property + +Signature: + +```typescript +params?: TParams; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.style.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.style.md new file mode 100644 index 0000000000000..f42df4b8b314e --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.style.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [Style](./kibana-plugin-plugins-expressions-public.style.md) + +## Style type + +Signature: + +```typescript +export declare type Style = ExpressionTypeStyle; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.textalignment.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.textalignment.md new file mode 100644 index 0000000000000..351a7ba6e1f27 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.textalignment.md @@ -0,0 +1,23 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [TextAlignment](./kibana-plugin-plugins-expressions-public.textalignment.md) + +## TextAlignment enum + +Enum of supported CSS `text-align` properties. + +Signature: + +```typescript +export declare enum TextAlignment +``` + +## Enumeration Members + +| Member | Value | Description | +| --- | --- | --- | +| CENTER | "center" | | +| JUSTIFY | "justify" | | +| LEFT | "left" | | +| RIGHT | "right" | | + diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.textdecoration.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.textdecoration.md new file mode 100644 index 0000000000000..3cd8e89f4cd8c --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.textdecoration.md @@ -0,0 +1,21 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [TextDecoration](./kibana-plugin-plugins-expressions-public.textdecoration.md) + +## TextDecoration enum + +Enum of supported CSS `text-decoration` properties. + +Signature: + +```typescript +export declare enum TextDecoration +``` + +## Enumeration Members + +| Member | Value | Description | +| --- | --- | --- | +| NONE | "none" | | +| UNDERLINE | "underline" | | + diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.typesregistry._constructor_.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.typesregistry._constructor_.md new file mode 100644 index 0000000000000..856bf2bf05ad1 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.typesregistry._constructor_.md @@ -0,0 +1,20 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [TypesRegistry](./kibana-plugin-plugins-expressions-public.typesregistry.md) > [(constructor)](./kibana-plugin-plugins-expressions-public.typesregistry._constructor_.md) + +## TypesRegistry.(constructor) + +Constructs a new instance of the `TypesRegistry` class + +Signature: + +```typescript +constructor(executor: Executor); +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| executor | Executor<any> | | + diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.typesregistry.get.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.typesregistry.get.md new file mode 100644 index 0000000000000..f83e7435485c5 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.typesregistry.get.md @@ -0,0 +1,22 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [TypesRegistry](./kibana-plugin-plugins-expressions-public.typesregistry.md) > [get](./kibana-plugin-plugins-expressions-public.typesregistry.get.md) + +## TypesRegistry.get() method + +Signature: + +```typescript +get(id: string): ExpressionType | null; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| id | string | | + +Returns: + +`ExpressionType | null` + diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.typesregistry.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.typesregistry.md new file mode 100644 index 0000000000000..f1f386ec4210f --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.typesregistry.md @@ -0,0 +1,27 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [TypesRegistry](./kibana-plugin-plugins-expressions-public.typesregistry.md) + +## TypesRegistry class + +Signature: + +```typescript +export declare class TypesRegistry implements IRegistry +``` + +## Constructors + +| Constructor | Modifiers | Description | +| --- | --- | --- | +| [(constructor)(executor)](./kibana-plugin-plugins-expressions-public.typesregistry._constructor_.md) | | Constructs a new instance of the TypesRegistry class | + +## Methods + +| Method | Modifiers | Description | +| --- | --- | --- | +| [get(id)](./kibana-plugin-plugins-expressions-public.typesregistry.get.md) | | | +| [register(typeDefinition)](./kibana-plugin-plugins-expressions-public.typesregistry.register.md) | | | +| [toArray()](./kibana-plugin-plugins-expressions-public.typesregistry.toarray.md) | | | +| [toJS()](./kibana-plugin-plugins-expressions-public.typesregistry.tojs.md) | | | + diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.typesregistry.register.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.typesregistry.register.md new file mode 100644 index 0000000000000..b328f26aa50e2 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.typesregistry.register.md @@ -0,0 +1,22 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [TypesRegistry](./kibana-plugin-plugins-expressions-public.typesregistry.md) > [register](./kibana-plugin-plugins-expressions-public.typesregistry.register.md) + +## TypesRegistry.register() method + +Signature: + +```typescript +register(typeDefinition: AnyExpressionTypeDefinition | (() => AnyExpressionTypeDefinition)): void; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| typeDefinition | AnyExpressionTypeDefinition | (() => AnyExpressionTypeDefinition) | | + +Returns: + +`void` + diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.typesregistry.toarray.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.typesregistry.toarray.md new file mode 100644 index 0000000000000..2e9c8799cbd61 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.typesregistry.toarray.md @@ -0,0 +1,15 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [TypesRegistry](./kibana-plugin-plugins-expressions-public.typesregistry.md) > [toArray](./kibana-plugin-plugins-expressions-public.typesregistry.toarray.md) + +## TypesRegistry.toArray() method + +Signature: + +```typescript +toArray(): ExpressionType[]; +``` +Returns: + +`ExpressionType[]` + diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.typesregistry.tojs.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.typesregistry.tojs.md new file mode 100644 index 0000000000000..14a22a890f0d1 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.typesregistry.tojs.md @@ -0,0 +1,15 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [TypesRegistry](./kibana-plugin-plugins-expressions-public.typesregistry.md) > [toJS](./kibana-plugin-plugins-expressions-public.typesregistry.tojs.md) + +## TypesRegistry.toJS() method + +Signature: + +```typescript +toJS(): Record; +``` +Returns: + +`Record` + diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.typestring.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.typestring.md new file mode 100644 index 0000000000000..1e85625907bb0 --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.typestring.md @@ -0,0 +1,15 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [TypeString](./kibana-plugin-plugins-expressions-public.typestring.md) + +## TypeString type + +If the type extends a Promise, we still need to return the string representation: + +`someArgument: Promise` results in `types: ['boolean', 'string']` + +Signature: + +```typescript +export declare type TypeString = KnownTypeToString>; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.typetostring.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.typetostring.md new file mode 100644 index 0000000000000..78f350a0c06ec --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.typetostring.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [TypeToString](./kibana-plugin-plugins-expressions-public.typetostring.md) + +## TypeToString type + +This can convert a type into a known Expression string representation of that type. For example, `TypeToString` will resolve to `'datatable'`. This allows Expression Functions to continue to specify their type in a simple string format. + +Signature: + +```typescript +export declare type TypeToString = KnownTypeToString | UnmappedTypeStrings; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.unmappedtypestrings.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.unmappedtypestrings.md new file mode 100644 index 0000000000000..6455d6520bcec --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.unmappedtypestrings.md @@ -0,0 +1,15 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [UnmappedTypeStrings](./kibana-plugin-plugins-expressions-public.unmappedtypestrings.md) + +## UnmappedTypeStrings type + +Types used in Expressions that don't map to a primitive cleanly: + +`date` is typed as a number or string, and represents a date + +Signature: + +```typescript +export declare type UnmappedTypeStrings = 'date' | 'filter'; +``` diff --git a/docs/development/plugins/expressions/server/index.md b/docs/development/plugins/expressions/server/index.md new file mode 100644 index 0000000000000..8c35c1631ba04 --- /dev/null +++ b/docs/development/plugins/expressions/server/index.md @@ -0,0 +1,12 @@ + + +[Home](./index.md) + +## API Reference + +## Packages + +| Package | Description | +| --- | --- | +| [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) | | + diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.anyexpressionfunctiondefinition.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.anyexpressionfunctiondefinition.md new file mode 100644 index 0000000000000..04e652a66aa5c --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.anyexpressionfunctiondefinition.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [AnyExpressionFunctionDefinition](./kibana-plugin-plugins-expressions-server.anyexpressionfunctiondefinition.md) + +## AnyExpressionFunctionDefinition type + +Type to capture every possible expression function definition. + +Signature: + +```typescript +export declare type AnyExpressionFunctionDefinition = ExpressionFunctionDefinition, any>; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.anyexpressiontypedefinition.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.anyexpressiontypedefinition.md new file mode 100644 index 0000000000000..c28e1aa411a34 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.anyexpressiontypedefinition.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [AnyExpressionTypeDefinition](./kibana-plugin-plugins-expressions-server.anyexpressiontypedefinition.md) + +## AnyExpressionTypeDefinition type + +Signature: + +```typescript +export declare type AnyExpressionTypeDefinition = ExpressionTypeDefinition; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.argumenttype.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.argumenttype.md new file mode 100644 index 0000000000000..360b8999f2053 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.argumenttype.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ArgumentType](./kibana-plugin-plugins-expressions-server.argumenttype.md) + +## ArgumentType type + +This type represents all of the possible combinations of properties of an Argument in an Expression Function. The presence or absence of certain fields influence the shape and presence of others within each `arg` in the specification. + +Signature: + +```typescript +export declare type ArgumentType = SingleArgumentType | MultipleArgumentType | UnresolvedSingleArgumentType | UnresolvedMultipleArgumentType; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.buildexpression.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.buildexpression.md new file mode 100644 index 0000000000000..2e84c2b706bfc --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.buildexpression.md @@ -0,0 +1,24 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [buildExpression](./kibana-plugin-plugins-expressions-server.buildexpression.md) + +## buildExpression() function + +Makes it easy to progressively build, update, and traverse an expression AST. You can either start with an empty AST, or provide an expression string, AST, or array of expression function builders to use as initial state. + +Signature: + +```typescript +export declare function buildExpression(initialState?: ExpressionAstFunctionBuilder[] | ExpressionAstExpression | string): ExpressionAstExpressionBuilder; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| initialState | ExpressionAstFunctionBuilder[] | ExpressionAstExpression | string | | + +Returns: + +`ExpressionAstExpressionBuilder` + diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.buildexpressionfunction.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.buildexpressionfunction.md new file mode 100644 index 0000000000000..09afd3d59a070 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.buildexpressionfunction.md @@ -0,0 +1,30 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [buildExpressionFunction](./kibana-plugin-plugins-expressions-server.buildexpressionfunction.md) + +## buildExpressionFunction() function + +Manages an AST for a single expression function. The return value can be provided to `buildExpression` to add this function to an expression. + +Note that to preserve type safety and ensure no args are missing, all required arguments for the specified function must be provided up front. If desired, they can be changed or removed later. + +Signature: + +```typescript +export declare function buildExpressionFunction(fnName: InferFunctionDefinition['name'], +initialArgs: { + [K in keyof FunctionArgs]: FunctionArgs[K] | ExpressionAstExpressionBuilder | ExpressionAstExpressionBuilder[]; +}): ExpressionAstFunctionBuilder; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fnName | InferFunctionDefinition<FnDef>['name'] | | +| initialArgs | {
    [K in keyof FunctionArgs<FnDef>]: FunctionArgs<FnDef>[K] | ExpressionAstExpressionBuilder | ExpressionAstExpressionBuilder[];
    } | | + +Returns: + +`ExpressionAstFunctionBuilder` + diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.datatable.columns.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.datatable.columns.md new file mode 100644 index 0000000000000..1bd089af13c6c --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.datatable.columns.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [Datatable](./kibana-plugin-plugins-expressions-server.datatable.md) > [columns](./kibana-plugin-plugins-expressions-server.datatable.columns.md) + +## Datatable.columns property + +Signature: + +```typescript +columns: DatatableColumn[]; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.datatable.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.datatable.md new file mode 100644 index 0000000000000..7dc2ab2596e12 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.datatable.md @@ -0,0 +1,22 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [Datatable](./kibana-plugin-plugins-expressions-server.datatable.md) + +## Datatable interface + +A `Datatable` in Canvas is a unique structure that represents tabulated data. + +Signature: + +```typescript +export interface Datatable +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [columns](./kibana-plugin-plugins-expressions-server.datatable.columns.md) | DatatableColumn[] | | +| [rows](./kibana-plugin-plugins-expressions-server.datatable.rows.md) | DatatableRow[] | | +| [type](./kibana-plugin-plugins-expressions-server.datatable.type.md) | typeof name | | + diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.datatable.rows.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.datatable.rows.md new file mode 100644 index 0000000000000..75bd8e2f56bde --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.datatable.rows.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [Datatable](./kibana-plugin-plugins-expressions-server.datatable.md) > [rows](./kibana-plugin-plugins-expressions-server.datatable.rows.md) + +## Datatable.rows property + +Signature: + +```typescript +rows: DatatableRow[]; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.datatable.type.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.datatable.type.md new file mode 100644 index 0000000000000..bcd250c5a9f9e --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.datatable.type.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [Datatable](./kibana-plugin-plugins-expressions-server.datatable.md) > [type](./kibana-plugin-plugins-expressions-server.datatable.type.md) + +## Datatable.type property + +Signature: + +```typescript +type: typeof name; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.datatablecolumn.id.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.datatablecolumn.id.md new file mode 100644 index 0000000000000..1f246825fa30a --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.datatablecolumn.id.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [DatatableColumn](./kibana-plugin-plugins-expressions-server.datatablecolumn.md) > [id](./kibana-plugin-plugins-expressions-server.datatablecolumn.id.md) + +## DatatableColumn.id property + +Signature: + +```typescript +id: string; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.datatablecolumn.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.datatablecolumn.md new file mode 100644 index 0000000000000..662f65d6fad21 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.datatablecolumn.md @@ -0,0 +1,22 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [DatatableColumn](./kibana-plugin-plugins-expressions-server.datatablecolumn.md) + +## DatatableColumn interface + +This type represents the shape of a column in a `Datatable`. + +Signature: + +```typescript +export interface DatatableColumn +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [id](./kibana-plugin-plugins-expressions-server.datatablecolumn.id.md) | string | | +| [meta](./kibana-plugin-plugins-expressions-server.datatablecolumn.meta.md) | DatatableColumnMeta | | +| [name](./kibana-plugin-plugins-expressions-server.datatablecolumn.name.md) | string | | + diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.datatablecolumn.meta.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.datatablecolumn.meta.md new file mode 100644 index 0000000000000..ef47c67a8d606 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.datatablecolumn.meta.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [DatatableColumn](./kibana-plugin-plugins-expressions-server.datatablecolumn.md) > [meta](./kibana-plugin-plugins-expressions-server.datatablecolumn.meta.md) + +## DatatableColumn.meta property + +Signature: + +```typescript +meta: DatatableColumnMeta; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.datatablecolumn.name.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.datatablecolumn.name.md new file mode 100644 index 0000000000000..112b4ac3b9941 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.datatablecolumn.name.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [DatatableColumn](./kibana-plugin-plugins-expressions-server.datatablecolumn.md) > [name](./kibana-plugin-plugins-expressions-server.datatablecolumn.name.md) + +## DatatableColumn.name property + +Signature: + +```typescript +name: string; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.datatablecolumntype.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.datatablecolumntype.md new file mode 100644 index 0000000000000..4afce913526de --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.datatablecolumntype.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [DatatableColumnType](./kibana-plugin-plugins-expressions-server.datatablecolumntype.md) + +## DatatableColumnType type + +This type represents the `type` of any `DatatableColumn` in a `Datatable`. + +Signature: + +```typescript +export declare type DatatableColumnType = 'string' | 'number' | 'boolean' | 'date' | 'null'; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.datatablerow.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.datatablerow.md new file mode 100644 index 0000000000000..56ef342b22a28 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.datatablerow.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [DatatableRow](./kibana-plugin-plugins-expressions-server.datatablerow.md) + +## DatatableRow type + +This type represents a row in a `Datatable`. + +Signature: + +```typescript +export declare type DatatableRow = Record; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.execution._constructor_.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.execution._constructor_.md new file mode 100644 index 0000000000000..75f4cc4c2a017 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.execution._constructor_.md @@ -0,0 +1,20 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [Execution](./kibana-plugin-plugins-expressions-server.execution.md) > [(constructor)](./kibana-plugin-plugins-expressions-server.execution._constructor_.md) + +## Execution.(constructor) + +Constructs a new instance of the `Execution` class + +Signature: + +```typescript +constructor(params: ExecutionParams); +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| params | ExecutionParams<ExtraContext> | | + diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.execution.cancel.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.execution.cancel.md new file mode 100644 index 0000000000000..2ee091da80504 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.execution.cancel.md @@ -0,0 +1,17 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [Execution](./kibana-plugin-plugins-expressions-server.execution.md) > [cancel](./kibana-plugin-plugins-expressions-server.execution.cancel.md) + +## Execution.cancel() method + +Stop execution of expression. + +Signature: + +```typescript +cancel(): void; +``` +Returns: + +`void` + diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.execution.cast.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.execution.cast.md new file mode 100644 index 0000000000000..22b876332efb4 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.execution.cast.md @@ -0,0 +1,23 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [Execution](./kibana-plugin-plugins-expressions-server.execution.md) > [cast](./kibana-plugin-plugins-expressions-server.execution.cast.md) + +## Execution.cast() method + +Signature: + +```typescript +cast(value: any, toTypeNames?: string[]): any; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| value | any | | +| toTypeNames | string[] | | + +Returns: + +`any` + diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.execution.context.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.execution.context.md new file mode 100644 index 0000000000000..d1969fb0859b7 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.execution.context.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [Execution](./kibana-plugin-plugins-expressions-server.execution.md) > [context](./kibana-plugin-plugins-expressions-server.execution.context.md) + +## Execution.context property + +Execution context - object that allows to do side-effects. Context is passed to every function. + +Signature: + +```typescript +readonly context: ExecutionContext & ExtraContext; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.execution.contract.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.execution.contract.md new file mode 100644 index 0000000000000..149b5a7ced9cb --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.execution.contract.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [Execution](./kibana-plugin-plugins-expressions-server.execution.md) > [contract](./kibana-plugin-plugins-expressions-server.execution.contract.md) + +## Execution.contract property + +Contract is a public representation of `Execution` instances. Contract we can return to other plugins for their consumption. + +Signature: + +```typescript +readonly contract: ExecutionContract; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.execution.expression.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.execution.expression.md new file mode 100644 index 0000000000000..0487378ce1bba --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.execution.expression.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [Execution](./kibana-plugin-plugins-expressions-server.execution.md) > [expression](./kibana-plugin-plugins-expressions-server.execution.expression.md) + +## Execution.expression property + +Signature: + +```typescript +readonly expression: string; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.execution.input.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.execution.input.md new file mode 100644 index 0000000000000..ea411523a2b0b --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.execution.input.md @@ -0,0 +1,15 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [Execution](./kibana-plugin-plugins-expressions-server.execution.md) > [input](./kibana-plugin-plugins-expressions-server.execution.input.md) + +## Execution.input property + +Initial input of the execution. + +N.B. It is initialized to `null` rather than `undefined` for legacy reasons, because in legacy interpreter it was set to `null` by default. + +Signature: + +```typescript +input: Input; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.execution.inspectoradapters.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.execution.inspectoradapters.md new file mode 100644 index 0000000000000..99bcca267f8ed --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.execution.inspectoradapters.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [Execution](./kibana-plugin-plugins-expressions-server.execution.md) > [inspectorAdapters](./kibana-plugin-plugins-expressions-server.execution.inspectoradapters.md) + +## Execution.inspectorAdapters property + +Signature: + +```typescript +get inspectorAdapters(): InspectorAdapters; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.execution.interpret.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.execution.interpret.md new file mode 100644 index 0000000000000..cf59e796e6120 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.execution.interpret.md @@ -0,0 +1,24 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [Execution](./kibana-plugin-plugins-expressions-server.execution.md) > [interpret](./kibana-plugin-plugins-expressions-server.execution.interpret.md) + +## Execution.interpret() method + +Signature: + +```typescript +interpret(ast: ExpressionAstNode, input: T, options?: ExpressionExecOptions): Promise; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| ast | ExpressionAstNode | | +| input | T | | +| options | ExpressionExecOptions | | + +Returns: + +`Promise` + diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.execution.invokechain.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.execution.invokechain.md new file mode 100644 index 0000000000000..9ada611f32bf2 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.execution.invokechain.md @@ -0,0 +1,23 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [Execution](./kibana-plugin-plugins-expressions-server.execution.md) > [invokeChain](./kibana-plugin-plugins-expressions-server.execution.invokechain.md) + +## Execution.invokeChain() method + +Signature: + +```typescript +invokeChain(chainArr: ExpressionAstFunction[], input: unknown): Promise; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| chainArr | ExpressionAstFunction[] | | +| input | unknown | | + +Returns: + +`Promise` + diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.execution.invokefunction.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.execution.invokefunction.md new file mode 100644 index 0000000000000..4519d21ee250a --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.execution.invokefunction.md @@ -0,0 +1,24 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [Execution](./kibana-plugin-plugins-expressions-server.execution.md) > [invokeFunction](./kibana-plugin-plugins-expressions-server.execution.invokefunction.md) + +## Execution.invokeFunction() method + +Signature: + +```typescript +invokeFunction(fn: ExpressionFunction, input: unknown, args: Record): Promise; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fn | ExpressionFunction | | +| input | unknown | | +| args | Record<string, unknown> | | + +Returns: + +`Promise` + diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.execution.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.execution.md new file mode 100644 index 0000000000000..fc663dd115580 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.execution.md @@ -0,0 +1,43 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [Execution](./kibana-plugin-plugins-expressions-server.execution.md) + +## Execution class + +Signature: + +```typescript +export declare class Execution = Record, Input = unknown, Output = unknown, InspectorAdapters extends Adapters = ExtraContext['inspectorAdapters'] extends object ? ExtraContext['inspectorAdapters'] : DefaultInspectorAdapters> +``` + +## Constructors + +| Constructor | Modifiers | Description | +| --- | --- | --- | +| [(constructor)(params)](./kibana-plugin-plugins-expressions-server.execution._constructor_.md) | | Constructs a new instance of the Execution class | + +## Properties + +| Property | Modifiers | Type | Description | +| --- | --- | --- | --- | +| [context](./kibana-plugin-plugins-expressions-server.execution.context.md) | | ExecutionContext<Input, InspectorAdapters> & ExtraContext | Execution context - object that allows to do side-effects. Context is passed to every function. | +| [contract](./kibana-plugin-plugins-expressions-server.execution.contract.md) | | ExecutionContract<ExtraContext, Input, Output, InspectorAdapters> | Contract is a public representation of Execution instances. Contract we can return to other plugins for their consumption. | +| [expression](./kibana-plugin-plugins-expressions-server.execution.expression.md) | | string | | +| [input](./kibana-plugin-plugins-expressions-server.execution.input.md) | | Input | Initial input of the execution.N.B. It is initialized to null rather than undefined for legacy reasons, because in legacy interpreter it was set to null by default. | +| [inspectorAdapters](./kibana-plugin-plugins-expressions-server.execution.inspectoradapters.md) | | InspectorAdapters | | +| [params](./kibana-plugin-plugins-expressions-server.execution.params.md) | | ExecutionParams<ExtraContext> | | +| [result](./kibana-plugin-plugins-expressions-server.execution.result.md) | | Promise<Output | ExpressionValueError> | | +| [state](./kibana-plugin-plugins-expressions-server.execution.state.md) | | ExecutionContainer<Output | ExpressionValueError> | Dynamic state of the execution. | + +## Methods + +| Method | Modifiers | Description | +| --- | --- | --- | +| [cancel()](./kibana-plugin-plugins-expressions-server.execution.cancel.md) | | Stop execution of expression. | +| [cast(value, toTypeNames)](./kibana-plugin-plugins-expressions-server.execution.cast.md) | | | +| [interpret(ast, input, options)](./kibana-plugin-plugins-expressions-server.execution.interpret.md) | | | +| [invokeChain(chainArr, input)](./kibana-plugin-plugins-expressions-server.execution.invokechain.md) | | | +| [invokeFunction(fn, input, args)](./kibana-plugin-plugins-expressions-server.execution.invokefunction.md) | | | +| [resolveArgs(fnDef, input, argAsts)](./kibana-plugin-plugins-expressions-server.execution.resolveargs.md) | | | +| [start(input)](./kibana-plugin-plugins-expressions-server.execution.start.md) | | Call this method to start execution.N.B. input is initialized to null rather than undefined for legacy reasons, because in legacy interpreter it was set to null by default. | + diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.execution.params.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.execution.params.md new file mode 100644 index 0000000000000..498f9bbfccfa4 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.execution.params.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [Execution](./kibana-plugin-plugins-expressions-server.execution.md) > [params](./kibana-plugin-plugins-expressions-server.execution.params.md) + +## Execution.params property + +Signature: + +```typescript +readonly params: ExecutionParams; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.execution.resolveargs.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.execution.resolveargs.md new file mode 100644 index 0000000000000..48cc43b2d7767 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.execution.resolveargs.md @@ -0,0 +1,24 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [Execution](./kibana-plugin-plugins-expressions-server.execution.md) > [resolveArgs](./kibana-plugin-plugins-expressions-server.execution.resolveargs.md) + +## Execution.resolveArgs() method + +Signature: + +```typescript +resolveArgs(fnDef: ExpressionFunction, input: unknown, argAsts: any): Promise; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| fnDef | ExpressionFunction | | +| input | unknown | | +| argAsts | any | | + +Returns: + +`Promise` + diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.execution.result.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.execution.result.md new file mode 100644 index 0000000000000..be0134cd2542e --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.execution.result.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [Execution](./kibana-plugin-plugins-expressions-server.execution.md) > [result](./kibana-plugin-plugins-expressions-server.execution.result.md) + +## Execution.result property + +Signature: + +```typescript +get result(): Promise; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.execution.start.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.execution.start.md new file mode 100644 index 0000000000000..9a4e93fe6a9af --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.execution.start.md @@ -0,0 +1,26 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [Execution](./kibana-plugin-plugins-expressions-server.execution.md) > [start](./kibana-plugin-plugins-expressions-server.execution.start.md) + +## Execution.start() method + +Call this method to start execution. + +N.B. `input` is initialized to `null` rather than `undefined` for legacy reasons, because in legacy interpreter it was set to `null` by default. + +Signature: + +```typescript +start(input?: Input): void; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| input | Input | | + +Returns: + +`void` + diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.execution.state.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.execution.state.md new file mode 100644 index 0000000000000..41e7e693a1da4 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.execution.state.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [Execution](./kibana-plugin-plugins-expressions-server.execution.md) > [state](./kibana-plugin-plugins-expressions-server.execution.state.md) + +## Execution.state property + +Dynamic state of the execution. + +Signature: + +```typescript +readonly state: ExecutionContainer; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executioncontainer.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executioncontainer.md new file mode 100644 index 0000000000000..5dc82fcbb9dd8 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executioncontainer.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExecutionContainer](./kibana-plugin-plugins-expressions-server.executioncontainer.md) + +## ExecutionContainer type + +Signature: + +```typescript +export declare type ExecutionContainer = StateContainer, ExecutionPureTransitions>; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executioncontext.abortsignal.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executioncontext.abortsignal.md new file mode 100644 index 0000000000000..5c43623c8e603 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executioncontext.abortsignal.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExecutionContext](./kibana-plugin-plugins-expressions-server.executioncontext.md) > [abortSignal](./kibana-plugin-plugins-expressions-server.executioncontext.abortsignal.md) + +## ExecutionContext.abortSignal property + +Adds ability to abort current execution. + +Signature: + +```typescript +abortSignal: AbortSignal; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executioncontext.getinitialinput.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executioncontext.getinitialinput.md new file mode 100644 index 0000000000000..b5f9b91e1c7b7 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executioncontext.getinitialinput.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExecutionContext](./kibana-plugin-plugins-expressions-server.executioncontext.md) > [getInitialInput](./kibana-plugin-plugins-expressions-server.executioncontext.getinitialinput.md) + +## ExecutionContext.getInitialInput property + +Get initial input with which execution started. + +Signature: + +```typescript +getInitialInput: () => Input; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executioncontext.getsavedobject.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executioncontext.getsavedobject.md new file mode 100644 index 0000000000000..b8c8f4f3bb067 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executioncontext.getsavedobject.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExecutionContext](./kibana-plugin-plugins-expressions-server.executioncontext.md) > [getSavedObject](./kibana-plugin-plugins-expressions-server.executioncontext.getsavedobject.md) + +## ExecutionContext.getSavedObject property + +Allows to fetch saved objects from ElasticSearch. In browser `getSavedObject` function is provided automatically by the Expressions plugin. On the server the caller of the expression has to provide this context function. The reason is because on the browser we always know the user who tries to fetch a saved object, thus saved object client is scoped automatically to that user. However, on the server we can scope that saved object client to any user, or even not scope it at all and execute it as an "internal" user. + +Signature: + +```typescript +getSavedObject?: (type: string, id: string) => Promise>; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executioncontext.inspectoradapters.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executioncontext.inspectoradapters.md new file mode 100644 index 0000000000000..b937432e4c180 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executioncontext.inspectoradapters.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExecutionContext](./kibana-plugin-plugins-expressions-server.executioncontext.md) > [inspectorAdapters](./kibana-plugin-plugins-expressions-server.executioncontext.inspectoradapters.md) + +## ExecutionContext.inspectorAdapters property + +Adapters for `inspector` plugin. + +Signature: + +```typescript +inspectorAdapters: InspectorAdapters; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executioncontext.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executioncontext.md new file mode 100644 index 0000000000000..0128ba934da73 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executioncontext.md @@ -0,0 +1,26 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExecutionContext](./kibana-plugin-plugins-expressions-server.executioncontext.md) + +## ExecutionContext interface + +`ExecutionContext` is an object available to all functions during a single execution; it provides various methods to perform side-effects. + +Signature: + +```typescript +export interface ExecutionContext +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [abortSignal](./kibana-plugin-plugins-expressions-server.executioncontext.abortsignal.md) | AbortSignal | Adds ability to abort current execution. | +| [getInitialInput](./kibana-plugin-plugins-expressions-server.executioncontext.getinitialinput.md) | () => Input | Get initial input with which execution started. | +| [getSavedObject](./kibana-plugin-plugins-expressions-server.executioncontext.getsavedobject.md) | <T extends SavedObjectAttributes = SavedObjectAttributes>(type: string, id: string) => Promise<SavedObject<T>> | Allows to fetch saved objects from ElasticSearch. In browser getSavedObject function is provided automatically by the Expressions plugin. On the server the caller of the expression has to provide this context function. The reason is because on the browser we always know the user who tries to fetch a saved object, thus saved object client is scoped automatically to that user. However, on the server we can scope that saved object client to any user, or even not scope it at all and execute it as an "internal" user. | +| [inspectorAdapters](./kibana-plugin-plugins-expressions-server.executioncontext.inspectoradapters.md) | InspectorAdapters | Adapters for inspector plugin. | +| [search](./kibana-plugin-plugins-expressions-server.executioncontext.search.md) | ExecutionContextSearch | Search context in which expression should operate. | +| [types](./kibana-plugin-plugins-expressions-server.executioncontext.types.md) | Record<string, ExpressionType> | A map of available expression types. | +| [variables](./kibana-plugin-plugins-expressions-server.executioncontext.variables.md) | Record<string, unknown> | Context variables that can be consumed using var and var_set functions. | + diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executioncontext.search.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executioncontext.search.md new file mode 100644 index 0000000000000..641e50696f6e0 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executioncontext.search.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExecutionContext](./kibana-plugin-plugins-expressions-server.executioncontext.md) > [search](./kibana-plugin-plugins-expressions-server.executioncontext.search.md) + +## ExecutionContext.search property + +Search context in which expression should operate. + +Signature: + +```typescript +search?: ExecutionContextSearch; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executioncontext.types.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executioncontext.types.md new file mode 100644 index 0000000000000..9f594a588b200 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executioncontext.types.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExecutionContext](./kibana-plugin-plugins-expressions-server.executioncontext.md) > [types](./kibana-plugin-plugins-expressions-server.executioncontext.types.md) + +## ExecutionContext.types property + +A map of available expression types. + +Signature: + +```typescript +types: Record; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executioncontext.variables.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executioncontext.variables.md new file mode 100644 index 0000000000000..bce3b7bb1bc4d --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executioncontext.variables.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExecutionContext](./kibana-plugin-plugins-expressions-server.executioncontext.md) > [variables](./kibana-plugin-plugins-expressions-server.executioncontext.variables.md) + +## ExecutionContext.variables property + +Context variables that can be consumed using `var` and `var_set` functions. + +Signature: + +```typescript +variables: Record; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executionparams.ast.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executionparams.ast.md new file mode 100644 index 0000000000000..adaccf091bc5e --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executionparams.ast.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExecutionParams](./kibana-plugin-plugins-expressions-server.executionparams.md) > [ast](./kibana-plugin-plugins-expressions-server.executionparams.ast.md) + +## ExecutionParams.ast property + +Signature: + +```typescript +ast?: ExpressionAstExpression; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executionparams.context.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executionparams.context.md new file mode 100644 index 0000000000000..8b9a210416dd6 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executionparams.context.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExecutionParams](./kibana-plugin-plugins-expressions-server.executionparams.md) > [context](./kibana-plugin-plugins-expressions-server.executionparams.context.md) + +## ExecutionParams.context property + +Signature: + +```typescript +context?: ExtraContext; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executionparams.debug.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executionparams.debug.md new file mode 100644 index 0000000000000..b3631e0aeebe6 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executionparams.debug.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExecutionParams](./kibana-plugin-plugins-expressions-server.executionparams.md) > [debug](./kibana-plugin-plugins-expressions-server.executionparams.debug.md) + +## ExecutionParams.debug property + +Whether to execute expression in \*debug mode\*. In \*debug mode\* inputs and outputs as well as all resolved arguments and time it took to execute each function are saved and are available for introspection. + +Signature: + +```typescript +debug?: boolean; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executionparams.executor.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executionparams.executor.md new file mode 100644 index 0000000000000..fef0f6f8e2495 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executionparams.executor.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExecutionParams](./kibana-plugin-plugins-expressions-server.executionparams.md) > [executor](./kibana-plugin-plugins-expressions-server.executionparams.executor.md) + +## ExecutionParams.executor property + +Signature: + +```typescript +executor: Executor; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executionparams.expression.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executionparams.expression.md new file mode 100644 index 0000000000000..7d75bd51a611b --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executionparams.expression.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExecutionParams](./kibana-plugin-plugins-expressions-server.executionparams.md) > [expression](./kibana-plugin-plugins-expressions-server.executionparams.expression.md) + +## ExecutionParams.expression property + +Signature: + +```typescript +expression?: string; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executionparams.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executionparams.md new file mode 100644 index 0000000000000..a7594bff48c1a --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executionparams.md @@ -0,0 +1,22 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExecutionParams](./kibana-plugin-plugins-expressions-server.executionparams.md) + +## ExecutionParams interface + +Signature: + +```typescript +export interface ExecutionParams = Record> +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [ast](./kibana-plugin-plugins-expressions-server.executionparams.ast.md) | ExpressionAstExpression | | +| [context](./kibana-plugin-plugins-expressions-server.executionparams.context.md) | ExtraContext | | +| [debug](./kibana-plugin-plugins-expressions-server.executionparams.debug.md) | boolean | Whether to execute expression in \*debug mode\*. In \*debug mode\* inputs and outputs as well as all resolved arguments and time it took to execute each function are saved and are available for introspection. | +| [executor](./kibana-plugin-plugins-expressions-server.executionparams.executor.md) | Executor<any> | | +| [expression](./kibana-plugin-plugins-expressions-server.executionparams.expression.md) | string | | + diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executionstate.ast.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executionstate.ast.md new file mode 100644 index 0000000000000..0eab94589a75e --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executionstate.ast.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExecutionState](./kibana-plugin-plugins-expressions-server.executionstate.md) > [ast](./kibana-plugin-plugins-expressions-server.executionstate.ast.md) + +## ExecutionState.ast property + +Signature: + +```typescript +ast: ExpressionAstExpression; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executionstate.error.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executionstate.error.md new file mode 100644 index 0000000000000..350d38697571a --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executionstate.error.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExecutionState](./kibana-plugin-plugins-expressions-server.executionstate.md) > [error](./kibana-plugin-plugins-expressions-server.executionstate.error.md) + +## ExecutionState.error property + +Error happened during the execution. + +Signature: + +```typescript +error?: Error; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executionstate.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executionstate.md new file mode 100644 index 0000000000000..a3b28bda8c864 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executionstate.md @@ -0,0 +1,21 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExecutionState](./kibana-plugin-plugins-expressions-server.executionstate.md) + +## ExecutionState interface + +Signature: + +```typescript +export interface ExecutionState extends ExecutorState +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [ast](./kibana-plugin-plugins-expressions-server.executionstate.ast.md) | ExpressionAstExpression | | +| [error](./kibana-plugin-plugins-expressions-server.executionstate.error.md) | Error | Error happened during the execution. | +| [result](./kibana-plugin-plugins-expressions-server.executionstate.result.md) | Output | Result of the expression execution. | +| [state](./kibana-plugin-plugins-expressions-server.executionstate.state.md) | 'not-started' | 'pending' | 'result' | 'error' | Tracks state of execution.- not-started - before .start() method was called. - pending - immediately after .start() method is called. - result - when expression execution completed. - error - when execution failed with error. | + diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executionstate.result.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executionstate.result.md new file mode 100644 index 0000000000000..b23ba17172a10 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executionstate.result.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExecutionState](./kibana-plugin-plugins-expressions-server.executionstate.md) > [result](./kibana-plugin-plugins-expressions-server.executionstate.result.md) + +## ExecutionState.result property + +Result of the expression execution. + +Signature: + +```typescript +result?: Output; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executionstate.state.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executionstate.state.md new file mode 100644 index 0000000000000..6dcfca1a4fa0e --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executionstate.state.md @@ -0,0 +1,15 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExecutionState](./kibana-plugin-plugins-expressions-server.executionstate.md) > [state](./kibana-plugin-plugins-expressions-server.executionstate.state.md) + +## ExecutionState.state property + +Tracks state of execution. + +- `not-started` - before .start() method was called. - `pending` - immediately after .start() method is called. - `result` - when expression execution completed. - `error` - when execution failed with error. + +Signature: + +```typescript +state: 'not-started' | 'pending' | 'result' | 'error'; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executor._constructor_.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executor._constructor_.md new file mode 100644 index 0000000000000..f9b6759ef5529 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executor._constructor_.md @@ -0,0 +1,20 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [Executor](./kibana-plugin-plugins-expressions-server.executor.md) > [(constructor)](./kibana-plugin-plugins-expressions-server.executor._constructor_.md) + +## Executor.(constructor) + +Constructs a new instance of the `Executor` class + +Signature: + +```typescript +constructor(state?: ExecutorState); +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| state | ExecutorState<Context> | | + diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executor.context.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executor.context.md new file mode 100644 index 0000000000000..d53401c6d0419 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executor.context.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [Executor](./kibana-plugin-plugins-expressions-server.executor.md) > [context](./kibana-plugin-plugins-expressions-server.executor.context.md) + +## Executor.context property + +Signature: + +```typescript +get context(): Record; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executor.createexecution.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executor.createexecution.md new file mode 100644 index 0000000000000..8ed228d70ff37 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executor.createexecution.md @@ -0,0 +1,24 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [Executor](./kibana-plugin-plugins-expressions-server.executor.md) > [createExecution](./kibana-plugin-plugins-expressions-server.executor.createexecution.md) + +## Executor.createExecution() method + +Signature: + +```typescript +createExecution = Record, Input = unknown, Output = unknown>(ast: string | ExpressionAstExpression, context?: ExtraContext, { debug }?: ExpressionExecOptions): Execution; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| ast | string | ExpressionAstExpression | | +| context | ExtraContext | | +| { debug } | ExpressionExecOptions | | + +Returns: + +`Execution` + diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executor.createwithdefaults.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executor.createwithdefaults.md new file mode 100644 index 0000000000000..67863cc9e9ebe --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executor.createwithdefaults.md @@ -0,0 +1,22 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [Executor](./kibana-plugin-plugins-expressions-server.executor.md) > [createWithDefaults](./kibana-plugin-plugins-expressions-server.executor.createwithdefaults.md) + +## Executor.createWithDefaults() method + +Signature: + +```typescript +static createWithDefaults = Record>(state?: ExecutorState): Executor; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| state | ExecutorState<Ctx> | | + +Returns: + +`Executor` + diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executor.extendcontext.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executor.extendcontext.md new file mode 100644 index 0000000000000..d78b4193b62fa --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executor.extendcontext.md @@ -0,0 +1,22 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [Executor](./kibana-plugin-plugins-expressions-server.executor.md) > [extendContext](./kibana-plugin-plugins-expressions-server.executor.extendcontext.md) + +## Executor.extendContext() method + +Signature: + +```typescript +extendContext(extraContext: Record): void; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| extraContext | Record<string, unknown> | | + +Returns: + +`void` + diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executor.fork.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executor.fork.md new file mode 100644 index 0000000000000..8cfec983e6cbd --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executor.fork.md @@ -0,0 +1,15 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [Executor](./kibana-plugin-plugins-expressions-server.executor.md) > [fork](./kibana-plugin-plugins-expressions-server.executor.fork.md) + +## Executor.fork() method + +Signature: + +```typescript +fork(): Executor; +``` +Returns: + +`Executor` + diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executor.functions.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executor.functions.md new file mode 100644 index 0000000000000..36cbe8608c872 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executor.functions.md @@ -0,0 +1,15 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [Executor](./kibana-plugin-plugins-expressions-server.executor.md) > [functions](./kibana-plugin-plugins-expressions-server.executor.functions.md) + +## Executor.functions property + +> Warning: This API is now obsolete. +> +> + +Signature: + +```typescript +readonly functions: FunctionsRegistry; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executor.getfunction.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executor.getfunction.md new file mode 100644 index 0000000000000..0c3f307214d01 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executor.getfunction.md @@ -0,0 +1,22 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [Executor](./kibana-plugin-plugins-expressions-server.executor.md) > [getFunction](./kibana-plugin-plugins-expressions-server.executor.getfunction.md) + +## Executor.getFunction() method + +Signature: + +```typescript +getFunction(name: string): ExpressionFunction | undefined; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| name | string | | + +Returns: + +`ExpressionFunction | undefined` + diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executor.getfunctions.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executor.getfunctions.md new file mode 100644 index 0000000000000..9f4132e30297d --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executor.getfunctions.md @@ -0,0 +1,15 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [Executor](./kibana-plugin-plugins-expressions-server.executor.md) > [getFunctions](./kibana-plugin-plugins-expressions-server.executor.getfunctions.md) + +## Executor.getFunctions() method + +Signature: + +```typescript +getFunctions(): Record; +``` +Returns: + +`Record` + diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executor.gettype.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executor.gettype.md new file mode 100644 index 0000000000000..ccff4bc632284 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executor.gettype.md @@ -0,0 +1,22 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [Executor](./kibana-plugin-plugins-expressions-server.executor.md) > [getType](./kibana-plugin-plugins-expressions-server.executor.gettype.md) + +## Executor.getType() method + +Signature: + +```typescript +getType(name: string): ExpressionType | undefined; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| name | string | | + +Returns: + +`ExpressionType | undefined` + diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executor.gettypes.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executor.gettypes.md new file mode 100644 index 0000000000000..8658f36867971 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executor.gettypes.md @@ -0,0 +1,15 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [Executor](./kibana-plugin-plugins-expressions-server.executor.md) > [getTypes](./kibana-plugin-plugins-expressions-server.executor.gettypes.md) + +## Executor.getTypes() method + +Signature: + +```typescript +getTypes(): Record; +``` +Returns: + +`Record` + diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executor.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executor.md new file mode 100644 index 0000000000000..7e6bb8c7ded5e --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executor.md @@ -0,0 +1,43 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [Executor](./kibana-plugin-plugins-expressions-server.executor.md) + +## Executor class + +Signature: + +```typescript +export declare class Executor = Record> +``` + +## Constructors + +| Constructor | Modifiers | Description | +| --- | --- | --- | +| [(constructor)(state)](./kibana-plugin-plugins-expressions-server.executor._constructor_.md) | | Constructs a new instance of the Executor class | + +## Properties + +| Property | Modifiers | Type | Description | +| --- | --- | --- | --- | +| [context](./kibana-plugin-plugins-expressions-server.executor.context.md) | | Record<string, unknown> | | +| [functions](./kibana-plugin-plugins-expressions-server.executor.functions.md) | | FunctionsRegistry | | +| [state](./kibana-plugin-plugins-expressions-server.executor.state.md) | | ExecutorContainer<Context> | | +| [types](./kibana-plugin-plugins-expressions-server.executor.types.md) | | TypesRegistry | | + +## Methods + +| Method | Modifiers | Description | +| --- | --- | --- | +| [createExecution(ast, context, { debug })](./kibana-plugin-plugins-expressions-server.executor.createexecution.md) | | | +| [createWithDefaults(state)](./kibana-plugin-plugins-expressions-server.executor.createwithdefaults.md) | static | | +| [extendContext(extraContext)](./kibana-plugin-plugins-expressions-server.executor.extendcontext.md) | | | +| [fork()](./kibana-plugin-plugins-expressions-server.executor.fork.md) | | | +| [getFunction(name)](./kibana-plugin-plugins-expressions-server.executor.getfunction.md) | | | +| [getFunctions()](./kibana-plugin-plugins-expressions-server.executor.getfunctions.md) | | | +| [getType(name)](./kibana-plugin-plugins-expressions-server.executor.gettype.md) | | | +| [getTypes()](./kibana-plugin-plugins-expressions-server.executor.gettypes.md) | | | +| [registerFunction(functionDefinition)](./kibana-plugin-plugins-expressions-server.executor.registerfunction.md) | | | +| [registerType(typeDefinition)](./kibana-plugin-plugins-expressions-server.executor.registertype.md) | | | +| [run(ast, input, context)](./kibana-plugin-plugins-expressions-server.executor.run.md) | | Execute expression and return result. | + diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executor.registerfunction.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executor.registerfunction.md new file mode 100644 index 0000000000000..0cdd62735980c --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executor.registerfunction.md @@ -0,0 +1,22 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [Executor](./kibana-plugin-plugins-expressions-server.executor.md) > [registerFunction](./kibana-plugin-plugins-expressions-server.executor.registerfunction.md) + +## Executor.registerFunction() method + +Signature: + +```typescript +registerFunction(functionDefinition: AnyExpressionFunctionDefinition | (() => AnyExpressionFunctionDefinition)): void; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| functionDefinition | AnyExpressionFunctionDefinition | (() => AnyExpressionFunctionDefinition) | | + +Returns: + +`void` + diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executor.registertype.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executor.registertype.md new file mode 100644 index 0000000000000..355ff92921f10 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executor.registertype.md @@ -0,0 +1,22 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [Executor](./kibana-plugin-plugins-expressions-server.executor.md) > [registerType](./kibana-plugin-plugins-expressions-server.executor.registertype.md) + +## Executor.registerType() method + +Signature: + +```typescript +registerType(typeDefinition: AnyExpressionTypeDefinition | (() => AnyExpressionTypeDefinition)): void; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| typeDefinition | AnyExpressionTypeDefinition | (() => AnyExpressionTypeDefinition) | | + +Returns: + +`void` + diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executor.run.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executor.run.md new file mode 100644 index 0000000000000..784a1df5d3ac2 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executor.run.md @@ -0,0 +1,26 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [Executor](./kibana-plugin-plugins-expressions-server.executor.md) > [run](./kibana-plugin-plugins-expressions-server.executor.run.md) + +## Executor.run() method + +Execute expression and return result. + +Signature: + +```typescript +run = Record>(ast: string | ExpressionAstExpression, input: Input, context?: ExtraContext): Promise; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| ast | string | ExpressionAstExpression | | +| input | Input | | +| context | ExtraContext | | + +Returns: + +`Promise` + diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executor.state.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executor.state.md new file mode 100644 index 0000000000000..2c3041484712a --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executor.state.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [Executor](./kibana-plugin-plugins-expressions-server.executor.md) > [state](./kibana-plugin-plugins-expressions-server.executor.state.md) + +## Executor.state property + +Signature: + +```typescript +readonly state: ExecutorContainer; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executor.types.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executor.types.md new file mode 100644 index 0000000000000..2082917cf0624 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executor.types.md @@ -0,0 +1,15 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [Executor](./kibana-plugin-plugins-expressions-server.executor.md) > [types](./kibana-plugin-plugins-expressions-server.executor.types.md) + +## Executor.types property + +> Warning: This API is now obsolete. +> +> + +Signature: + +```typescript +readonly types: TypesRegistry; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executorcontainer.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executorcontainer.md new file mode 100644 index 0000000000000..a3847c5ad9a77 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executorcontainer.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExecutorContainer](./kibana-plugin-plugins-expressions-server.executorcontainer.md) + +## ExecutorContainer type + +Signature: + +```typescript +export declare type ExecutorContainer = Record> = StateContainer, ExecutorPureTransitions, ExecutorPureSelectors>; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executorstate.context.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executorstate.context.md new file mode 100644 index 0000000000000..0829f2d6caf04 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executorstate.context.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExecutorState](./kibana-plugin-plugins-expressions-server.executorstate.md) > [context](./kibana-plugin-plugins-expressions-server.executorstate.context.md) + +## ExecutorState.context property + +Signature: + +```typescript +context: Context; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executorstate.functions.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executorstate.functions.md new file mode 100644 index 0000000000000..92a0865a7bb2f --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executorstate.functions.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExecutorState](./kibana-plugin-plugins-expressions-server.executorstate.md) > [functions](./kibana-plugin-plugins-expressions-server.executorstate.functions.md) + +## ExecutorState.functions property + +Signature: + +```typescript +functions: Record; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executorstate.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executorstate.md new file mode 100644 index 0000000000000..5faa326ee3534 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executorstate.md @@ -0,0 +1,20 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExecutorState](./kibana-plugin-plugins-expressions-server.executorstate.md) + +## ExecutorState interface + +Signature: + +```typescript +export interface ExecutorState = Record> +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [context](./kibana-plugin-plugins-expressions-server.executorstate.context.md) | Context | | +| [functions](./kibana-plugin-plugins-expressions-server.executorstate.functions.md) | Record<string, ExpressionFunction> | | +| [types](./kibana-plugin-plugins-expressions-server.executorstate.types.md) | Record<string, ExpressionType> | | + diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executorstate.types.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executorstate.types.md new file mode 100644 index 0000000000000..a435fabfedf92 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executorstate.types.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExecutorState](./kibana-plugin-plugins-expressions-server.executorstate.md) > [types](./kibana-plugin-plugins-expressions-server.executorstate.types.md) + +## ExecutorState.types property + +Signature: + +```typescript +types: Record; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionastargument.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionastargument.md new file mode 100644 index 0000000000000..0518949ad612f --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionastargument.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionAstArgument](./kibana-plugin-plugins-expressions-server.expressionastargument.md) + +## ExpressionAstArgument type + +Signature: + +```typescript +export declare type ExpressionAstArgument = string | boolean | number | ExpressionAstExpression; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionastexpression.chain.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionastexpression.chain.md new file mode 100644 index 0000000000000..cc8006b918dec --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionastexpression.chain.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionAstExpression](./kibana-plugin-plugins-expressions-server.expressionastexpression.md) > [chain](./kibana-plugin-plugins-expressions-server.expressionastexpression.chain.md) + +## ExpressionAstExpression.chain property + +Signature: + +```typescript +chain: ExpressionAstFunction[]; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionastexpression.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionastexpression.md new file mode 100644 index 0000000000000..b5f83d1af7cb7 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionastexpression.md @@ -0,0 +1,19 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionAstExpression](./kibana-plugin-plugins-expressions-server.expressionastexpression.md) + +## ExpressionAstExpression interface + +Signature: + +```typescript +export interface ExpressionAstExpression +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [chain](./kibana-plugin-plugins-expressions-server.expressionastexpression.chain.md) | ExpressionAstFunction[] | | +| [type](./kibana-plugin-plugins-expressions-server.expressionastexpression.type.md) | 'expression' | | + diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionastexpression.type.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionastexpression.type.md new file mode 100644 index 0000000000000..46cd60cecaa84 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionastexpression.type.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionAstExpression](./kibana-plugin-plugins-expressions-server.expressionastexpression.md) > [type](./kibana-plugin-plugins-expressions-server.expressionastexpression.type.md) + +## ExpressionAstExpression.type property + +Signature: + +```typescript +type: 'expression'; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionastexpressionbuilder.findfunction.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionastexpressionbuilder.findfunction.md new file mode 100644 index 0000000000000..28cf8707c17d6 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionastexpressionbuilder.findfunction.md @@ -0,0 +1,15 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionAstExpressionBuilder](./kibana-plugin-plugins-expressions-server.expressionastexpressionbuilder.md) > [findFunction](./kibana-plugin-plugins-expressions-server.expressionastexpressionbuilder.findfunction.md) + +## ExpressionAstExpressionBuilder.findFunction property + +Recursively searches expression for all ocurrences of the function, including in subexpressions. + +Useful when performing migrations on a specific function, as you can iterate over the array of references and update all functions at once. + +Signature: + +```typescript +findFunction: (fnName: InferFunctionDefinition['name']) => Array> | []; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionastexpressionbuilder.functions.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionastexpressionbuilder.functions.md new file mode 100644 index 0000000000000..c3e1add70511b --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionastexpressionbuilder.functions.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionAstExpressionBuilder](./kibana-plugin-plugins-expressions-server.expressionastexpressionbuilder.md) > [functions](./kibana-plugin-plugins-expressions-server.expressionastexpressionbuilder.functions.md) + +## ExpressionAstExpressionBuilder.functions property + +Array of each of the `buildExpressionFunction()` instances in this expression. Use this to remove or reorder functions in the expression. + +Signature: + +```typescript +functions: ExpressionAstFunctionBuilder[]; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionastexpressionbuilder.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionastexpressionbuilder.md new file mode 100644 index 0000000000000..50a9c76daaa2b --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionastexpressionbuilder.md @@ -0,0 +1,22 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionAstExpressionBuilder](./kibana-plugin-plugins-expressions-server.expressionastexpressionbuilder.md) + +## ExpressionAstExpressionBuilder interface + +Signature: + +```typescript +export interface ExpressionAstExpressionBuilder +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [findFunction](./kibana-plugin-plugins-expressions-server.expressionastexpressionbuilder.findfunction.md) | <FnDef extends AnyExpressionFunctionDefinition = AnyExpressionFunctionDefinition>(fnName: InferFunctionDefinition<FnDef>['name']) => Array<ExpressionAstFunctionBuilder<FnDef>> | [] | Recursively searches expression for all ocurrences of the function, including in subexpressions.Useful when performing migrations on a specific function, as you can iterate over the array of references and update all functions at once. | +| [functions](./kibana-plugin-plugins-expressions-server.expressionastexpressionbuilder.functions.md) | ExpressionAstFunctionBuilder[] | Array of each of the buildExpressionFunction() instances in this expression. Use this to remove or reorder functions in the expression. | +| [toAst](./kibana-plugin-plugins-expressions-server.expressionastexpressionbuilder.toast.md) | () => ExpressionAstExpression | Converts expression to an AST. ExpressionAstExpression | +| [toString](./kibana-plugin-plugins-expressions-server.expressionastexpressionbuilder.tostring.md) | () => string | Converts expression to an expression string. string | +| [type](./kibana-plugin-plugins-expressions-server.expressionastexpressionbuilder.type.md) | 'expression_builder' | Used to identify expression builder objects. | + diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionastexpressionbuilder.toast.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionastexpressionbuilder.toast.md new file mode 100644 index 0000000000000..5c6189e6a46c4 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionastexpressionbuilder.toast.md @@ -0,0 +1,15 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionAstExpressionBuilder](./kibana-plugin-plugins-expressions-server.expressionastexpressionbuilder.md) > [toAst](./kibana-plugin-plugins-expressions-server.expressionastexpressionbuilder.toast.md) + +## ExpressionAstExpressionBuilder.toAst property + +Converts expression to an AST. + + `ExpressionAstExpression` + +Signature: + +```typescript +toAst: () => ExpressionAstExpression; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionastexpressionbuilder.tostring.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionastexpressionbuilder.tostring.md new file mode 100644 index 0000000000000..80aaeef1700c3 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionastexpressionbuilder.tostring.md @@ -0,0 +1,15 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionAstExpressionBuilder](./kibana-plugin-plugins-expressions-server.expressionastexpressionbuilder.md) > [toString](./kibana-plugin-plugins-expressions-server.expressionastexpressionbuilder.tostring.md) + +## ExpressionAstExpressionBuilder.toString property + +Converts expression to an expression string. + + `string` + +Signature: + +```typescript +toString: () => string; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionastexpressionbuilder.type.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionastexpressionbuilder.type.md new file mode 100644 index 0000000000000..401b2e3725e84 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionastexpressionbuilder.type.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionAstExpressionBuilder](./kibana-plugin-plugins-expressions-server.expressionastexpressionbuilder.md) > [type](./kibana-plugin-plugins-expressions-server.expressionastexpressionbuilder.type.md) + +## ExpressionAstExpressionBuilder.type property + +Used to identify expression builder objects. + +Signature: + +```typescript +type: 'expression_builder'; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionastfunction.arguments.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionastfunction.arguments.md new file mode 100644 index 0000000000000..052cadffb9bdb --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionastfunction.arguments.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionAstFunction](./kibana-plugin-plugins-expressions-server.expressionastfunction.md) > [arguments](./kibana-plugin-plugins-expressions-server.expressionastfunction.arguments.md) + +## ExpressionAstFunction.arguments property + +Signature: + +```typescript +arguments: Record; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionastfunction.debug.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionastfunction.debug.md new file mode 100644 index 0000000000000..b3227c2ac5822 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionastfunction.debug.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionAstFunction](./kibana-plugin-plugins-expressions-server.expressionastfunction.md) > [debug](./kibana-plugin-plugins-expressions-server.expressionastfunction.debug.md) + +## ExpressionAstFunction.debug property + +Debug information added to each function when expression is executed in \*debug mode\*. + +Signature: + +```typescript +debug?: ExpressionAstFunctionDebug; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionastfunction.function.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionastfunction.function.md new file mode 100644 index 0000000000000..9964409f49119 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionastfunction.function.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionAstFunction](./kibana-plugin-plugins-expressions-server.expressionastfunction.md) > [function](./kibana-plugin-plugins-expressions-server.expressionastfunction.function.md) + +## ExpressionAstFunction.function property + +Signature: + +```typescript +function: string; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionastfunction.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionastfunction.md new file mode 100644 index 0000000000000..1d49de44b571d --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionastfunction.md @@ -0,0 +1,21 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionAstFunction](./kibana-plugin-plugins-expressions-server.expressionastfunction.md) + +## ExpressionAstFunction interface + +Signature: + +```typescript +export interface ExpressionAstFunction +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [arguments](./kibana-plugin-plugins-expressions-server.expressionastfunction.arguments.md) | Record<string, ExpressionAstArgument[]> | | +| [debug](./kibana-plugin-plugins-expressions-server.expressionastfunction.debug.md) | ExpressionAstFunctionDebug | Debug information added to each function when expression is executed in \*debug mode\*. | +| [function](./kibana-plugin-plugins-expressions-server.expressionastfunction.function.md) | string | | +| [type](./kibana-plugin-plugins-expressions-server.expressionastfunction.type.md) | 'function' | | + diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionastfunction.type.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionastfunction.type.md new file mode 100644 index 0000000000000..3fd10524c1599 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionastfunction.type.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionAstFunction](./kibana-plugin-plugins-expressions-server.expressionastfunction.md) > [type](./kibana-plugin-plugins-expressions-server.expressionastfunction.type.md) + +## ExpressionAstFunction.type property + +Signature: + +```typescript +type: 'function'; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionastfunctionbuilder.addargument.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionastfunctionbuilder.addargument.md new file mode 100644 index 0000000000000..29e3baec18a2e --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionastfunctionbuilder.addargument.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionAstFunctionBuilder](./kibana-plugin-plugins-expressions-server.expressionastfunctionbuilder.md) > [addArgument](./kibana-plugin-plugins-expressions-server.expressionastfunctionbuilder.addargument.md) + +## ExpressionAstFunctionBuilder.addArgument property + +Adds an additional argument to the function. For multi-args, this should be called once for each new arg. Note that TS will not enforce whether multi-args are available, so only use this to update an existing arg if you are certain it is a multi-arg. + +Signature: + +```typescript +addArgument:
    >(name: A, value: FunctionArgs[A] | ExpressionAstExpressionBuilder) => this; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionastfunctionbuilder.arguments.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionastfunctionbuilder.arguments.md new file mode 100644 index 0000000000000..4c0eee637b3e1 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionastfunctionbuilder.arguments.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionAstFunctionBuilder](./kibana-plugin-plugins-expressions-server.expressionastfunctionbuilder.md) > [arguments](./kibana-plugin-plugins-expressions-server.expressionastfunctionbuilder.arguments.md) + +## ExpressionAstFunctionBuilder.arguments property + +Object of all args currently added to the function. This is structured similarly to `ExpressionAstFunction['arguments']`, however any subexpressions are returned as expression builder instances instead of expression ASTs. + +Signature: + +```typescript +arguments: FunctionBuilderArguments; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionastfunctionbuilder.getargument.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionastfunctionbuilder.getargument.md new file mode 100644 index 0000000000000..09b76ccbf23d9 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionastfunctionbuilder.getargument.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionAstFunctionBuilder](./kibana-plugin-plugins-expressions-server.expressionastfunctionbuilder.md) > [getArgument](./kibana-plugin-plugins-expressions-server.expressionastfunctionbuilder.getargument.md) + +## ExpressionAstFunctionBuilder.getArgument property + +Retrieves an existing argument by name. Useful when you want to retrieve the current array of args and add something to it before calling `replaceArgument`. Any subexpression arguments will be returned as expression builder instances. + +Signature: + +```typescript +getArgument: >(name: A) => Array[A] | ExpressionAstExpressionBuilder> | undefined; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionastfunctionbuilder.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionastfunctionbuilder.md new file mode 100644 index 0000000000000..2a502d6f05e0b --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionastfunctionbuilder.md @@ -0,0 +1,26 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionAstFunctionBuilder](./kibana-plugin-plugins-expressions-server.expressionastfunctionbuilder.md) + +## ExpressionAstFunctionBuilder interface + +Signature: + +```typescript +export interface ExpressionAstFunctionBuilder +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [addArgument](./kibana-plugin-plugins-expressions-server.expressionastfunctionbuilder.addargument.md) | <A extends FunctionArgName<FnDef>>(name: A, value: FunctionArgs<FnDef>[A] | ExpressionAstExpressionBuilder) => this | Adds an additional argument to the function. For multi-args, this should be called once for each new arg. Note that TS will not enforce whether multi-args are available, so only use this to update an existing arg if you are certain it is a multi-arg. | +| [arguments](./kibana-plugin-plugins-expressions-server.expressionastfunctionbuilder.arguments.md) | FunctionBuilderArguments<FnDef> | Object of all args currently added to the function. This is structured similarly to ExpressionAstFunction['arguments'], however any subexpressions are returned as expression builder instances instead of expression ASTs. | +| [getArgument](./kibana-plugin-plugins-expressions-server.expressionastfunctionbuilder.getargument.md) | <A extends FunctionArgName<FnDef>>(name: A) => Array<FunctionArgs<FnDef>[A] | ExpressionAstExpressionBuilder> | undefined | Retrieves an existing argument by name. Useful when you want to retrieve the current array of args and add something to it before calling replaceArgument. Any subexpression arguments will be returned as expression builder instances. | +| [name](./kibana-plugin-plugins-expressions-server.expressionastfunctionbuilder.name.md) | InferFunctionDefinition<FnDef>['name'] | Name of this expression function. | +| [removeArgument](./kibana-plugin-plugins-expressions-server.expressionastfunctionbuilder.removeargument.md) | <A extends OptionalKeys<FunctionArgs<FnDef>>>(name: A) => this | Removes an (optional) argument from the function.TypeScript will enforce that you only remove optional arguments. For manipulating required args, use replaceArgument. | +| [replaceArgument](./kibana-plugin-plugins-expressions-server.expressionastfunctionbuilder.replaceargument.md) | <A extends FunctionArgName<FnDef>>(name: A, value: Array<FunctionArgs<FnDef>[A] | ExpressionAstExpressionBuilder>) => this | Overwrites an existing argument with a new value. In order to support multi-args, the value given must always be an array. | +| [toAst](./kibana-plugin-plugins-expressions-server.expressionastfunctionbuilder.toast.md) | () => ExpressionAstFunction | Converts function to an AST. ExpressionAstFunction | +| [toString](./kibana-plugin-plugins-expressions-server.expressionastfunctionbuilder.tostring.md) | () => string | Converts function to an expression string. string | +| [type](./kibana-plugin-plugins-expressions-server.expressionastfunctionbuilder.type.md) | 'expression_function_builder' | Used to identify expression function builder objects. | + diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionastfunctionbuilder.name.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionastfunctionbuilder.name.md new file mode 100644 index 0000000000000..a2b6a4128549f --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionastfunctionbuilder.name.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionAstFunctionBuilder](./kibana-plugin-plugins-expressions-server.expressionastfunctionbuilder.md) > [name](./kibana-plugin-plugins-expressions-server.expressionastfunctionbuilder.name.md) + +## ExpressionAstFunctionBuilder.name property + +Name of this expression function. + +Signature: + +```typescript +name: InferFunctionDefinition['name']; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionastfunctionbuilder.removeargument.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionastfunctionbuilder.removeargument.md new file mode 100644 index 0000000000000..b5fd0cc7e3727 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionastfunctionbuilder.removeargument.md @@ -0,0 +1,15 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionAstFunctionBuilder](./kibana-plugin-plugins-expressions-server.expressionastfunctionbuilder.md) > [removeArgument](./kibana-plugin-plugins-expressions-server.expressionastfunctionbuilder.removeargument.md) + +## ExpressionAstFunctionBuilder.removeArgument property + +Removes an (optional) argument from the function. + +TypeScript will enforce that you only remove optional arguments. For manipulating required args, use `replaceArgument`. + +Signature: + +```typescript +removeArgument: >>(name: A) => this; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionastfunctionbuilder.replaceargument.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionastfunctionbuilder.replaceargument.md new file mode 100644 index 0000000000000..943d8ea235763 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionastfunctionbuilder.replaceargument.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionAstFunctionBuilder](./kibana-plugin-plugins-expressions-server.expressionastfunctionbuilder.md) > [replaceArgument](./kibana-plugin-plugins-expressions-server.expressionastfunctionbuilder.replaceargument.md) + +## ExpressionAstFunctionBuilder.replaceArgument property + +Overwrites an existing argument with a new value. In order to support multi-args, the value given must always be an array. + +Signature: + +```typescript +replaceArgument: >(name: A, value: Array[A] | ExpressionAstExpressionBuilder>) => this; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionastfunctionbuilder.toast.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionastfunctionbuilder.toast.md new file mode 100644 index 0000000000000..a8e9205610501 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionastfunctionbuilder.toast.md @@ -0,0 +1,15 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionAstFunctionBuilder](./kibana-plugin-plugins-expressions-server.expressionastfunctionbuilder.md) > [toAst](./kibana-plugin-plugins-expressions-server.expressionastfunctionbuilder.toast.md) + +## ExpressionAstFunctionBuilder.toAst property + +Converts function to an AST. + + `ExpressionAstFunction` + +Signature: + +```typescript +toAst: () => ExpressionAstFunction; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionastfunctionbuilder.tostring.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionastfunctionbuilder.tostring.md new file mode 100644 index 0000000000000..af307cbc84c9f --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionastfunctionbuilder.tostring.md @@ -0,0 +1,15 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionAstFunctionBuilder](./kibana-plugin-plugins-expressions-server.expressionastfunctionbuilder.md) > [toString](./kibana-plugin-plugins-expressions-server.expressionastfunctionbuilder.tostring.md) + +## ExpressionAstFunctionBuilder.toString property + +Converts function to an expression string. + + `string` + +Signature: + +```typescript +toString: () => string; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionastfunctionbuilder.type.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionastfunctionbuilder.type.md new file mode 100644 index 0000000000000..ed1db54c6eeaa --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionastfunctionbuilder.type.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionAstFunctionBuilder](./kibana-plugin-plugins-expressions-server.expressionastfunctionbuilder.md) > [type](./kibana-plugin-plugins-expressions-server.expressionastfunctionbuilder.type.md) + +## ExpressionAstFunctionBuilder.type property + +Used to identify expression function builder objects. + +Signature: + +```typescript +type: 'expression_function_builder'; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionastnode.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionastnode.md new file mode 100644 index 0000000000000..d04c5556ff0ff --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionastnode.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionAstNode](./kibana-plugin-plugins-expressions-server.expressionastnode.md) + +## ExpressionAstNode type + +Signature: + +```typescript +export declare type ExpressionAstNode = ExpressionAstExpression | ExpressionAstFunction | ExpressionAstArgument; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunction._constructor_.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunction._constructor_.md new file mode 100644 index 0000000000000..96ed22f3277b4 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunction._constructor_.md @@ -0,0 +1,20 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionFunction](./kibana-plugin-plugins-expressions-server.expressionfunction.md) > [(constructor)](./kibana-plugin-plugins-expressions-server.expressionfunction._constructor_.md) + +## ExpressionFunction.(constructor) + +Constructs a new instance of the `ExpressionFunction` class + +Signature: + +```typescript +constructor(functionDefinition: AnyExpressionFunctionDefinition); +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| functionDefinition | AnyExpressionFunctionDefinition | | + diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunction.accepts.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunction.accepts.md new file mode 100644 index 0000000000000..25008a56e0465 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunction.accepts.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionFunction](./kibana-plugin-plugins-expressions-server.expressionfunction.md) > [accepts](./kibana-plugin-plugins-expressions-server.expressionfunction.accepts.md) + +## ExpressionFunction.accepts property + +Signature: + +```typescript +accepts: (type: string) => boolean; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunction.aliases.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunction.aliases.md new file mode 100644 index 0000000000000..6e11246275d04 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunction.aliases.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionFunction](./kibana-plugin-plugins-expressions-server.expressionfunction.md) > [aliases](./kibana-plugin-plugins-expressions-server.expressionfunction.aliases.md) + +## ExpressionFunction.aliases property + +Aliases that can be used instead of `name`. + +Signature: + +```typescript +aliases: string[]; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunction.args.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunction.args.md new file mode 100644 index 0000000000000..ffa8cd0d11f7a --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunction.args.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionFunction](./kibana-plugin-plugins-expressions-server.expressionfunction.md) > [args](./kibana-plugin-plugins-expressions-server.expressionfunction.args.md) + +## ExpressionFunction.args property + +Specification of expression function parameters. + +Signature: + +```typescript +args: Record; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunction.fn.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunction.fn.md new file mode 100644 index 0000000000000..12056cac12cce --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunction.fn.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionFunction](./kibana-plugin-plugins-expressions-server.expressionfunction.md) > [fn](./kibana-plugin-plugins-expressions-server.expressionfunction.fn.md) + +## ExpressionFunction.fn property + +Function to run function (context, args) + +Signature: + +```typescript +fn: (input: ExpressionValue, params: Record, handlers: object) => ExpressionValue; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunction.help.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunction.help.md new file mode 100644 index 0000000000000..0a20a1ec60860 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunction.help.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionFunction](./kibana-plugin-plugins-expressions-server.expressionfunction.md) > [help](./kibana-plugin-plugins-expressions-server.expressionfunction.help.md) + +## ExpressionFunction.help property + +A short help text. + +Signature: + +```typescript +help: string; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunction.inputtypes.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunction.inputtypes.md new file mode 100644 index 0000000000000..1fa11bbb77416 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunction.inputtypes.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionFunction](./kibana-plugin-plugins-expressions-server.expressionfunction.md) > [inputTypes](./kibana-plugin-plugins-expressions-server.expressionfunction.inputtypes.md) + +## ExpressionFunction.inputTypes property + +Type of inputs that this function supports. + +Signature: + +```typescript +inputTypes: string[] | undefined; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunction.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunction.md new file mode 100644 index 0000000000000..aac3878b8c859 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunction.md @@ -0,0 +1,31 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionFunction](./kibana-plugin-plugins-expressions-server.expressionfunction.md) + +## ExpressionFunction class + +Signature: + +```typescript +export declare class ExpressionFunction +``` + +## Constructors + +| Constructor | Modifiers | Description | +| --- | --- | --- | +| [(constructor)(functionDefinition)](./kibana-plugin-plugins-expressions-server.expressionfunction._constructor_.md) | | Constructs a new instance of the ExpressionFunction class | + +## Properties + +| Property | Modifiers | Type | Description | +| --- | --- | --- | --- | +| [accepts](./kibana-plugin-plugins-expressions-server.expressionfunction.accepts.md) | | (type: string) => boolean | | +| [aliases](./kibana-plugin-plugins-expressions-server.expressionfunction.aliases.md) | | string[] | Aliases that can be used instead of name. | +| [args](./kibana-plugin-plugins-expressions-server.expressionfunction.args.md) | | Record<string, ExpressionFunctionParameter> | Specification of expression function parameters. | +| [fn](./kibana-plugin-plugins-expressions-server.expressionfunction.fn.md) | | (input: ExpressionValue, params: Record<string, any>, handlers: object) => ExpressionValue | Function to run function (context, args) | +| [help](./kibana-plugin-plugins-expressions-server.expressionfunction.help.md) | | string | A short help text. | +| [inputTypes](./kibana-plugin-plugins-expressions-server.expressionfunction.inputtypes.md) | | string[] | undefined | Type of inputs that this function supports. | +| [name](./kibana-plugin-plugins-expressions-server.expressionfunction.name.md) | | string | Name of function | +| [type](./kibana-plugin-plugins-expressions-server.expressionfunction.type.md) | | string | Return type of function. This SHOULD be supplied. We use it for UI and autocomplete hinting. We may also use it for optimizations in the future. | + diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunction.name.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunction.name.md new file mode 100644 index 0000000000000..46115c10c79ad --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunction.name.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionFunction](./kibana-plugin-plugins-expressions-server.expressionfunction.md) > [name](./kibana-plugin-plugins-expressions-server.expressionfunction.name.md) + +## ExpressionFunction.name property + +Name of function + +Signature: + +```typescript +name: string; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunction.type.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunction.type.md new file mode 100644 index 0000000000000..82bfff184b7cf --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunction.type.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionFunction](./kibana-plugin-plugins-expressions-server.expressionfunction.md) > [type](./kibana-plugin-plugins-expressions-server.expressionfunction.type.md) + +## ExpressionFunction.type property + +Return type of function. This SHOULD be supplied. We use it for UI and autocomplete hinting. We may also use it for optimizations in the future. + +Signature: + +```typescript +type: string; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunctiondefinition.aliases.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunctiondefinition.aliases.md new file mode 100644 index 0000000000000..3f5a608cc9bd2 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunctiondefinition.aliases.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionFunctionDefinition](./kibana-plugin-plugins-expressions-server.expressionfunctiondefinition.md) > [aliases](./kibana-plugin-plugins-expressions-server.expressionfunctiondefinition.aliases.md) + +## ExpressionFunctionDefinition.aliases property + + What is this? + +Signature: + +```typescript +aliases?: string[]; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunctiondefinition.args.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunctiondefinition.args.md new file mode 100644 index 0000000000000..4ceb1d92bf8eb --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunctiondefinition.args.md @@ -0,0 +1,15 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionFunctionDefinition](./kibana-plugin-plugins-expressions-server.expressionfunctiondefinition.md) > [args](./kibana-plugin-plugins-expressions-server.expressionfunctiondefinition.args.md) + +## ExpressionFunctionDefinition.args property + +Specification of arguments that function supports. This list will also be used for autocomplete functionality when your function is being edited. + +Signature: + +```typescript +args: { + [key in keyof Arguments]: ArgumentType; + }; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunctiondefinition.context.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunctiondefinition.context.md new file mode 100644 index 0000000000000..54d5c7c8a688d --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunctiondefinition.context.md @@ -0,0 +1,18 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionFunctionDefinition](./kibana-plugin-plugins-expressions-server.expressionfunctiondefinition.md) > [context](./kibana-plugin-plugins-expressions-server.expressionfunctiondefinition.context.md) + +## ExpressionFunctionDefinition.context property + +> Warning: This API is now obsolete. +> +> Use `inputTypes` instead. +> + +Signature: + +```typescript +context?: { + types: AnyExpressionFunctionDefinition['inputTypes']; + }; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunctiondefinition.fn.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunctiondefinition.fn.md new file mode 100644 index 0000000000000..41f85be7141be --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunctiondefinition.fn.md @@ -0,0 +1,26 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionFunctionDefinition](./kibana-plugin-plugins-expressions-server.expressionfunctiondefinition.md) > [fn](./kibana-plugin-plugins-expressions-server.expressionfunctiondefinition.fn.md) + +## ExpressionFunctionDefinition.fn() method + +The actual implementation of the function. + +Signature: + +```typescript +fn(input: Input, args: Arguments, context: Context): Output; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| input | Input | | +| args | Arguments | | +| context | Context | | + +Returns: + +`Output` + diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunctiondefinition.help.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunctiondefinition.help.md new file mode 100644 index 0000000000000..594cb768f3caa --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunctiondefinition.help.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionFunctionDefinition](./kibana-plugin-plugins-expressions-server.expressionfunctiondefinition.md) > [help](./kibana-plugin-plugins-expressions-server.expressionfunctiondefinition.help.md) + +## ExpressionFunctionDefinition.help property + +Help text displayed in the Expression editor. This text should be internationalized. + +Signature: + +```typescript +help: string; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunctiondefinition.inputtypes.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunctiondefinition.inputtypes.md new file mode 100644 index 0000000000000..b47dc915cc72e --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunctiondefinition.inputtypes.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionFunctionDefinition](./kibana-plugin-plugins-expressions-server.expressionfunctiondefinition.md) > [inputTypes](./kibana-plugin-plugins-expressions-server.expressionfunctiondefinition.inputtypes.md) + +## ExpressionFunctionDefinition.inputTypes property + +List of allowed type names for input value of this function. If this property is set the input of function will be cast to the first possible type in this list. If this property is missing the input will be provided to the function as-is. + +Signature: + +```typescript +inputTypes?: Array>; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunctiondefinition.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunctiondefinition.md new file mode 100644 index 0000000000000..6463c6ac537b9 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunctiondefinition.md @@ -0,0 +1,32 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionFunctionDefinition](./kibana-plugin-plugins-expressions-server.expressionfunctiondefinition.md) + +## ExpressionFunctionDefinition interface + +`ExpressionFunctionDefinition` is the interface plugins have to implement to register a function in `expressions` plugin. + +Signature: + +```typescript +export interface ExpressionFunctionDefinition, Output, Context extends ExecutionContext = ExecutionContext> +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [aliases](./kibana-plugin-plugins-expressions-server.expressionfunctiondefinition.aliases.md) | string[] | What is this? | +| [args](./kibana-plugin-plugins-expressions-server.expressionfunctiondefinition.args.md) | {
    [key in keyof Arguments]: ArgumentType<Arguments[key]>;
    } | Specification of arguments that function supports. This list will also be used for autocomplete functionality when your function is being edited. | +| [context](./kibana-plugin-plugins-expressions-server.expressionfunctiondefinition.context.md) | {
    types: AnyExpressionFunctionDefinition['inputTypes'];
    } | | +| [help](./kibana-plugin-plugins-expressions-server.expressionfunctiondefinition.help.md) | string | Help text displayed in the Expression editor. This text should be internationalized. | +| [inputTypes](./kibana-plugin-plugins-expressions-server.expressionfunctiondefinition.inputtypes.md) | Array<TypeToString<Input>> | List of allowed type names for input value of this function. If this property is set the input of function will be cast to the first possible type in this list. If this property is missing the input will be provided to the function as-is. | +| [name](./kibana-plugin-plugins-expressions-server.expressionfunctiondefinition.name.md) | Name | The name of the function, as will be used in expression. | +| [type](./kibana-plugin-plugins-expressions-server.expressionfunctiondefinition.type.md) | TypeToString<UnwrapPromiseOrReturn<Output>> | Name of type of value this function outputs. | + +## Methods + +| Method | Description | +| --- | --- | +| [fn(input, args, context)](./kibana-plugin-plugins-expressions-server.expressionfunctiondefinition.fn.md) | The actual implementation of the function. | + diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunctiondefinition.name.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunctiondefinition.name.md new file mode 100644 index 0000000000000..177b44aab4ce8 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunctiondefinition.name.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionFunctionDefinition](./kibana-plugin-plugins-expressions-server.expressionfunctiondefinition.md) > [name](./kibana-plugin-plugins-expressions-server.expressionfunctiondefinition.name.md) + +## ExpressionFunctionDefinition.name property + +The name of the function, as will be used in expression. + +Signature: + +```typescript +name: Name; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunctiondefinition.type.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunctiondefinition.type.md new file mode 100644 index 0000000000000..a73ded342f053 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunctiondefinition.type.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionFunctionDefinition](./kibana-plugin-plugins-expressions-server.expressionfunctiondefinition.md) > [type](./kibana-plugin-plugins-expressions-server.expressionfunctiondefinition.type.md) + +## ExpressionFunctionDefinition.type property + +Name of type of value this function outputs. + +Signature: + +```typescript +type?: TypeToString>; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunctiondefinitions.clog.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunctiondefinitions.clog.md new file mode 100644 index 0000000000000..0c01e93152c75 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunctiondefinitions.clog.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionFunctionDefinitions](./kibana-plugin-plugins-expressions-server.expressionfunctiondefinitions.md) > [clog](./kibana-plugin-plugins-expressions-server.expressionfunctiondefinitions.clog.md) + +## ExpressionFunctionDefinitions.clog property + +Signature: + +```typescript +clog: ExpressionFunctionClog; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunctiondefinitions.font.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunctiondefinitions.font.md new file mode 100644 index 0000000000000..842e3e069d91e --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunctiondefinitions.font.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionFunctionDefinitions](./kibana-plugin-plugins-expressions-server.expressionfunctiondefinitions.md) > [font](./kibana-plugin-plugins-expressions-server.expressionfunctiondefinitions.font.md) + +## ExpressionFunctionDefinitions.font property + +Signature: + +```typescript +font: ExpressionFunctionFont; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunctiondefinitions.kibana.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunctiondefinitions.kibana.md new file mode 100644 index 0000000000000..8e6d189f8f450 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunctiondefinitions.kibana.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionFunctionDefinitions](./kibana-plugin-plugins-expressions-server.expressionfunctiondefinitions.md) > [kibana](./kibana-plugin-plugins-expressions-server.expressionfunctiondefinitions.kibana.md) + +## ExpressionFunctionDefinitions.kibana property + +Signature: + +```typescript +kibana: ExpressionFunctionKibana; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunctiondefinitions.kibana_context.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunctiondefinitions.kibana_context.md new file mode 100644 index 0000000000000..f9e248ad6d913 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunctiondefinitions.kibana_context.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionFunctionDefinitions](./kibana-plugin-plugins-expressions-server.expressionfunctiondefinitions.md) > [kibana\_context](./kibana-plugin-plugins-expressions-server.expressionfunctiondefinitions.kibana_context.md) + +## ExpressionFunctionDefinitions.kibana\_context property + +Signature: + +```typescript +kibana_context: ExpressionFunctionKibanaContext; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunctiondefinitions.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunctiondefinitions.md new file mode 100644 index 0000000000000..71cd0b98a68c2 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunctiondefinitions.md @@ -0,0 +1,26 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionFunctionDefinitions](./kibana-plugin-plugins-expressions-server.expressionfunctiondefinitions.md) + +## ExpressionFunctionDefinitions interface + +A mapping of `ExpressionFunctionDefinition`s for functions which the Expressions services provides out-of-the-box. Any new functions registered by the Expressions plugin should have their types added here. + +Signature: + +```typescript +export interface ExpressionFunctionDefinitions +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [clog](./kibana-plugin-plugins-expressions-server.expressionfunctiondefinitions.clog.md) | ExpressionFunctionClog | | +| [font](./kibana-plugin-plugins-expressions-server.expressionfunctiondefinitions.font.md) | ExpressionFunctionFont | | +| [kibana\_context](./kibana-plugin-plugins-expressions-server.expressionfunctiondefinitions.kibana_context.md) | ExpressionFunctionKibanaContext | | +| [kibana](./kibana-plugin-plugins-expressions-server.expressionfunctiondefinitions.kibana.md) | ExpressionFunctionKibana | | +| [theme](./kibana-plugin-plugins-expressions-server.expressionfunctiondefinitions.theme.md) | ExpressionFunctionTheme | | +| [var\_set](./kibana-plugin-plugins-expressions-server.expressionfunctiondefinitions.var_set.md) | ExpressionFunctionVarSet | | +| [var](./kibana-plugin-plugins-expressions-server.expressionfunctiondefinitions.var.md) | ExpressionFunctionVar | | + diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunctiondefinitions.theme.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunctiondefinitions.theme.md new file mode 100644 index 0000000000000..98291fe35c1aa --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunctiondefinitions.theme.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionFunctionDefinitions](./kibana-plugin-plugins-expressions-server.expressionfunctiondefinitions.md) > [theme](./kibana-plugin-plugins-expressions-server.expressionfunctiondefinitions.theme.md) + +## ExpressionFunctionDefinitions.theme property + +Signature: + +```typescript +theme: ExpressionFunctionTheme; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunctiondefinitions.var.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunctiondefinitions.var.md new file mode 100644 index 0000000000000..55d576193ba9c --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunctiondefinitions.var.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionFunctionDefinitions](./kibana-plugin-plugins-expressions-server.expressionfunctiondefinitions.md) > [var](./kibana-plugin-plugins-expressions-server.expressionfunctiondefinitions.var.md) + +## ExpressionFunctionDefinitions.var property + +Signature: + +```typescript +var: ExpressionFunctionVar; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunctiondefinitions.var_set.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunctiondefinitions.var_set.md new file mode 100644 index 0000000000000..3163cf1accab1 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunctiondefinitions.var_set.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionFunctionDefinitions](./kibana-plugin-plugins-expressions-server.expressionfunctiondefinitions.md) > [var\_set](./kibana-plugin-plugins-expressions-server.expressionfunctiondefinitions.var_set.md) + +## ExpressionFunctionDefinitions.var\_set property + +Signature: + +```typescript +var_set: ExpressionFunctionVarSet; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunctionkibana.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunctionkibana.md new file mode 100644 index 0000000000000..aac2ae1c3ca4e --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunctionkibana.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionFunctionKibana](./kibana-plugin-plugins-expressions-server.expressionfunctionkibana.md) + +## ExpressionFunctionKibana type + +Signature: + +```typescript +export declare type ExpressionFunctionKibana = ExpressionFunctionDefinition<'kibana', ExpressionValueSearchContext | null, object, ExpressionValueSearchContext>; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunctionparameter._constructor_.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunctionparameter._constructor_.md new file mode 100644 index 0000000000000..a9ad2069cfe15 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunctionparameter._constructor_.md @@ -0,0 +1,21 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionFunctionParameter](./kibana-plugin-plugins-expressions-server.expressionfunctionparameter.md) > [(constructor)](./kibana-plugin-plugins-expressions-server.expressionfunctionparameter._constructor_.md) + +## ExpressionFunctionParameter.(constructor) + +Constructs a new instance of the `ExpressionFunctionParameter` class + +Signature: + +```typescript +constructor(name: string, arg: ArgumentType); +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| name | string | | +| arg | ArgumentType<any> | | + diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunctionparameter.accepts.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunctionparameter.accepts.md new file mode 100644 index 0000000000000..083bbdf1da4e7 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunctionparameter.accepts.md @@ -0,0 +1,22 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionFunctionParameter](./kibana-plugin-plugins-expressions-server.expressionfunctionparameter.md) > [accepts](./kibana-plugin-plugins-expressions-server.expressionfunctionparameter.accepts.md) + +## ExpressionFunctionParameter.accepts() method + +Signature: + +```typescript +accepts(type: string): boolean; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| type | string | | + +Returns: + +`boolean` + diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunctionparameter.aliases.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunctionparameter.aliases.md new file mode 100644 index 0000000000000..c7d27a48bdad5 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunctionparameter.aliases.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionFunctionParameter](./kibana-plugin-plugins-expressions-server.expressionfunctionparameter.md) > [aliases](./kibana-plugin-plugins-expressions-server.expressionfunctionparameter.aliases.md) + +## ExpressionFunctionParameter.aliases property + +Signature: + +```typescript +aliases: string[]; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunctionparameter.default.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunctionparameter.default.md new file mode 100644 index 0000000000000..d4105febffe86 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunctionparameter.default.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionFunctionParameter](./kibana-plugin-plugins-expressions-server.expressionfunctionparameter.md) > [default](./kibana-plugin-plugins-expressions-server.expressionfunctionparameter.default.md) + +## ExpressionFunctionParameter.default property + +Signature: + +```typescript +default: any; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunctionparameter.help.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunctionparameter.help.md new file mode 100644 index 0000000000000..b21626df64121 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunctionparameter.help.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionFunctionParameter](./kibana-plugin-plugins-expressions-server.expressionfunctionparameter.md) > [help](./kibana-plugin-plugins-expressions-server.expressionfunctionparameter.help.md) + +## ExpressionFunctionParameter.help property + +Signature: + +```typescript +help: string; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunctionparameter.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunctionparameter.md new file mode 100644 index 0000000000000..e9e35183e4e76 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunctionparameter.md @@ -0,0 +1,38 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionFunctionParameter](./kibana-plugin-plugins-expressions-server.expressionfunctionparameter.md) + +## ExpressionFunctionParameter class + +Signature: + +```typescript +export declare class ExpressionFunctionParameter +``` + +## Constructors + +| Constructor | Modifiers | Description | +| --- | --- | --- | +| [(constructor)(name, arg)](./kibana-plugin-plugins-expressions-server.expressionfunctionparameter._constructor_.md) | | Constructs a new instance of the ExpressionFunctionParameter class | + +## Properties + +| Property | Modifiers | Type | Description | +| --- | --- | --- | --- | +| [aliases](./kibana-plugin-plugins-expressions-server.expressionfunctionparameter.aliases.md) | | string[] | | +| [default](./kibana-plugin-plugins-expressions-server.expressionfunctionparameter.default.md) | | any | | +| [help](./kibana-plugin-plugins-expressions-server.expressionfunctionparameter.help.md) | | string | | +| [multi](./kibana-plugin-plugins-expressions-server.expressionfunctionparameter.multi.md) | | boolean | | +| [name](./kibana-plugin-plugins-expressions-server.expressionfunctionparameter.name.md) | | string | | +| [options](./kibana-plugin-plugins-expressions-server.expressionfunctionparameter.options.md) | | any[] | | +| [required](./kibana-plugin-plugins-expressions-server.expressionfunctionparameter.required.md) | | boolean | | +| [resolve](./kibana-plugin-plugins-expressions-server.expressionfunctionparameter.resolve.md) | | boolean | | +| [types](./kibana-plugin-plugins-expressions-server.expressionfunctionparameter.types.md) | | string[] | | + +## Methods + +| Method | Modifiers | Description | +| --- | --- | --- | +| [accepts(type)](./kibana-plugin-plugins-expressions-server.expressionfunctionparameter.accepts.md) | | | + diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunctionparameter.multi.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunctionparameter.multi.md new file mode 100644 index 0000000000000..86e1921910a30 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunctionparameter.multi.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionFunctionParameter](./kibana-plugin-plugins-expressions-server.expressionfunctionparameter.md) > [multi](./kibana-plugin-plugins-expressions-server.expressionfunctionparameter.multi.md) + +## ExpressionFunctionParameter.multi property + +Signature: + +```typescript +multi: boolean; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunctionparameter.name.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunctionparameter.name.md new file mode 100644 index 0000000000000..8aab81d92e65a --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunctionparameter.name.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionFunctionParameter](./kibana-plugin-plugins-expressions-server.expressionfunctionparameter.md) > [name](./kibana-plugin-plugins-expressions-server.expressionfunctionparameter.name.md) + +## ExpressionFunctionParameter.name property + +Signature: + +```typescript +name: string; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunctionparameter.options.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunctionparameter.options.md new file mode 100644 index 0000000000000..95369ebd5ce88 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunctionparameter.options.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionFunctionParameter](./kibana-plugin-plugins-expressions-server.expressionfunctionparameter.md) > [options](./kibana-plugin-plugins-expressions-server.expressionfunctionparameter.options.md) + +## ExpressionFunctionParameter.options property + +Signature: + +```typescript +options: any[]; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunctionparameter.required.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunctionparameter.required.md new file mode 100644 index 0000000000000..0e58b41e2a22c --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunctionparameter.required.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionFunctionParameter](./kibana-plugin-plugins-expressions-server.expressionfunctionparameter.md) > [required](./kibana-plugin-plugins-expressions-server.expressionfunctionparameter.required.md) + +## ExpressionFunctionParameter.required property + +Signature: + +```typescript +required: boolean; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunctionparameter.resolve.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunctionparameter.resolve.md new file mode 100644 index 0000000000000..3415c5f6a7639 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunctionparameter.resolve.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionFunctionParameter](./kibana-plugin-plugins-expressions-server.expressionfunctionparameter.md) > [resolve](./kibana-plugin-plugins-expressions-server.expressionfunctionparameter.resolve.md) + +## ExpressionFunctionParameter.resolve property + +Signature: + +```typescript +resolve: boolean; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunctionparameter.types.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunctionparameter.types.md new file mode 100644 index 0000000000000..f7d6079705e8e --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunctionparameter.types.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionFunctionParameter](./kibana-plugin-plugins-expressions-server.expressionfunctionparameter.md) > [types](./kibana-plugin-plugins-expressions-server.expressionfunctionparameter.types.md) + +## ExpressionFunctionParameter.types property + +Signature: + +```typescript +types: string[]; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionimage.dataurl.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionimage.dataurl.md new file mode 100644 index 0000000000000..a51dc1eaea66f --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionimage.dataurl.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionImage](./kibana-plugin-plugins-expressions-server.expressionimage.md) > [dataurl](./kibana-plugin-plugins-expressions-server.expressionimage.dataurl.md) + +## ExpressionImage.dataurl property + +Signature: + +```typescript +dataurl: string; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionimage.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionimage.md new file mode 100644 index 0000000000000..7f323fba7bfe1 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionimage.md @@ -0,0 +1,20 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionImage](./kibana-plugin-plugins-expressions-server.expressionimage.md) + +## ExpressionImage interface + +Signature: + +```typescript +export interface ExpressionImage +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [dataurl](./kibana-plugin-plugins-expressions-server.expressionimage.dataurl.md) | string | | +| [mode](./kibana-plugin-plugins-expressions-server.expressionimage.mode.md) | string | | +| [type](./kibana-plugin-plugins-expressions-server.expressionimage.type.md) | 'image' | | + diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionimage.mode.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionimage.mode.md new file mode 100644 index 0000000000000..9aae0ed3ea8b4 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionimage.mode.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionImage](./kibana-plugin-plugins-expressions-server.expressionimage.md) > [mode](./kibana-plugin-plugins-expressions-server.expressionimage.mode.md) + +## ExpressionImage.mode property + +Signature: + +```typescript +mode: string; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionimage.type.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionimage.type.md new file mode 100644 index 0000000000000..0cc0418228281 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionimage.type.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionImage](./kibana-plugin-plugins-expressions-server.expressionimage.md) > [type](./kibana-plugin-plugins-expressions-server.expressionimage.type.md) + +## ExpressionImage.type property + +Signature: + +```typescript +type: 'image'; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionrenderdefinition.displayname.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionrenderdefinition.displayname.md new file mode 100644 index 0000000000000..8ae5aa2f1790e --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionrenderdefinition.displayname.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionRenderDefinition](./kibana-plugin-plugins-expressions-server.expressionrenderdefinition.md) > [displayName](./kibana-plugin-plugins-expressions-server.expressionrenderdefinition.displayname.md) + +## ExpressionRenderDefinition.displayName property + +A user friendly name of the renderer as will be displayed to user in UI. + +Signature: + +```typescript +displayName?: string; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionrenderdefinition.help.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionrenderdefinition.help.md new file mode 100644 index 0000000000000..971abba04fdf9 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionrenderdefinition.help.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionRenderDefinition](./kibana-plugin-plugins-expressions-server.expressionrenderdefinition.md) > [help](./kibana-plugin-plugins-expressions-server.expressionrenderdefinition.help.md) + +## ExpressionRenderDefinition.help property + +Help text as will be displayed to user. A sentence or few about what this element does. + +Signature: + +```typescript +help?: string; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionrenderdefinition.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionrenderdefinition.md new file mode 100644 index 0000000000000..9cefb6ef196cf --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionrenderdefinition.md @@ -0,0 +1,23 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionRenderDefinition](./kibana-plugin-plugins-expressions-server.expressionrenderdefinition.md) + +## ExpressionRenderDefinition interface + +Signature: + +```typescript +export interface ExpressionRenderDefinition +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [displayName](./kibana-plugin-plugins-expressions-server.expressionrenderdefinition.displayname.md) | string | A user friendly name of the renderer as will be displayed to user in UI. | +| [help](./kibana-plugin-plugins-expressions-server.expressionrenderdefinition.help.md) | string | Help text as will be displayed to user. A sentence or few about what this element does. | +| [name](./kibana-plugin-plugins-expressions-server.expressionrenderdefinition.name.md) | string | Technical name of the renderer, used as ID to identify renderer in expression renderer registry. This must match the name of the expression function that is used to create the type: render object. | +| [render](./kibana-plugin-plugins-expressions-server.expressionrenderdefinition.render.md) | (domNode: HTMLElement, config: Config, handlers: IInterpreterRenderHandlers) => void | Promise<void> | The function called to render the output data of an expression. | +| [reuseDomNode](./kibana-plugin-plugins-expressions-server.expressionrenderdefinition.reusedomnode.md) | boolean | Tell the renderer if the dom node should be reused, it's recreated each time by default. | +| [validate](./kibana-plugin-plugins-expressions-server.expressionrenderdefinition.validate.md) | () => undefined | Error | Used to validate the data before calling the render function. | + diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionrenderdefinition.name.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionrenderdefinition.name.md new file mode 100644 index 0000000000000..62eec0109c374 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionrenderdefinition.name.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionRenderDefinition](./kibana-plugin-plugins-expressions-server.expressionrenderdefinition.md) > [name](./kibana-plugin-plugins-expressions-server.expressionrenderdefinition.name.md) + +## ExpressionRenderDefinition.name property + +Technical name of the renderer, used as ID to identify renderer in expression renderer registry. This must match the name of the expression function that is used to create the `type: render` object. + +Signature: + +```typescript +name: string; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionrenderdefinition.render.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionrenderdefinition.render.md new file mode 100644 index 0000000000000..99698e1828637 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionrenderdefinition.render.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionRenderDefinition](./kibana-plugin-plugins-expressions-server.expressionrenderdefinition.md) > [render](./kibana-plugin-plugins-expressions-server.expressionrenderdefinition.render.md) + +## ExpressionRenderDefinition.render property + +The function called to render the output data of an expression. + +Signature: + +```typescript +render: (domNode: HTMLElement, config: Config, handlers: IInterpreterRenderHandlers) => void | Promise; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionrenderdefinition.reusedomnode.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionrenderdefinition.reusedomnode.md new file mode 100644 index 0000000000000..435920cccc642 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionrenderdefinition.reusedomnode.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionRenderDefinition](./kibana-plugin-plugins-expressions-server.expressionrenderdefinition.md) > [reuseDomNode](./kibana-plugin-plugins-expressions-server.expressionrenderdefinition.reusedomnode.md) + +## ExpressionRenderDefinition.reuseDomNode property + +Tell the renderer if the dom node should be reused, it's recreated each time by default. + +Signature: + +```typescript +reuseDomNode: boolean; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionrenderdefinition.validate.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionrenderdefinition.validate.md new file mode 100644 index 0000000000000..f640744374eda --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionrenderdefinition.validate.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionRenderDefinition](./kibana-plugin-plugins-expressions-server.expressionrenderdefinition.md) > [validate](./kibana-plugin-plugins-expressions-server.expressionrenderdefinition.validate.md) + +## ExpressionRenderDefinition.validate property + +Used to validate the data before calling the render function. + +Signature: + +```typescript +validate?: () => undefined | Error; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionrenderer._constructor_.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionrenderer._constructor_.md new file mode 100644 index 0000000000000..5db39853728af --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionrenderer._constructor_.md @@ -0,0 +1,20 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionRenderer](./kibana-plugin-plugins-expressions-server.expressionrenderer.md) > [(constructor)](./kibana-plugin-plugins-expressions-server.expressionrenderer._constructor_.md) + +## ExpressionRenderer.(constructor) + +Constructs a new instance of the `ExpressionRenderer` class + +Signature: + +```typescript +constructor(config: ExpressionRenderDefinition); +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| config | ExpressionRenderDefinition<Config> | | + diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionrenderer.displayname.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionrenderer.displayname.md new file mode 100644 index 0000000000000..41846bf41997f --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionrenderer.displayname.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionRenderer](./kibana-plugin-plugins-expressions-server.expressionrenderer.md) > [displayName](./kibana-plugin-plugins-expressions-server.expressionrenderer.displayname.md) + +## ExpressionRenderer.displayName property + +Signature: + +```typescript +readonly displayName: string; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionrenderer.help.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionrenderer.help.md new file mode 100644 index 0000000000000..9cf60c832fb95 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionrenderer.help.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionRenderer](./kibana-plugin-plugins-expressions-server.expressionrenderer.md) > [help](./kibana-plugin-plugins-expressions-server.expressionrenderer.help.md) + +## ExpressionRenderer.help property + +Signature: + +```typescript +readonly help: string; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionrenderer.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionrenderer.md new file mode 100644 index 0000000000000..6f5c336a89e5c --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionrenderer.md @@ -0,0 +1,29 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionRenderer](./kibana-plugin-plugins-expressions-server.expressionrenderer.md) + +## ExpressionRenderer class + +Signature: + +```typescript +export declare class ExpressionRenderer +``` + +## Constructors + +| Constructor | Modifiers | Description | +| --- | --- | --- | +| [(constructor)(config)](./kibana-plugin-plugins-expressions-server.expressionrenderer._constructor_.md) | | Constructs a new instance of the ExpressionRenderer class | + +## Properties + +| Property | Modifiers | Type | Description | +| --- | --- | --- | --- | +| [displayName](./kibana-plugin-plugins-expressions-server.expressionrenderer.displayname.md) | | string | | +| [help](./kibana-plugin-plugins-expressions-server.expressionrenderer.help.md) | | string | | +| [name](./kibana-plugin-plugins-expressions-server.expressionrenderer.name.md) | | string | | +| [render](./kibana-plugin-plugins-expressions-server.expressionrenderer.render.md) | | ExpressionRenderDefinition<Config>['render'] | | +| [reuseDomNode](./kibana-plugin-plugins-expressions-server.expressionrenderer.reusedomnode.md) | | boolean | | +| [validate](./kibana-plugin-plugins-expressions-server.expressionrenderer.validate.md) | | () => void | Error | | + diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionrenderer.name.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionrenderer.name.md new file mode 100644 index 0000000000000..f320fcd8408ab --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionrenderer.name.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionRenderer](./kibana-plugin-plugins-expressions-server.expressionrenderer.md) > [name](./kibana-plugin-plugins-expressions-server.expressionrenderer.name.md) + +## ExpressionRenderer.name property + +Signature: + +```typescript +readonly name: string; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionrenderer.render.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionrenderer.render.md new file mode 100644 index 0000000000000..d7cf04e6d8bfa --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionrenderer.render.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionRenderer](./kibana-plugin-plugins-expressions-server.expressionrenderer.md) > [render](./kibana-plugin-plugins-expressions-server.expressionrenderer.render.md) + +## ExpressionRenderer.render property + +Signature: + +```typescript +readonly render: ExpressionRenderDefinition['render']; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionrenderer.reusedomnode.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionrenderer.reusedomnode.md new file mode 100644 index 0000000000000..8fd9c5fa8e6ff --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionrenderer.reusedomnode.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionRenderer](./kibana-plugin-plugins-expressions-server.expressionrenderer.md) > [reuseDomNode](./kibana-plugin-plugins-expressions-server.expressionrenderer.reusedomnode.md) + +## ExpressionRenderer.reuseDomNode property + +Signature: + +```typescript +readonly reuseDomNode: boolean; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionrenderer.validate.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionrenderer.validate.md new file mode 100644 index 0000000000000..d40945cfb88f1 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionrenderer.validate.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionRenderer](./kibana-plugin-plugins-expressions-server.expressionrenderer.md) > [validate](./kibana-plugin-plugins-expressions-server.expressionrenderer.validate.md) + +## ExpressionRenderer.validate property + +Signature: + +```typescript +readonly validate: () => void | Error; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionrendererregistry.get.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionrendererregistry.get.md new file mode 100644 index 0000000000000..6f8e6c868ac9b --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionrendererregistry.get.md @@ -0,0 +1,22 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionRendererRegistry](./kibana-plugin-plugins-expressions-server.expressionrendererregistry.md) > [get](./kibana-plugin-plugins-expressions-server.expressionrendererregistry.get.md) + +## ExpressionRendererRegistry.get() method + +Signature: + +```typescript +get(id: string): ExpressionRenderer | null; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| id | string | | + +Returns: + +`ExpressionRenderer | null` + diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionrendererregistry.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionrendererregistry.md new file mode 100644 index 0000000000000..d4a34ab140854 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionrendererregistry.md @@ -0,0 +1,21 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionRendererRegistry](./kibana-plugin-plugins-expressions-server.expressionrendererregistry.md) + +## ExpressionRendererRegistry class + +Signature: + +```typescript +export declare class ExpressionRendererRegistry implements IRegistry +``` + +## Methods + +| Method | Modifiers | Description | +| --- | --- | --- | +| [get(id)](./kibana-plugin-plugins-expressions-server.expressionrendererregistry.get.md) | | | +| [register(definition)](./kibana-plugin-plugins-expressions-server.expressionrendererregistry.register.md) | | | +| [toArray()](./kibana-plugin-plugins-expressions-server.expressionrendererregistry.toarray.md) | | | +| [toJS()](./kibana-plugin-plugins-expressions-server.expressionrendererregistry.tojs.md) | | | + diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionrendererregistry.register.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionrendererregistry.register.md new file mode 100644 index 0000000000000..d5411a327fbcd --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionrendererregistry.register.md @@ -0,0 +1,22 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionRendererRegistry](./kibana-plugin-plugins-expressions-server.expressionrendererregistry.md) > [register](./kibana-plugin-plugins-expressions-server.expressionrendererregistry.register.md) + +## ExpressionRendererRegistry.register() method + +Signature: + +```typescript +register(definition: AnyExpressionRenderDefinition | (() => AnyExpressionRenderDefinition)): void; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| definition | AnyExpressionRenderDefinition | (() => AnyExpressionRenderDefinition) | | + +Returns: + +`void` + diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionrendererregistry.toarray.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionrendererregistry.toarray.md new file mode 100644 index 0000000000000..edb153000b458 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionrendererregistry.toarray.md @@ -0,0 +1,15 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionRendererRegistry](./kibana-plugin-plugins-expressions-server.expressionrendererregistry.md) > [toArray](./kibana-plugin-plugins-expressions-server.expressionrendererregistry.toarray.md) + +## ExpressionRendererRegistry.toArray() method + +Signature: + +```typescript +toArray(): ExpressionRenderer[]; +``` +Returns: + +`ExpressionRenderer[]` + diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionrendererregistry.tojs.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionrendererregistry.tojs.md new file mode 100644 index 0000000000000..f7230e9102c8f --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionrendererregistry.tojs.md @@ -0,0 +1,15 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionRendererRegistry](./kibana-plugin-plugins-expressions-server.expressionrendererregistry.md) > [toJS](./kibana-plugin-plugins-expressions-server.expressionrendererregistry.tojs.md) + +## ExpressionRendererRegistry.toJS() method + +Signature: + +```typescript +toJS(): Record; +``` +Returns: + +`Record` + diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionsserverplugin._constructor_.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionsserverplugin._constructor_.md new file mode 100644 index 0000000000000..639ae379f0ed7 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionsserverplugin._constructor_.md @@ -0,0 +1,20 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionsServerPlugin](./kibana-plugin-plugins-expressions-server.expressionsserverplugin.md) > [(constructor)](./kibana-plugin-plugins-expressions-server.expressionsserverplugin._constructor_.md) + +## ExpressionsServerPlugin.(constructor) + +Constructs a new instance of the `ExpressionsServerPlugin` class + +Signature: + +```typescript +constructor(initializerContext: PluginInitializerContext); +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| initializerContext | PluginInitializerContext | | + diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionsserverplugin.expressions.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionsserverplugin.expressions.md new file mode 100644 index 0000000000000..a391220a6349e --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionsserverplugin.expressions.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionsServerPlugin](./kibana-plugin-plugins-expressions-server.expressionsserverplugin.md) > [expressions](./kibana-plugin-plugins-expressions-server.expressionsserverplugin.expressions.md) + +## ExpressionsServerPlugin.expressions property + +Signature: + +```typescript +readonly expressions: ExpressionsService; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionsserverplugin.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionsserverplugin.md new file mode 100644 index 0000000000000..f92d572b1111a --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionsserverplugin.md @@ -0,0 +1,32 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionsServerPlugin](./kibana-plugin-plugins-expressions-server.expressionsserverplugin.md) + +## ExpressionsServerPlugin class + +Signature: + +```typescript +export declare class ExpressionsServerPlugin implements Plugin +``` + +## Constructors + +| Constructor | Modifiers | Description | +| --- | --- | --- | +| [(constructor)(initializerContext)](./kibana-plugin-plugins-expressions-server.expressionsserverplugin._constructor_.md) | | Constructs a new instance of the ExpressionsServerPlugin class | + +## Properties + +| Property | Modifiers | Type | Description | +| --- | --- | --- | --- | +| [expressions](./kibana-plugin-plugins-expressions-server.expressionsserverplugin.expressions.md) | | ExpressionsService | | + +## Methods + +| Method | Modifiers | Description | +| --- | --- | --- | +| [setup(core)](./kibana-plugin-plugins-expressions-server.expressionsserverplugin.setup.md) | | | +| [start(core)](./kibana-plugin-plugins-expressions-server.expressionsserverplugin.start.md) | | | +| [stop()](./kibana-plugin-plugins-expressions-server.expressionsserverplugin.stop.md) | | | + diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionsserverplugin.setup.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionsserverplugin.setup.md new file mode 100644 index 0000000000000..18e33d4e0bc60 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionsserverplugin.setup.md @@ -0,0 +1,22 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionsServerPlugin](./kibana-plugin-plugins-expressions-server.expressionsserverplugin.md) > [setup](./kibana-plugin-plugins-expressions-server.expressionsserverplugin.setup.md) + +## ExpressionsServerPlugin.setup() method + +Signature: + +```typescript +setup(core: CoreSetup): ExpressionsServerSetup; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| core | CoreSetup | | + +Returns: + +`ExpressionsServerSetup` + diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionsserverplugin.start.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionsserverplugin.start.md new file mode 100644 index 0000000000000..31578685ff386 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionsserverplugin.start.md @@ -0,0 +1,22 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionsServerPlugin](./kibana-plugin-plugins-expressions-server.expressionsserverplugin.md) > [start](./kibana-plugin-plugins-expressions-server.expressionsserverplugin.start.md) + +## ExpressionsServerPlugin.start() method + +Signature: + +```typescript +start(core: CoreStart): ExpressionsServerStart; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| core | CoreStart | | + +Returns: + +`ExpressionsServerStart` + diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionsserverplugin.stop.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionsserverplugin.stop.md new file mode 100644 index 0000000000000..2f6abade901b1 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionsserverplugin.stop.md @@ -0,0 +1,15 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionsServerPlugin](./kibana-plugin-plugins-expressions-server.expressionsserverplugin.md) > [stop](./kibana-plugin-plugins-expressions-server.expressionsserverplugin.stop.md) + +## ExpressionsServerPlugin.stop() method + +Signature: + +```typescript +stop(): void; +``` +Returns: + +`void` + diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionsserversetup.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionsserversetup.md new file mode 100644 index 0000000000000..2cf591a59c4f6 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionsserversetup.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionsServerSetup](./kibana-plugin-plugins-expressions-server.expressionsserversetup.md) + +## ExpressionsServerSetup type + +Signature: + +```typescript +export declare type ExpressionsServerSetup = ExpressionsServiceSetup; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionsserverstart.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionsserverstart.md new file mode 100644 index 0000000000000..9ceb261a7f689 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionsserverstart.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionsServerStart](./kibana-plugin-plugins-expressions-server.expressionsserverstart.md) + +## ExpressionsServerStart type + +Signature: + +```typescript +export declare type ExpressionsServerStart = ExpressionsServiceStart; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressiontype._constructor_.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressiontype._constructor_.md new file mode 100644 index 0000000000000..966955c03ff08 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressiontype._constructor_.md @@ -0,0 +1,20 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionType](./kibana-plugin-plugins-expressions-server.expressiontype.md) > [(constructor)](./kibana-plugin-plugins-expressions-server.expressiontype._constructor_.md) + +## ExpressionType.(constructor) + +Constructs a new instance of the `ExpressionType` class + +Signature: + +```typescript +constructor(definition: AnyExpressionTypeDefinition); +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| definition | AnyExpressionTypeDefinition | | + diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressiontype.castsfrom.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressiontype.castsfrom.md new file mode 100644 index 0000000000000..57758e8fa7788 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressiontype.castsfrom.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionType](./kibana-plugin-plugins-expressions-server.expressiontype.md) > [castsFrom](./kibana-plugin-plugins-expressions-server.expressiontype.castsfrom.md) + +## ExpressionType.castsFrom property + +Signature: + +```typescript +castsFrom: (value: ExpressionValue) => boolean; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressiontype.caststo.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressiontype.caststo.md new file mode 100644 index 0000000000000..eec17f8606817 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressiontype.caststo.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionType](./kibana-plugin-plugins-expressions-server.expressiontype.md) > [castsTo](./kibana-plugin-plugins-expressions-server.expressiontype.caststo.md) + +## ExpressionType.castsTo property + +Signature: + +```typescript +castsTo: (value: ExpressionValue) => boolean; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressiontype.create.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressiontype.create.md new file mode 100644 index 0000000000000..3fbd1f7986254 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressiontype.create.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionType](./kibana-plugin-plugins-expressions-server.expressiontype.md) > [create](./kibana-plugin-plugins-expressions-server.expressiontype.create.md) + +## ExpressionType.create property + +Signature: + +```typescript +create: unknown; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressiontype.deserialize.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressiontype.deserialize.md new file mode 100644 index 0000000000000..232d70b846092 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressiontype.deserialize.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionType](./kibana-plugin-plugins-expressions-server.expressiontype.md) > [deserialize](./kibana-plugin-plugins-expressions-server.expressiontype.deserialize.md) + +## ExpressionType.deserialize property + +Signature: + +```typescript +deserialize?: (serialized: any) => ExpressionValue; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressiontype.from.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressiontype.from.md new file mode 100644 index 0000000000000..4d24a4162c096 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressiontype.from.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionType](./kibana-plugin-plugins-expressions-server.expressiontype.md) > [from](./kibana-plugin-plugins-expressions-server.expressiontype.from.md) + +## ExpressionType.from property + +Signature: + +```typescript +from: (value: ExpressionValue, types: Record) => any; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressiontype.getfromfn.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressiontype.getfromfn.md new file mode 100644 index 0000000000000..092227af92a19 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressiontype.getfromfn.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionType](./kibana-plugin-plugins-expressions-server.expressiontype.md) > [getFromFn](./kibana-plugin-plugins-expressions-server.expressiontype.getfromfn.md) + +## ExpressionType.getFromFn property + +Signature: + +```typescript +getFromFn: (typeName: string) => undefined | ExpressionValueConverter; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressiontype.gettofn.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressiontype.gettofn.md new file mode 100644 index 0000000000000..8454116f50ac8 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressiontype.gettofn.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionType](./kibana-plugin-plugins-expressions-server.expressiontype.md) > [getToFn](./kibana-plugin-plugins-expressions-server.expressiontype.gettofn.md) + +## ExpressionType.getToFn property + +Signature: + +```typescript +getToFn: (typeName: string) => undefined | ExpressionValueConverter; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressiontype.help.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressiontype.help.md new file mode 100644 index 0000000000000..bd5be7329d6a4 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressiontype.help.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionType](./kibana-plugin-plugins-expressions-server.expressiontype.md) > [help](./kibana-plugin-plugins-expressions-server.expressiontype.help.md) + +## ExpressionType.help property + +A short help text. + +Signature: + +```typescript +help: string; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressiontype.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressiontype.md new file mode 100644 index 0000000000000..49f3f504c9419 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressiontype.md @@ -0,0 +1,35 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionType](./kibana-plugin-plugins-expressions-server.expressiontype.md) + +## ExpressionType class + +Signature: + +```typescript +export declare class ExpressionType +``` + +## Constructors + +| Constructor | Modifiers | Description | +| --- | --- | --- | +| [(constructor)(definition)](./kibana-plugin-plugins-expressions-server.expressiontype._constructor_.md) | | Constructs a new instance of the ExpressionType class | + +## Properties + +| Property | Modifiers | Type | Description | +| --- | --- | --- | --- | +| [castsFrom](./kibana-plugin-plugins-expressions-server.expressiontype.castsfrom.md) | | (value: ExpressionValue) => boolean | | +| [castsTo](./kibana-plugin-plugins-expressions-server.expressiontype.caststo.md) | | (value: ExpressionValue) => boolean | | +| [create](./kibana-plugin-plugins-expressions-server.expressiontype.create.md) | | unknown | | +| [deserialize](./kibana-plugin-plugins-expressions-server.expressiontype.deserialize.md) | | (serialized: any) => ExpressionValue | | +| [from](./kibana-plugin-plugins-expressions-server.expressiontype.from.md) | | (value: ExpressionValue, types: Record<string, ExpressionType>) => any | | +| [getFromFn](./kibana-plugin-plugins-expressions-server.expressiontype.getfromfn.md) | | (typeName: string) => undefined | ExpressionValueConverter<ExpressionValue, ExpressionValue> | | +| [getToFn](./kibana-plugin-plugins-expressions-server.expressiontype.gettofn.md) | | (typeName: string) => undefined | ExpressionValueConverter<ExpressionValue, ExpressionValue> | | +| [help](./kibana-plugin-plugins-expressions-server.expressiontype.help.md) | | string | A short help text. | +| [name](./kibana-plugin-plugins-expressions-server.expressiontype.name.md) | | string | | +| [serialize](./kibana-plugin-plugins-expressions-server.expressiontype.serialize.md) | | (value: ExpressionValue) => any | Optional serialization (used when passing context around client/server). | +| [to](./kibana-plugin-plugins-expressions-server.expressiontype.to.md) | | (value: ExpressionValue, toTypeName: string, types: Record<string, ExpressionType>) => any | | +| [validate](./kibana-plugin-plugins-expressions-server.expressiontype.validate.md) | | (type: any) => void | Error | Type validation, useful for checking function output. | + diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressiontype.name.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressiontype.name.md new file mode 100644 index 0000000000000..44e0e18270b14 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressiontype.name.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionType](./kibana-plugin-plugins-expressions-server.expressiontype.md) > [name](./kibana-plugin-plugins-expressions-server.expressiontype.name.md) + +## ExpressionType.name property + +Signature: + +```typescript +name: string; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressiontype.serialize.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressiontype.serialize.md new file mode 100644 index 0000000000000..013b95bf2d0ce --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressiontype.serialize.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionType](./kibana-plugin-plugins-expressions-server.expressiontype.md) > [serialize](./kibana-plugin-plugins-expressions-server.expressiontype.serialize.md) + +## ExpressionType.serialize property + +Optional serialization (used when passing context around client/server). + +Signature: + +```typescript +serialize?: (value: ExpressionValue) => any; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressiontype.to.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressiontype.to.md new file mode 100644 index 0000000000000..70e4504324f22 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressiontype.to.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionType](./kibana-plugin-plugins-expressions-server.expressiontype.md) > [to](./kibana-plugin-plugins-expressions-server.expressiontype.to.md) + +## ExpressionType.to property + +Signature: + +```typescript +to: (value: ExpressionValue, toTypeName: string, types: Record) => any; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressiontype.validate.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressiontype.validate.md new file mode 100644 index 0000000000000..6e1fd681a732b --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressiontype.validate.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionType](./kibana-plugin-plugins-expressions-server.expressiontype.md) > [validate](./kibana-plugin-plugins-expressions-server.expressiontype.validate.md) + +## ExpressionType.validate property + +Type validation, useful for checking function output. + +Signature: + +```typescript +validate: (type: any) => void | Error; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressiontypedefinition.deserialize.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressiontypedefinition.deserialize.md new file mode 100644 index 0000000000000..71e9ecd7270d9 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressiontypedefinition.deserialize.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionTypeDefinition](./kibana-plugin-plugins-expressions-server.expressiontypedefinition.md) > [deserialize](./kibana-plugin-plugins-expressions-server.expressiontypedefinition.deserialize.md) + +## ExpressionTypeDefinition.deserialize property + +Signature: + +```typescript +deserialize?: (type: SerializedType) => Value; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressiontypedefinition.from.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressiontypedefinition.from.md new file mode 100644 index 0000000000000..f3ad8791c7bac --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressiontypedefinition.from.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionTypeDefinition](./kibana-plugin-plugins-expressions-server.expressiontypedefinition.md) > [from](./kibana-plugin-plugins-expressions-server.expressiontypedefinition.from.md) + +## ExpressionTypeDefinition.from property + +Signature: + +```typescript +from?: { + [type: string]: ExpressionValueConverter; + }; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressiontypedefinition.help.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressiontypedefinition.help.md new file mode 100644 index 0000000000000..f1c4d48599da6 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressiontypedefinition.help.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionTypeDefinition](./kibana-plugin-plugins-expressions-server.expressiontypedefinition.md) > [help](./kibana-plugin-plugins-expressions-server.expressiontypedefinition.help.md) + +## ExpressionTypeDefinition.help property + +Signature: + +```typescript +help?: string; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressiontypedefinition.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressiontypedefinition.md new file mode 100644 index 0000000000000..5179bd1df7311 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressiontypedefinition.md @@ -0,0 +1,26 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionTypeDefinition](./kibana-plugin-plugins-expressions-server.expressiontypedefinition.md) + +## ExpressionTypeDefinition interface + +A generic type which represents a custom Expression Type Definition that's registered to the Interpreter. + +Signature: + +```typescript +export interface ExpressionTypeDefinition +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [deserialize](./kibana-plugin-plugins-expressions-server.expressiontypedefinition.deserialize.md) | (type: SerializedType) => Value | | +| [from](./kibana-plugin-plugins-expressions-server.expressiontypedefinition.from.md) | {
    [type: string]: ExpressionValueConverter<any, Value>;
    } | | +| [help](./kibana-plugin-plugins-expressions-server.expressiontypedefinition.help.md) | string | | +| [name](./kibana-plugin-plugins-expressions-server.expressiontypedefinition.name.md) | Name | | +| [serialize](./kibana-plugin-plugins-expressions-server.expressiontypedefinition.serialize.md) | (type: Value) => SerializedType | | +| [to](./kibana-plugin-plugins-expressions-server.expressiontypedefinition.to.md) | {
    [type: string]: ExpressionValueConverter<Value, any>;
    } | | +| [validate](./kibana-plugin-plugins-expressions-server.expressiontypedefinition.validate.md) | (type: any) => void | Error | | + diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressiontypedefinition.name.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressiontypedefinition.name.md new file mode 100644 index 0000000000000..cfc1cebac16da --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressiontypedefinition.name.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionTypeDefinition](./kibana-plugin-plugins-expressions-server.expressiontypedefinition.md) > [name](./kibana-plugin-plugins-expressions-server.expressiontypedefinition.name.md) + +## ExpressionTypeDefinition.name property + +Signature: + +```typescript +name: Name; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressiontypedefinition.serialize.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressiontypedefinition.serialize.md new file mode 100644 index 0000000000000..05ec569f62638 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressiontypedefinition.serialize.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionTypeDefinition](./kibana-plugin-plugins-expressions-server.expressiontypedefinition.md) > [serialize](./kibana-plugin-plugins-expressions-server.expressiontypedefinition.serialize.md) + +## ExpressionTypeDefinition.serialize property + +Signature: + +```typescript +serialize?: (type: Value) => SerializedType; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressiontypedefinition.to.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressiontypedefinition.to.md new file mode 100644 index 0000000000000..6c2c22fc902c6 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressiontypedefinition.to.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionTypeDefinition](./kibana-plugin-plugins-expressions-server.expressiontypedefinition.md) > [to](./kibana-plugin-plugins-expressions-server.expressiontypedefinition.to.md) + +## ExpressionTypeDefinition.to property + +Signature: + +```typescript +to?: { + [type: string]: ExpressionValueConverter; + }; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressiontypedefinition.validate.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressiontypedefinition.validate.md new file mode 100644 index 0000000000000..acdcf089fcbe0 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressiontypedefinition.validate.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionTypeDefinition](./kibana-plugin-plugins-expressions-server.expressiontypedefinition.md) > [validate](./kibana-plugin-plugins-expressions-server.expressiontypedefinition.validate.md) + +## ExpressionTypeDefinition.validate property + +Signature: + +```typescript +validate?: (type: any) => void | Error; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressiontypestyle.css.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressiontypestyle.css.md new file mode 100644 index 0000000000000..7cb6e9bc8b45d --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressiontypestyle.css.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionTypeStyle](./kibana-plugin-plugins-expressions-server.expressiontypestyle.md) > [css](./kibana-plugin-plugins-expressions-server.expressiontypestyle.css.md) + +## ExpressionTypeStyle.css property + +Signature: + +```typescript +css: string; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressiontypestyle.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressiontypestyle.md new file mode 100644 index 0000000000000..274e9b7b6772c --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressiontypestyle.md @@ -0,0 +1,22 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionTypeStyle](./kibana-plugin-plugins-expressions-server.expressiontypestyle.md) + +## ExpressionTypeStyle interface + +An object that represents style information, typically CSS. + +Signature: + +```typescript +export interface ExpressionTypeStyle +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [css](./kibana-plugin-plugins-expressions-server.expressiontypestyle.css.md) | string | | +| [spec](./kibana-plugin-plugins-expressions-server.expressiontypestyle.spec.md) | CSSStyle | | +| [type](./kibana-plugin-plugins-expressions-server.expressiontypestyle.type.md) | 'style' | | + diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressiontypestyle.spec.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressiontypestyle.spec.md new file mode 100644 index 0000000000000..95f3edbc2b725 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressiontypestyle.spec.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionTypeStyle](./kibana-plugin-plugins-expressions-server.expressiontypestyle.md) > [spec](./kibana-plugin-plugins-expressions-server.expressiontypestyle.spec.md) + +## ExpressionTypeStyle.spec property + +Signature: + +```typescript +spec: CSSStyle; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressiontypestyle.type.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressiontypestyle.type.md new file mode 100644 index 0000000000000..be3b476cb8b53 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressiontypestyle.type.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionTypeStyle](./kibana-plugin-plugins-expressions-server.expressiontypestyle.md) > [type](./kibana-plugin-plugins-expressions-server.expressiontypestyle.type.md) + +## ExpressionTypeStyle.type property + +Signature: + +```typescript +type: 'style'; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionvalue.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionvalue.md new file mode 100644 index 0000000000000..fc9af5fbc6695 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionvalue.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionValue](./kibana-plugin-plugins-expressions-server.expressionvalue.md) + +## ExpressionValue type + +Signature: + +```typescript +export declare type ExpressionValue = ExpressionValueUnboxed | ExpressionValueBoxed; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionvalueboxed.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionvalueboxed.md new file mode 100644 index 0000000000000..ad84aec0dc6d5 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionvalueboxed.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionValueBoxed](./kibana-plugin-plugins-expressions-server.expressionvalueboxed.md) + +## ExpressionValueBoxed type + +Signature: + +```typescript +export declare type ExpressionValueBoxed = { + type: Type; +} & Value; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionvalueconverter.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionvalueconverter.md new file mode 100644 index 0000000000000..d1b69590141cb --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionvalueconverter.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionValueConverter](./kibana-plugin-plugins-expressions-server.expressionvalueconverter.md) + +## ExpressionValueConverter type + +Signature: + +```typescript +export declare type ExpressionValueConverter = (input: I, availableTypes: Record) => O; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionvalueerror.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionvalueerror.md new file mode 100644 index 0000000000000..b90e4360e055a --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionvalueerror.md @@ -0,0 +1,20 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionValueError](./kibana-plugin-plugins-expressions-server.expressionvalueerror.md) + +## ExpressionValueError type + +Signature: + +```typescript +export declare type ExpressionValueError = ExpressionValueBoxed<'error', { + error: { + message: string; + type?: string; + name?: string; + stack?: string; + original?: Error; + }; + info?: unknown; +}>; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionvaluefilter.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionvaluefilter.md new file mode 100644 index 0000000000000..fb65bc2550513 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionvaluefilter.md @@ -0,0 +1,21 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionValueFilter](./kibana-plugin-plugins-expressions-server.expressionvaluefilter.md) + +## ExpressionValueFilter type + +Represents an object that is a Filter. + +Signature: + +```typescript +export declare type ExpressionValueFilter = ExpressionValueBoxed<'filter', { + filterType?: string; + value?: string; + column?: string; + and: ExpressionValueFilter[]; + to?: string; + from?: string; + query?: string | null; +}>; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionvaluenum.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionvaluenum.md new file mode 100644 index 0000000000000..b109a23dc7259 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionvaluenum.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionValueNum](./kibana-plugin-plugins-expressions-server.expressionvaluenum.md) + +## ExpressionValueNum type + +Signature: + +```typescript +export declare type ExpressionValueNum = ExpressionValueBoxed<'num', { + value: number; +}>; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionvaluerender.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionvaluerender.md new file mode 100644 index 0000000000000..96958d753a78e --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionvaluerender.md @@ -0,0 +1,16 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionValueRender](./kibana-plugin-plugins-expressions-server.expressionvaluerender.md) + +## ExpressionValueRender type + +Represents an object that is intended to be rendered. + +Signature: + +```typescript +export declare type ExpressionValueRender = ExpressionValueBoxed; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionvaluesearchcontext.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionvaluesearchcontext.md new file mode 100644 index 0000000000000..6e38adde3ba91 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionvaluesearchcontext.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionValueSearchContext](./kibana-plugin-plugins-expressions-server.expressionvaluesearchcontext.md) + +## ExpressionValueSearchContext type + +Signature: + +```typescript +export declare type ExpressionValueSearchContext = ExpressionValueBoxed<'kibana_context', ExecutionContextSearch>; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionvalueunboxed.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionvalueunboxed.md new file mode 100644 index 0000000000000..2393b2bb70e6b --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionvalueunboxed.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [ExpressionValueUnboxed](./kibana-plugin-plugins-expressions-server.expressionvalueunboxed.md) + +## ExpressionValueUnboxed type + +Signature: + +```typescript +export declare type ExpressionValueUnboxed = any; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.font.label.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.font.label.md new file mode 100644 index 0000000000000..5f11f866be2f6 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.font.label.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [Font](./kibana-plugin-plugins-expressions-server.font.md) > [label](./kibana-plugin-plugins-expressions-server.font.label.md) + +## Font.label property + +Signature: + +```typescript +label: FontLabel; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.font.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.font.md new file mode 100644 index 0000000000000..f3ff25e034624 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.font.md @@ -0,0 +1,21 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [Font](./kibana-plugin-plugins-expressions-server.font.md) + +## Font interface + +An interface representing a font in Canvas, with a textual label and the CSS `font-value`. + +Signature: + +```typescript +export interface Font +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [label](./kibana-plugin-plugins-expressions-server.font.label.md) | FontLabel | | +| [value](./kibana-plugin-plugins-expressions-server.font.value.md) | FontValue | | + diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.font.value.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.font.value.md new file mode 100644 index 0000000000000..1bb1fac163661 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.font.value.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [Font](./kibana-plugin-plugins-expressions-server.font.md) > [value](./kibana-plugin-plugins-expressions-server.font.value.md) + +## Font.value property + +Signature: + +```typescript +value: FontValue; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.fontlabel.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.fontlabel.md new file mode 100644 index 0000000000000..4837abb7542fa --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.fontlabel.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [FontLabel](./kibana-plugin-plugins-expressions-server.fontlabel.md) + +## FontLabel type + +This type contains a unions of all supported font labels, or the the name of the font the user would see in a UI. + +Signature: + +```typescript +export declare type FontLabel = typeof fonts[number]['label']; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.fontstyle.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.fontstyle.md new file mode 100644 index 0000000000000..26588096666df --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.fontstyle.md @@ -0,0 +1,21 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [FontStyle](./kibana-plugin-plugins-expressions-server.fontstyle.md) + +## FontStyle enum + +Enum of supported CSS `font-style` properties. + +Signature: + +```typescript +export declare enum FontStyle +``` + +## Enumeration Members + +| Member | Value | Description | +| --- | --- | --- | +| ITALIC | "italic" | | +| NORMAL | "normal" | | + diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.fontvalue.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.fontvalue.md new file mode 100644 index 0000000000000..6c0332067a369 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.fontvalue.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [FontValue](./kibana-plugin-plugins-expressions-server.fontvalue.md) + +## FontValue type + +This type contains a union of all supported font values, equivalent to the CSS `font-value` property. + +Signature: + +```typescript +export declare type FontValue = typeof fonts[number]['value']; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.fontweight.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.fontweight.md new file mode 100644 index 0000000000000..314e4b17df01e --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.fontweight.md @@ -0,0 +1,32 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [FontWeight](./kibana-plugin-plugins-expressions-server.fontweight.md) + +## FontWeight enum + +Enum of supported CSS `font-weight` properties. + +Signature: + +```typescript +export declare enum FontWeight +``` + +## Enumeration Members + +| Member | Value | Description | +| --- | --- | --- | +| BOLD | "bold" | | +| BOLDER | "bolder" | | +| EIGHT | "800" | | +| FIVE | "500" | | +| FOUR | "400" | | +| LIGHTER | "lighter" | | +| NINE | "900" | | +| NORMAL | "normal" | | +| ONE | "100" | | +| SEVEN | "700" | | +| SIX | "600" | | +| THREE | "300" | | +| TWO | "200" | | + diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.format.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.format.md new file mode 100644 index 0000000000000..aae8498bce03f --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.format.md @@ -0,0 +1,23 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [format](./kibana-plugin-plugins-expressions-server.format.md) + +## format() function + +Signature: + +```typescript +export declare function format(ast: T, type: T extends ExpressionAstExpression ? 'expression' : 'argument'): string; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| ast | T | | +| type | T extends ExpressionAstExpression ? 'expression' : 'argument' | | + +Returns: + +`string` + diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.formatexpression.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.formatexpression.md new file mode 100644 index 0000000000000..701d7b448f69f --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.formatexpression.md @@ -0,0 +1,24 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [formatExpression](./kibana-plugin-plugins-expressions-server.formatexpression.md) + +## formatExpression() function + +Given expression pipeline AST, returns formatted string. + +Signature: + +```typescript +export declare function formatExpression(ast: ExpressionAstExpression): string; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| ast | ExpressionAstExpression | | + +Returns: + +`string` + diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.functionsregistry._constructor_.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.functionsregistry._constructor_.md new file mode 100644 index 0000000000000..c3dc8b8e9b16f --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.functionsregistry._constructor_.md @@ -0,0 +1,20 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [FunctionsRegistry](./kibana-plugin-plugins-expressions-server.functionsregistry.md) > [(constructor)](./kibana-plugin-plugins-expressions-server.functionsregistry._constructor_.md) + +## FunctionsRegistry.(constructor) + +Constructs a new instance of the `FunctionsRegistry` class + +Signature: + +```typescript +constructor(executor: Executor); +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| executor | Executor<any> | | + diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.functionsregistry.get.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.functionsregistry.get.md new file mode 100644 index 0000000000000..795b3a87eac09 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.functionsregistry.get.md @@ -0,0 +1,22 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [FunctionsRegistry](./kibana-plugin-plugins-expressions-server.functionsregistry.md) > [get](./kibana-plugin-plugins-expressions-server.functionsregistry.get.md) + +## FunctionsRegistry.get() method + +Signature: + +```typescript +get(id: string): ExpressionFunction | null; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| id | string | | + +Returns: + +`ExpressionFunction | null` + diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.functionsregistry.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.functionsregistry.md new file mode 100644 index 0000000000000..790105c68241a --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.functionsregistry.md @@ -0,0 +1,27 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [FunctionsRegistry](./kibana-plugin-plugins-expressions-server.functionsregistry.md) + +## FunctionsRegistry class + +Signature: + +```typescript +export declare class FunctionsRegistry implements IRegistry +``` + +## Constructors + +| Constructor | Modifiers | Description | +| --- | --- | --- | +| [(constructor)(executor)](./kibana-plugin-plugins-expressions-server.functionsregistry._constructor_.md) | | Constructs a new instance of the FunctionsRegistry class | + +## Methods + +| Method | Modifiers | Description | +| --- | --- | --- | +| [get(id)](./kibana-plugin-plugins-expressions-server.functionsregistry.get.md) | | | +| [register(functionDefinition)](./kibana-plugin-plugins-expressions-server.functionsregistry.register.md) | | | +| [toArray()](./kibana-plugin-plugins-expressions-server.functionsregistry.toarray.md) | | | +| [toJS()](./kibana-plugin-plugins-expressions-server.functionsregistry.tojs.md) | | | + diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.functionsregistry.register.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.functionsregistry.register.md new file mode 100644 index 0000000000000..7da47937e80f0 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.functionsregistry.register.md @@ -0,0 +1,22 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [FunctionsRegistry](./kibana-plugin-plugins-expressions-server.functionsregistry.md) > [register](./kibana-plugin-plugins-expressions-server.functionsregistry.register.md) + +## FunctionsRegistry.register() method + +Signature: + +```typescript +register(functionDefinition: AnyExpressionFunctionDefinition | (() => AnyExpressionFunctionDefinition)): void; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| functionDefinition | AnyExpressionFunctionDefinition | (() => AnyExpressionFunctionDefinition) | | + +Returns: + +`void` + diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.functionsregistry.toarray.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.functionsregistry.toarray.md new file mode 100644 index 0000000000000..5f9ca38990076 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.functionsregistry.toarray.md @@ -0,0 +1,15 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [FunctionsRegistry](./kibana-plugin-plugins-expressions-server.functionsregistry.md) > [toArray](./kibana-plugin-plugins-expressions-server.functionsregistry.toarray.md) + +## FunctionsRegistry.toArray() method + +Signature: + +```typescript +toArray(): ExpressionFunction[]; +``` +Returns: + +`ExpressionFunction[]` + diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.functionsregistry.tojs.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.functionsregistry.tojs.md new file mode 100644 index 0000000000000..35751bb534e58 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.functionsregistry.tojs.md @@ -0,0 +1,15 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [FunctionsRegistry](./kibana-plugin-plugins-expressions-server.functionsregistry.md) > [toJS](./kibana-plugin-plugins-expressions-server.functionsregistry.tojs.md) + +## FunctionsRegistry.toJS() method + +Signature: + +```typescript +toJS(): Record; +``` +Returns: + +`Record` + diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.iinterpreterrenderhandlers.done.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.iinterpreterrenderhandlers.done.md new file mode 100644 index 0000000000000..c6204769e893c --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.iinterpreterrenderhandlers.done.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [IInterpreterRenderHandlers](./kibana-plugin-plugins-expressions-server.iinterpreterrenderhandlers.md) > [done](./kibana-plugin-plugins-expressions-server.iinterpreterrenderhandlers.done.md) + +## IInterpreterRenderHandlers.done property + +Done increments the number of rendering successes + +Signature: + +```typescript +done: () => void; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.iinterpreterrenderhandlers.event.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.iinterpreterrenderhandlers.event.md new file mode 100644 index 0000000000000..6a011aaf7f132 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.iinterpreterrenderhandlers.event.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [IInterpreterRenderHandlers](./kibana-plugin-plugins-expressions-server.iinterpreterrenderhandlers.md) > [event](./kibana-plugin-plugins-expressions-server.iinterpreterrenderhandlers.event.md) + +## IInterpreterRenderHandlers.event property + +Signature: + +```typescript +event: (event: any) => void; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.iinterpreterrenderhandlers.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.iinterpreterrenderhandlers.md new file mode 100644 index 0000000000000..ccf6271f712b9 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.iinterpreterrenderhandlers.md @@ -0,0 +1,23 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [IInterpreterRenderHandlers](./kibana-plugin-plugins-expressions-server.iinterpreterrenderhandlers.md) + +## IInterpreterRenderHandlers interface + +Signature: + +```typescript +export interface IInterpreterRenderHandlers +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [done](./kibana-plugin-plugins-expressions-server.iinterpreterrenderhandlers.done.md) | () => void | Done increments the number of rendering successes | +| [event](./kibana-plugin-plugins-expressions-server.iinterpreterrenderhandlers.event.md) | (event: any) => void | | +| [onDestroy](./kibana-plugin-plugins-expressions-server.iinterpreterrenderhandlers.ondestroy.md) | (fn: () => void) => void | | +| [reload](./kibana-plugin-plugins-expressions-server.iinterpreterrenderhandlers.reload.md) | () => void | | +| [uiState](./kibana-plugin-plugins-expressions-server.iinterpreterrenderhandlers.uistate.md) | PersistedState | | +| [update](./kibana-plugin-plugins-expressions-server.iinterpreterrenderhandlers.update.md) | (params: any) => void | | + diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.iinterpreterrenderhandlers.ondestroy.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.iinterpreterrenderhandlers.ondestroy.md new file mode 100644 index 0000000000000..14ef98d17769c --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.iinterpreterrenderhandlers.ondestroy.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [IInterpreterRenderHandlers](./kibana-plugin-plugins-expressions-server.iinterpreterrenderhandlers.md) > [onDestroy](./kibana-plugin-plugins-expressions-server.iinterpreterrenderhandlers.ondestroy.md) + +## IInterpreterRenderHandlers.onDestroy property + +Signature: + +```typescript +onDestroy: (fn: () => void) => void; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.iinterpreterrenderhandlers.reload.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.iinterpreterrenderhandlers.reload.md new file mode 100644 index 0000000000000..c5e74e79f652b --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.iinterpreterrenderhandlers.reload.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [IInterpreterRenderHandlers](./kibana-plugin-plugins-expressions-server.iinterpreterrenderhandlers.md) > [reload](./kibana-plugin-plugins-expressions-server.iinterpreterrenderhandlers.reload.md) + +## IInterpreterRenderHandlers.reload property + +Signature: + +```typescript +reload: () => void; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.iinterpreterrenderhandlers.uistate.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.iinterpreterrenderhandlers.uistate.md new file mode 100644 index 0000000000000..b09433c6454ad --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.iinterpreterrenderhandlers.uistate.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [IInterpreterRenderHandlers](./kibana-plugin-plugins-expressions-server.iinterpreterrenderhandlers.md) > [uiState](./kibana-plugin-plugins-expressions-server.iinterpreterrenderhandlers.uistate.md) + +## IInterpreterRenderHandlers.uiState property + +Signature: + +```typescript +uiState?: PersistedState; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.iinterpreterrenderhandlers.update.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.iinterpreterrenderhandlers.update.md new file mode 100644 index 0000000000000..2649ea99b3386 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.iinterpreterrenderhandlers.update.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [IInterpreterRenderHandlers](./kibana-plugin-plugins-expressions-server.iinterpreterrenderhandlers.md) > [update](./kibana-plugin-plugins-expressions-server.iinterpreterrenderhandlers.update.md) + +## IInterpreterRenderHandlers.update property + +Signature: + +```typescript +update: (params: any) => void; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.interpretererrortype.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.interpretererrortype.md new file mode 100644 index 0000000000000..032cea643c5bf --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.interpretererrortype.md @@ -0,0 +1,16 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [InterpreterErrorType](./kibana-plugin-plugins-expressions-server.interpretererrortype.md) + +## InterpreterErrorType type + +> Warning: This API is now obsolete. +> +> Exported for backwards compatibility. +> + +Signature: + +```typescript +export declare type InterpreterErrorType = ExpressionValueError; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.iregistry.get.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.iregistry.get.md new file mode 100644 index 0000000000000..b0b4524afe40a --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.iregistry.get.md @@ -0,0 +1,22 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [IRegistry](./kibana-plugin-plugins-expressions-server.iregistry.md) > [get](./kibana-plugin-plugins-expressions-server.iregistry.get.md) + +## IRegistry.get() method + +Signature: + +```typescript +get(id: string): T | null; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| id | string | | + +Returns: + +`T | null` + diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.iregistry.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.iregistry.md new file mode 100644 index 0000000000000..71aafe2db2dd1 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.iregistry.md @@ -0,0 +1,20 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [IRegistry](./kibana-plugin-plugins-expressions-server.iregistry.md) + +## IRegistry interface + +Signature: + +```typescript +export interface IRegistry +``` + +## Methods + +| Method | Description | +| --- | --- | +| [get(id)](./kibana-plugin-plugins-expressions-server.iregistry.get.md) | | +| [toArray()](./kibana-plugin-plugins-expressions-server.iregistry.toarray.md) | | +| [toJS()](./kibana-plugin-plugins-expressions-server.iregistry.tojs.md) | | + diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.iregistry.toarray.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.iregistry.toarray.md new file mode 100644 index 0000000000000..73718cd036c85 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.iregistry.toarray.md @@ -0,0 +1,15 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [IRegistry](./kibana-plugin-plugins-expressions-server.iregistry.md) > [toArray](./kibana-plugin-plugins-expressions-server.iregistry.toarray.md) + +## IRegistry.toArray() method + +Signature: + +```typescript +toArray(): T[]; +``` +Returns: + +`T[]` + diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.iregistry.tojs.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.iregistry.tojs.md new file mode 100644 index 0000000000000..af83efbd99aa7 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.iregistry.tojs.md @@ -0,0 +1,15 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [IRegistry](./kibana-plugin-plugins-expressions-server.iregistry.md) > [toJS](./kibana-plugin-plugins-expressions-server.iregistry.tojs.md) + +## IRegistry.toJS() method + +Signature: + +```typescript +toJS(): Record; +``` +Returns: + +`Record` + diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.isexpressionastbuilder.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.isexpressionastbuilder.md new file mode 100644 index 0000000000000..7692ff21ae934 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.isexpressionastbuilder.md @@ -0,0 +1,28 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [isExpressionAstBuilder](./kibana-plugin-plugins-expressions-server.isexpressionastbuilder.md) + +## isExpressionAstBuilder() function + +Type guard that checks whether a given value is an `ExpressionAstExpressionBuilder`. This is useful when working with subexpressions, where you might be retrieving a function argument, and need to know whether it is an expression builder instance which you can perform operations on. + +Signature: + +```typescript +export declare function isExpressionAstBuilder(val: any): val is ExpressionAstExpressionBuilder; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| val | any | | + +Returns: + +`val is ExpressionAstExpressionBuilder` + +## Example + +const arg = myFunction.getArgument('foo'); if (isExpressionAstBuilder(foo)) { foo.toAst(); } + diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.kibana_context_name.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.kibana_context_name.md new file mode 100644 index 0000000000000..bd47c52e0d5ce --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.kibana_context_name.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [KIBANA\_CONTEXT\_NAME](./kibana-plugin-plugins-expressions-server.kibana_context_name.md) + +## KIBANA\_CONTEXT\_NAME type + +Signature: + +```typescript +export declare type KIBANA_CONTEXT_NAME = 'kibana_context'; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.kibanacontext.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.kibanacontext.md new file mode 100644 index 0000000000000..023748173e7dd --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.kibanacontext.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [KibanaContext](./kibana-plugin-plugins-expressions-server.kibanacontext.md) + +## KibanaContext type + +Signature: + +```typescript +export declare type KibanaContext = ExpressionValueSearchContext; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.kibanadatatable.columns.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.kibanadatatable.columns.md new file mode 100644 index 0000000000000..423e543e4307a --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.kibanadatatable.columns.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [KibanaDatatable](./kibana-plugin-plugins-expressions-server.kibanadatatable.md) > [columns](./kibana-plugin-plugins-expressions-server.kibanadatatable.columns.md) + +## KibanaDatatable.columns property + +Signature: + +```typescript +columns: KibanaDatatableColumn[]; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.kibanadatatable.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.kibanadatatable.md new file mode 100644 index 0000000000000..30ee3ac2fcd13 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.kibanadatatable.md @@ -0,0 +1,20 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [KibanaDatatable](./kibana-plugin-plugins-expressions-server.kibanadatatable.md) + +## KibanaDatatable interface + +Signature: + +```typescript +export interface KibanaDatatable +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [columns](./kibana-plugin-plugins-expressions-server.kibanadatatable.columns.md) | KibanaDatatableColumn[] | | +| [rows](./kibana-plugin-plugins-expressions-server.kibanadatatable.rows.md) | KibanaDatatableRow[] | | +| [type](./kibana-plugin-plugins-expressions-server.kibanadatatable.type.md) | typeof name | | + diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.kibanadatatable.rows.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.kibanadatatable.rows.md new file mode 100644 index 0000000000000..42170a83fc3c8 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.kibanadatatable.rows.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [KibanaDatatable](./kibana-plugin-plugins-expressions-server.kibanadatatable.md) > [rows](./kibana-plugin-plugins-expressions-server.kibanadatatable.rows.md) + +## KibanaDatatable.rows property + +Signature: + +```typescript +rows: KibanaDatatableRow[]; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.kibanadatatable.type.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.kibanadatatable.type.md new file mode 100644 index 0000000000000..c36674540a1ba --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.kibanadatatable.type.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [KibanaDatatable](./kibana-plugin-plugins-expressions-server.kibanadatatable.md) > [type](./kibana-plugin-plugins-expressions-server.kibanadatatable.type.md) + +## KibanaDatatable.type property + +Signature: + +```typescript +type: typeof name; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.kibanadatatablecolumn.formathint.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.kibanadatatablecolumn.formathint.md new file mode 100644 index 0000000000000..a1e6949019dcb --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.kibanadatatablecolumn.formathint.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [KibanaDatatableColumn](./kibana-plugin-plugins-expressions-server.kibanadatatablecolumn.md) > [formatHint](./kibana-plugin-plugins-expressions-server.kibanadatatablecolumn.formathint.md) + +## KibanaDatatableColumn.formatHint property + +Signature: + +```typescript +formatHint?: SerializedFieldFormat; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.kibanadatatablecolumn.id.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.kibanadatatablecolumn.id.md new file mode 100644 index 0000000000000..6f90da1ac9c94 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.kibanadatatablecolumn.id.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [KibanaDatatableColumn](./kibana-plugin-plugins-expressions-server.kibanadatatablecolumn.md) > [id](./kibana-plugin-plugins-expressions-server.kibanadatatablecolumn.id.md) + +## KibanaDatatableColumn.id property + +Signature: + +```typescript +id: string; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.kibanadatatablecolumn.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.kibanadatatablecolumn.md new file mode 100644 index 0000000000000..171477911502f --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.kibanadatatablecolumn.md @@ -0,0 +1,21 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [KibanaDatatableColumn](./kibana-plugin-plugins-expressions-server.kibanadatatablecolumn.md) + +## KibanaDatatableColumn interface + +Signature: + +```typescript +export interface KibanaDatatableColumn +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [formatHint](./kibana-plugin-plugins-expressions-server.kibanadatatablecolumn.formathint.md) | SerializedFieldFormat | | +| [id](./kibana-plugin-plugins-expressions-server.kibanadatatablecolumn.id.md) | string | | +| [meta](./kibana-plugin-plugins-expressions-server.kibanadatatablecolumn.meta.md) | KibanaDatatableColumnMeta | | +| [name](./kibana-plugin-plugins-expressions-server.kibanadatatablecolumn.name.md) | string | | + diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.kibanadatatablecolumn.meta.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.kibanadatatablecolumn.meta.md new file mode 100644 index 0000000000000..40b20d51e6ec6 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.kibanadatatablecolumn.meta.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [KibanaDatatableColumn](./kibana-plugin-plugins-expressions-server.kibanadatatablecolumn.md) > [meta](./kibana-plugin-plugins-expressions-server.kibanadatatablecolumn.meta.md) + +## KibanaDatatableColumn.meta property + +Signature: + +```typescript +meta?: KibanaDatatableColumnMeta; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.kibanadatatablecolumn.name.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.kibanadatatablecolumn.name.md new file mode 100644 index 0000000000000..3a85e2325483a --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.kibanadatatablecolumn.name.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [KibanaDatatableColumn](./kibana-plugin-plugins-expressions-server.kibanadatatablecolumn.md) > [name](./kibana-plugin-plugins-expressions-server.kibanadatatablecolumn.name.md) + +## KibanaDatatableColumn.name property + +Signature: + +```typescript +name: string; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.kibanadatatablecolumnmeta.aggconfigparams.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.kibanadatatablecolumnmeta.aggconfigparams.md new file mode 100644 index 0000000000000..539b24174f725 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.kibanadatatablecolumnmeta.aggconfigparams.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [KibanaDatatableColumnMeta](./kibana-plugin-plugins-expressions-server.kibanadatatablecolumnmeta.md) > [aggConfigParams](./kibana-plugin-plugins-expressions-server.kibanadatatablecolumnmeta.aggconfigparams.md) + +## KibanaDatatableColumnMeta.aggConfigParams property + +Signature: + +```typescript +aggConfigParams?: Record; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.kibanadatatablecolumnmeta.indexpatternid.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.kibanadatatablecolumnmeta.indexpatternid.md new file mode 100644 index 0000000000000..2704915a15071 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.kibanadatatablecolumnmeta.indexpatternid.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [KibanaDatatableColumnMeta](./kibana-plugin-plugins-expressions-server.kibanadatatablecolumnmeta.md) > [indexPatternId](./kibana-plugin-plugins-expressions-server.kibanadatatablecolumnmeta.indexpatternid.md) + +## KibanaDatatableColumnMeta.indexPatternId property + +Signature: + +```typescript +indexPatternId?: string; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.kibanadatatablecolumnmeta.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.kibanadatatablecolumnmeta.md new file mode 100644 index 0000000000000..d9a96e665f010 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.kibanadatatablecolumnmeta.md @@ -0,0 +1,20 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [KibanaDatatableColumnMeta](./kibana-plugin-plugins-expressions-server.kibanadatatablecolumnmeta.md) + +## KibanaDatatableColumnMeta interface + +Signature: + +```typescript +export interface KibanaDatatableColumnMeta +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [aggConfigParams](./kibana-plugin-plugins-expressions-server.kibanadatatablecolumnmeta.aggconfigparams.md) | Record<string, any> | | +| [indexPatternId](./kibana-plugin-plugins-expressions-server.kibanadatatablecolumnmeta.indexpatternid.md) | string | | +| [type](./kibana-plugin-plugins-expressions-server.kibanadatatablecolumnmeta.type.md) | string | | + diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.kibanadatatablecolumnmeta.type.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.kibanadatatablecolumnmeta.type.md new file mode 100644 index 0000000000000..56e3757ef621a --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.kibanadatatablecolumnmeta.type.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [KibanaDatatableColumnMeta](./kibana-plugin-plugins-expressions-server.kibanadatatablecolumnmeta.md) > [type](./kibana-plugin-plugins-expressions-server.kibanadatatablecolumnmeta.type.md) + +## KibanaDatatableColumnMeta.type property + +Signature: + +```typescript +type: string; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.kibanadatatablerow.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.kibanadatatablerow.md new file mode 100644 index 0000000000000..dd0f3f4cb2f60 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.kibanadatatablerow.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [KibanaDatatableRow](./kibana-plugin-plugins-expressions-server.kibanadatatablerow.md) + +## KibanaDatatableRow interface + +Signature: + +```typescript +export interface KibanaDatatableRow +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.knowntypetostring.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.knowntypetostring.md new file mode 100644 index 0000000000000..ed536ac3b7173 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.knowntypetostring.md @@ -0,0 +1,17 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [KnownTypeToString](./kibana-plugin-plugins-expressions-server.knowntypetostring.md) + +## KnownTypeToString type + +Map the type of the generic to a string-based representation of the type. + +If the provided generic is its own type interface, we use the value of the `type` key as a string literal type for it. + +Signature: + +```typescript +export declare type KnownTypeToString = T extends string ? 'string' : T extends boolean ? 'boolean' : T extends number ? 'number' : T extends null ? 'null' : T extends { + type: string; +} ? T['type'] : never; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.md new file mode 100644 index 0000000000000..c9fed2e00c66c --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.md @@ -0,0 +1,116 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) + +## kibana-plugin-plugins-expressions-server package + +## Classes + +| Class | Description | +| --- | --- | +| [Execution](./kibana-plugin-plugins-expressions-server.execution.md) | | +| [Executor](./kibana-plugin-plugins-expressions-server.executor.md) | | +| [ExpressionFunction](./kibana-plugin-plugins-expressions-server.expressionfunction.md) | | +| [ExpressionFunctionParameter](./kibana-plugin-plugins-expressions-server.expressionfunctionparameter.md) | | +| [ExpressionRenderer](./kibana-plugin-plugins-expressions-server.expressionrenderer.md) | | +| [ExpressionRendererRegistry](./kibana-plugin-plugins-expressions-server.expressionrendererregistry.md) | | +| [ExpressionsServerPlugin](./kibana-plugin-plugins-expressions-server.expressionsserverplugin.md) | | +| [ExpressionType](./kibana-plugin-plugins-expressions-server.expressiontype.md) | | +| [FunctionsRegistry](./kibana-plugin-plugins-expressions-server.functionsregistry.md) | | +| [TypesRegistry](./kibana-plugin-plugins-expressions-server.typesregistry.md) | | + +## Enumerations + +| Enumeration | Description | +| --- | --- | +| [FontStyle](./kibana-plugin-plugins-expressions-server.fontstyle.md) | Enum of supported CSS font-style properties. | +| [FontWeight](./kibana-plugin-plugins-expressions-server.fontweight.md) | Enum of supported CSS font-weight properties. | +| [Overflow](./kibana-plugin-plugins-expressions-server.overflow.md) | Enum of supported CSS overflow properties. | +| [TextAlignment](./kibana-plugin-plugins-expressions-server.textalignment.md) | Enum of supported CSS text-align properties. | +| [TextDecoration](./kibana-plugin-plugins-expressions-server.textdecoration.md) | Enum of supported CSS text-decoration properties. | + +## Functions + +| Function | Description | +| --- | --- | +| [buildExpression(initialState)](./kibana-plugin-plugins-expressions-server.buildexpression.md) | Makes it easy to progressively build, update, and traverse an expression AST. You can either start with an empty AST, or provide an expression string, AST, or array of expression function builders to use as initial state. | +| [buildExpressionFunction(fnName, initialArgs)](./kibana-plugin-plugins-expressions-server.buildexpressionfunction.md) | Manages an AST for a single expression function. The return value can be provided to buildExpression to add this function to an expression.Note that to preserve type safety and ensure no args are missing, all required arguments for the specified function must be provided up front. If desired, they can be changed or removed later. | +| [format(ast, type)](./kibana-plugin-plugins-expressions-server.format.md) | | +| [formatExpression(ast)](./kibana-plugin-plugins-expressions-server.formatexpression.md) | Given expression pipeline AST, returns formatted string. | +| [isExpressionAstBuilder(val)](./kibana-plugin-plugins-expressions-server.isexpressionastbuilder.md) | Type guard that checks whether a given value is an ExpressionAstExpressionBuilder. This is useful when working with subexpressions, where you might be retrieving a function argument, and need to know whether it is an expression builder instance which you can perform operations on. | +| [parse(expression, startRule)](./kibana-plugin-plugins-expressions-server.parse.md) | | +| [parseExpression(expression)](./kibana-plugin-plugins-expressions-server.parseexpression.md) | Given expression pipeline string, returns parsed AST. | +| [plugin(initializerContext)](./kibana-plugin-plugins-expressions-server.plugin.md) | | + +## Interfaces + +| Interface | Description | +| --- | --- | +| [Datatable](./kibana-plugin-plugins-expressions-server.datatable.md) | A Datatable in Canvas is a unique structure that represents tabulated data. | +| [DatatableColumn](./kibana-plugin-plugins-expressions-server.datatablecolumn.md) | This type represents the shape of a column in a Datatable. | +| [ExecutionContext](./kibana-plugin-plugins-expressions-server.executioncontext.md) | ExecutionContext is an object available to all functions during a single execution; it provides various methods to perform side-effects. | +| [ExecutionParams](./kibana-plugin-plugins-expressions-server.executionparams.md) | | +| [ExecutionState](./kibana-plugin-plugins-expressions-server.executionstate.md) | | +| [ExecutorState](./kibana-plugin-plugins-expressions-server.executorstate.md) | | +| [ExpressionAstExpression](./kibana-plugin-plugins-expressions-server.expressionastexpression.md) | | +| [ExpressionAstExpressionBuilder](./kibana-plugin-plugins-expressions-server.expressionastexpressionbuilder.md) | | +| [ExpressionAstFunction](./kibana-plugin-plugins-expressions-server.expressionastfunction.md) | | +| [ExpressionAstFunctionBuilder](./kibana-plugin-plugins-expressions-server.expressionastfunctionbuilder.md) | | +| [ExpressionFunctionDefinition](./kibana-plugin-plugins-expressions-server.expressionfunctiondefinition.md) | ExpressionFunctionDefinition is the interface plugins have to implement to register a function in expressions plugin. | +| [ExpressionFunctionDefinitions](./kibana-plugin-plugins-expressions-server.expressionfunctiondefinitions.md) | A mapping of ExpressionFunctionDefinitions for functions which the Expressions services provides out-of-the-box. Any new functions registered by the Expressions plugin should have their types added here. | +| [ExpressionImage](./kibana-plugin-plugins-expressions-server.expressionimage.md) | | +| [ExpressionRenderDefinition](./kibana-plugin-plugins-expressions-server.expressionrenderdefinition.md) | | +| [ExpressionTypeDefinition](./kibana-plugin-plugins-expressions-server.expressiontypedefinition.md) | A generic type which represents a custom Expression Type Definition that's registered to the Interpreter. | +| [ExpressionTypeStyle](./kibana-plugin-plugins-expressions-server.expressiontypestyle.md) | An object that represents style information, typically CSS. | +| [Font](./kibana-plugin-plugins-expressions-server.font.md) | An interface representing a font in Canvas, with a textual label and the CSS font-value. | +| [IInterpreterRenderHandlers](./kibana-plugin-plugins-expressions-server.iinterpreterrenderhandlers.md) | | +| [IRegistry](./kibana-plugin-plugins-expressions-server.iregistry.md) | | +| [KibanaDatatable](./kibana-plugin-plugins-expressions-server.kibanadatatable.md) | | +| [KibanaDatatableColumn](./kibana-plugin-plugins-expressions-server.kibanadatatablecolumn.md) | | +| [KibanaDatatableColumnMeta](./kibana-plugin-plugins-expressions-server.kibanadatatablecolumnmeta.md) | | +| [KibanaDatatableRow](./kibana-plugin-plugins-expressions-server.kibanadatatablerow.md) | | +| [PointSeriesColumn](./kibana-plugin-plugins-expressions-server.pointseriescolumn.md) | Column in a PointSeries | +| [Range](./kibana-plugin-plugins-expressions-server.range.md) | | +| [SerializedDatatable](./kibana-plugin-plugins-expressions-server.serializeddatatable.md) | | +| [SerializedFieldFormat](./kibana-plugin-plugins-expressions-server.serializedfieldformat.md) | JSON representation of a field formatter configuration. Is used to carry information about how to format data in a data table as part of the column definition. | + +## Type Aliases + +| Type Alias | Description | +| --- | --- | +| [AnyExpressionFunctionDefinition](./kibana-plugin-plugins-expressions-server.anyexpressionfunctiondefinition.md) | Type to capture every possible expression function definition. | +| [AnyExpressionTypeDefinition](./kibana-plugin-plugins-expressions-server.anyexpressiontypedefinition.md) | | +| [ArgumentType](./kibana-plugin-plugins-expressions-server.argumenttype.md) | This type represents all of the possible combinations of properties of an Argument in an Expression Function. The presence or absence of certain fields influence the shape and presence of others within each arg in the specification. | +| [DatatableColumnType](./kibana-plugin-plugins-expressions-server.datatablecolumntype.md) | This type represents the type of any DatatableColumn in a Datatable. | +| [DatatableRow](./kibana-plugin-plugins-expressions-server.datatablerow.md) | This type represents a row in a Datatable. | +| [ExecutionContainer](./kibana-plugin-plugins-expressions-server.executioncontainer.md) | | +| [ExecutorContainer](./kibana-plugin-plugins-expressions-server.executorcontainer.md) | | +| [ExpressionAstArgument](./kibana-plugin-plugins-expressions-server.expressionastargument.md) | | +| [ExpressionAstNode](./kibana-plugin-plugins-expressions-server.expressionastnode.md) | | +| [ExpressionFunctionKibana](./kibana-plugin-plugins-expressions-server.expressionfunctionkibana.md) | | +| [ExpressionsServerSetup](./kibana-plugin-plugins-expressions-server.expressionsserversetup.md) | | +| [ExpressionsServerStart](./kibana-plugin-plugins-expressions-server.expressionsserverstart.md) | | +| [ExpressionValue](./kibana-plugin-plugins-expressions-server.expressionvalue.md) | | +| [ExpressionValueBoxed](./kibana-plugin-plugins-expressions-server.expressionvalueboxed.md) | | +| [ExpressionValueConverter](./kibana-plugin-plugins-expressions-server.expressionvalueconverter.md) | | +| [ExpressionValueError](./kibana-plugin-plugins-expressions-server.expressionvalueerror.md) | | +| [ExpressionValueFilter](./kibana-plugin-plugins-expressions-server.expressionvaluefilter.md) | Represents an object that is a Filter. | +| [ExpressionValueNum](./kibana-plugin-plugins-expressions-server.expressionvaluenum.md) | | +| [ExpressionValueRender](./kibana-plugin-plugins-expressions-server.expressionvaluerender.md) | Represents an object that is intended to be rendered. | +| [ExpressionValueSearchContext](./kibana-plugin-plugins-expressions-server.expressionvaluesearchcontext.md) | | +| [ExpressionValueUnboxed](./kibana-plugin-plugins-expressions-server.expressionvalueunboxed.md) | | +| [FontLabel](./kibana-plugin-plugins-expressions-server.fontlabel.md) | This type contains a unions of all supported font labels, or the the name of the font the user would see in a UI. | +| [FontValue](./kibana-plugin-plugins-expressions-server.fontvalue.md) | This type contains a union of all supported font values, equivalent to the CSS font-value property. | +| [InterpreterErrorType](./kibana-plugin-plugins-expressions-server.interpretererrortype.md) | | +| [KIBANA\_CONTEXT\_NAME](./kibana-plugin-plugins-expressions-server.kibana_context_name.md) | | +| [KibanaContext](./kibana-plugin-plugins-expressions-server.kibanacontext.md) | | +| [KnownTypeToString](./kibana-plugin-plugins-expressions-server.knowntypetostring.md) | Map the type of the generic to a string-based representation of the type.If the provided generic is its own type interface, we use the value of the type key as a string literal type for it. | +| [PointSeries](./kibana-plugin-plugins-expressions-server.pointseries.md) | A PointSeries is a unique structure that represents dots on a chart. | +| [PointSeriesColumnName](./kibana-plugin-plugins-expressions-server.pointseriescolumnname.md) | Allowed column names in a PointSeries | +| [PointSeriesColumns](./kibana-plugin-plugins-expressions-server.pointseriescolumns.md) | Represents a collection of valid Columns in a PointSeries | +| [PointSeriesRow](./kibana-plugin-plugins-expressions-server.pointseriesrow.md) | | +| [Style](./kibana-plugin-plugins-expressions-server.style.md) | | +| [TypeString](./kibana-plugin-plugins-expressions-server.typestring.md) | If the type extends a Promise, we still need to return the string representation:someArgument: Promise<boolean | string> results in types: ['boolean', 'string'] | +| [TypeToString](./kibana-plugin-plugins-expressions-server.typetostring.md) | This can convert a type into a known Expression string representation of that type. For example, TypeToString<Datatable> will resolve to 'datatable'. This allows Expression Functions to continue to specify their type in a simple string format. | +| [UnmappedTypeStrings](./kibana-plugin-plugins-expressions-server.unmappedtypestrings.md) | Types used in Expressions that don't map to a primitive cleanly:date is typed as a number or string, and represents a date | + diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.overflow.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.overflow.md new file mode 100644 index 0000000000000..2b1d1a34cd46a --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.overflow.md @@ -0,0 +1,23 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [Overflow](./kibana-plugin-plugins-expressions-server.overflow.md) + +## Overflow enum + +Enum of supported CSS `overflow` properties. + +Signature: + +```typescript +export declare enum Overflow +``` + +## Enumeration Members + +| Member | Value | Description | +| --- | --- | --- | +| AUTO | "auto" | | +| HIDDEN | "hidden" | | +| SCROLL | "scroll" | | +| VISIBLE | "visible" | | + diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.parse.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.parse.md new file mode 100644 index 0000000000000..ec2534986006f --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.parse.md @@ -0,0 +1,23 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [parse](./kibana-plugin-plugins-expressions-server.parse.md) + +## parse() function + +Signature: + +```typescript +export declare function parse(expression: E, startRule: S): S extends 'expression' ? ExpressionAstExpression : ExpressionAstArgument; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expression | E | | +| startRule | S | | + +Returns: + +`S extends 'expression' ? ExpressionAstExpression : ExpressionAstArgument` + diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.parseexpression.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.parseexpression.md new file mode 100644 index 0000000000000..0d8547fd5243b --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.parseexpression.md @@ -0,0 +1,24 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [parseExpression](./kibana-plugin-plugins-expressions-server.parseexpression.md) + +## parseExpression() function + +Given expression pipeline string, returns parsed AST. + +Signature: + +```typescript +export declare function parseExpression(expression: string): ExpressionAstExpression; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| expression | string | | + +Returns: + +`ExpressionAstExpression` + diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.plugin.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.plugin.md new file mode 100644 index 0000000000000..79a7100ebf540 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.plugin.md @@ -0,0 +1,22 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [plugin](./kibana-plugin-plugins-expressions-server.plugin.md) + +## plugin() function + +Signature: + +```typescript +export declare function plugin(initializerContext: PluginInitializerContext): ExpressionsServerPlugin; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| initializerContext | PluginInitializerContext | | + +Returns: + +`ExpressionsServerPlugin` + diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.pointseries.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.pointseries.md new file mode 100644 index 0000000000000..f65efd705666d --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.pointseries.md @@ -0,0 +1,16 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [PointSeries](./kibana-plugin-plugins-expressions-server.pointseries.md) + +## PointSeries type + +A `PointSeries` is a unique structure that represents dots on a chart. + +Signature: + +```typescript +export declare type PointSeries = ExpressionValueBoxed<'pointseries', { + columns: PointSeriesColumns; + rows: PointSeriesRow[]; +}>; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.pointseriescolumn.expression.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.pointseriescolumn.expression.md new file mode 100644 index 0000000000000..c857a9f29fa60 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.pointseriescolumn.expression.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [PointSeriesColumn](./kibana-plugin-plugins-expressions-server.pointseriescolumn.md) > [expression](./kibana-plugin-plugins-expressions-server.pointseriescolumn.expression.md) + +## PointSeriesColumn.expression property + +Signature: + +```typescript +expression: string; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.pointseriescolumn.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.pointseriescolumn.md new file mode 100644 index 0000000000000..5aec683421dd1 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.pointseriescolumn.md @@ -0,0 +1,22 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [PointSeriesColumn](./kibana-plugin-plugins-expressions-server.pointseriescolumn.md) + +## PointSeriesColumn interface + +Column in a PointSeries + +Signature: + +```typescript +export interface PointSeriesColumn +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [expression](./kibana-plugin-plugins-expressions-server.pointseriescolumn.expression.md) | string | | +| [role](./kibana-plugin-plugins-expressions-server.pointseriescolumn.role.md) | 'measure' | 'dimension' | | +| [type](./kibana-plugin-plugins-expressions-server.pointseriescolumn.type.md) | 'number' | 'string' | | + diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.pointseriescolumn.role.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.pointseriescolumn.role.md new file mode 100644 index 0000000000000..1f6b770ecba15 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.pointseriescolumn.role.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [PointSeriesColumn](./kibana-plugin-plugins-expressions-server.pointseriescolumn.md) > [role](./kibana-plugin-plugins-expressions-server.pointseriescolumn.role.md) + +## PointSeriesColumn.role property + +Signature: + +```typescript +role: 'measure' | 'dimension'; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.pointseriescolumn.type.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.pointseriescolumn.type.md new file mode 100644 index 0000000000000..5cb51f460d722 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.pointseriescolumn.type.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [PointSeriesColumn](./kibana-plugin-plugins-expressions-server.pointseriescolumn.md) > [type](./kibana-plugin-plugins-expressions-server.pointseriescolumn.type.md) + +## PointSeriesColumn.type property + +Signature: + +```typescript +type: 'number' | 'string'; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.pointseriescolumnname.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.pointseriescolumnname.md new file mode 100644 index 0000000000000..2d8522b30903c --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.pointseriescolumnname.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [PointSeriesColumnName](./kibana-plugin-plugins-expressions-server.pointseriescolumnname.md) + +## PointSeriesColumnName type + +Allowed column names in a PointSeries + +Signature: + +```typescript +export declare type PointSeriesColumnName = 'x' | 'y' | 'color' | 'size' | 'text'; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.pointseriescolumns.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.pointseriescolumns.md new file mode 100644 index 0000000000000..f6eee6e2bc9d1 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.pointseriescolumns.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [PointSeriesColumns](./kibana-plugin-plugins-expressions-server.pointseriescolumns.md) + +## PointSeriesColumns type + +Represents a collection of valid Columns in a PointSeries + +Signature: + +```typescript +export declare type PointSeriesColumns = Record | {}; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.pointseriesrow.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.pointseriesrow.md new file mode 100644 index 0000000000000..d9a77305e9f99 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.pointseriesrow.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [PointSeriesRow](./kibana-plugin-plugins-expressions-server.pointseriesrow.md) + +## PointSeriesRow type + +Signature: + +```typescript +export declare type PointSeriesRow = Record; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.range.from.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.range.from.md new file mode 100644 index 0000000000000..f349681c1472f --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.range.from.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [Range](./kibana-plugin-plugins-expressions-server.range.md) > [from](./kibana-plugin-plugins-expressions-server.range.from.md) + +## Range.from property + +Signature: + +```typescript +from: number; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.range.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.range.md new file mode 100644 index 0000000000000..d369d882757fc --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.range.md @@ -0,0 +1,20 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [Range](./kibana-plugin-plugins-expressions-server.range.md) + +## Range interface + +Signature: + +```typescript +export interface Range +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [from](./kibana-plugin-plugins-expressions-server.range.from.md) | number | | +| [to](./kibana-plugin-plugins-expressions-server.range.to.md) | number | | +| [type](./kibana-plugin-plugins-expressions-server.range.type.md) | typeof name | | + diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.range.to.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.range.to.md new file mode 100644 index 0000000000000..c5a1fe2fe2080 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.range.to.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [Range](./kibana-plugin-plugins-expressions-server.range.md) > [to](./kibana-plugin-plugins-expressions-server.range.to.md) + +## Range.to property + +Signature: + +```typescript +to: number; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.range.type.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.range.type.md new file mode 100644 index 0000000000000..dd856dc0eb713 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.range.type.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [Range](./kibana-plugin-plugins-expressions-server.range.md) > [type](./kibana-plugin-plugins-expressions-server.range.type.md) + +## Range.type property + +Signature: + +```typescript +type: typeof name; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.serializeddatatable.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.serializeddatatable.md new file mode 100644 index 0000000000000..12951f9323503 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.serializeddatatable.md @@ -0,0 +1,18 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [SerializedDatatable](./kibana-plugin-plugins-expressions-server.serializeddatatable.md) + +## SerializedDatatable interface + +Signature: + +```typescript +export interface SerializedDatatable extends Datatable +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [rows](./kibana-plugin-plugins-expressions-server.serializeddatatable.rows.md) | string[][] | | + diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.serializeddatatable.rows.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.serializeddatatable.rows.md new file mode 100644 index 0000000000000..e82504f153f6b --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.serializeddatatable.rows.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [SerializedDatatable](./kibana-plugin-plugins-expressions-server.serializeddatatable.md) > [rows](./kibana-plugin-plugins-expressions-server.serializeddatatable.rows.md) + +## SerializedDatatable.rows property + +Signature: + +```typescript +rows: string[][]; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.serializedfieldformat.id.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.serializedfieldformat.id.md new file mode 100644 index 0000000000000..def3296aedcf7 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.serializedfieldformat.id.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [SerializedFieldFormat](./kibana-plugin-plugins-expressions-server.serializedfieldformat.md) > [id](./kibana-plugin-plugins-expressions-server.serializedfieldformat.id.md) + +## SerializedFieldFormat.id property + +Signature: + +```typescript +id?: string; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.serializedfieldformat.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.serializedfieldformat.md new file mode 100644 index 0000000000000..c62e830ccf7b9 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.serializedfieldformat.md @@ -0,0 +1,21 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [SerializedFieldFormat](./kibana-plugin-plugins-expressions-server.serializedfieldformat.md) + +## SerializedFieldFormat interface + +JSON representation of a field formatter configuration. Is used to carry information about how to format data in a data table as part of the column definition. + +Signature: + +```typescript +export interface SerializedFieldFormat> +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [id](./kibana-plugin-plugins-expressions-server.serializedfieldformat.id.md) | string | | +| [params](./kibana-plugin-plugins-expressions-server.serializedfieldformat.params.md) | TParams | | + diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.serializedfieldformat.params.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.serializedfieldformat.params.md new file mode 100644 index 0000000000000..8861f729aa2b1 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.serializedfieldformat.params.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [SerializedFieldFormat](./kibana-plugin-plugins-expressions-server.serializedfieldformat.md) > [params](./kibana-plugin-plugins-expressions-server.serializedfieldformat.params.md) + +## SerializedFieldFormat.params property + +Signature: + +```typescript +params?: TParams; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.style.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.style.md new file mode 100644 index 0000000000000..e43addfd5ff30 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.style.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [Style](./kibana-plugin-plugins-expressions-server.style.md) + +## Style type + +Signature: + +```typescript +export declare type Style = ExpressionTypeStyle; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.textalignment.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.textalignment.md new file mode 100644 index 0000000000000..2adc12371b4be --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.textalignment.md @@ -0,0 +1,23 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [TextAlignment](./kibana-plugin-plugins-expressions-server.textalignment.md) + +## TextAlignment enum + +Enum of supported CSS `text-align` properties. + +Signature: + +```typescript +export declare enum TextAlignment +``` + +## Enumeration Members + +| Member | Value | Description | +| --- | --- | --- | +| CENTER | "center" | | +| JUSTIFY | "justify" | | +| LEFT | "left" | | +| RIGHT | "right" | | + diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.textdecoration.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.textdecoration.md new file mode 100644 index 0000000000000..98d9b38547baf --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.textdecoration.md @@ -0,0 +1,21 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [TextDecoration](./kibana-plugin-plugins-expressions-server.textdecoration.md) + +## TextDecoration enum + +Enum of supported CSS `text-decoration` properties. + +Signature: + +```typescript +export declare enum TextDecoration +``` + +## Enumeration Members + +| Member | Value | Description | +| --- | --- | --- | +| NONE | "none" | | +| UNDERLINE | "underline" | | + diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.typesregistry._constructor_.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.typesregistry._constructor_.md new file mode 100644 index 0000000000000..87290d88214d0 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.typesregistry._constructor_.md @@ -0,0 +1,20 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [TypesRegistry](./kibana-plugin-plugins-expressions-server.typesregistry.md) > [(constructor)](./kibana-plugin-plugins-expressions-server.typesregistry._constructor_.md) + +## TypesRegistry.(constructor) + +Constructs a new instance of the `TypesRegistry` class + +Signature: + +```typescript +constructor(executor: Executor); +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| executor | Executor<any> | | + diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.typesregistry.get.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.typesregistry.get.md new file mode 100644 index 0000000000000..c8d674eab50cd --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.typesregistry.get.md @@ -0,0 +1,22 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [TypesRegistry](./kibana-plugin-plugins-expressions-server.typesregistry.md) > [get](./kibana-plugin-plugins-expressions-server.typesregistry.get.md) + +## TypesRegistry.get() method + +Signature: + +```typescript +get(id: string): ExpressionType | null; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| id | string | | + +Returns: + +`ExpressionType | null` + diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.typesregistry.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.typesregistry.md new file mode 100644 index 0000000000000..2c4d75e020035 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.typesregistry.md @@ -0,0 +1,27 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [TypesRegistry](./kibana-plugin-plugins-expressions-server.typesregistry.md) + +## TypesRegistry class + +Signature: + +```typescript +export declare class TypesRegistry implements IRegistry +``` + +## Constructors + +| Constructor | Modifiers | Description | +| --- | --- | --- | +| [(constructor)(executor)](./kibana-plugin-plugins-expressions-server.typesregistry._constructor_.md) | | Constructs a new instance of the TypesRegistry class | + +## Methods + +| Method | Modifiers | Description | +| --- | --- | --- | +| [get(id)](./kibana-plugin-plugins-expressions-server.typesregistry.get.md) | | | +| [register(typeDefinition)](./kibana-plugin-plugins-expressions-server.typesregistry.register.md) | | | +| [toArray()](./kibana-plugin-plugins-expressions-server.typesregistry.toarray.md) | | | +| [toJS()](./kibana-plugin-plugins-expressions-server.typesregistry.tojs.md) | | | + diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.typesregistry.register.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.typesregistry.register.md new file mode 100644 index 0000000000000..935a862407dfe --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.typesregistry.register.md @@ -0,0 +1,22 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [TypesRegistry](./kibana-plugin-plugins-expressions-server.typesregistry.md) > [register](./kibana-plugin-plugins-expressions-server.typesregistry.register.md) + +## TypesRegistry.register() method + +Signature: + +```typescript +register(typeDefinition: AnyExpressionTypeDefinition | (() => AnyExpressionTypeDefinition)): void; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| typeDefinition | AnyExpressionTypeDefinition | (() => AnyExpressionTypeDefinition) | | + +Returns: + +`void` + diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.typesregistry.toarray.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.typesregistry.toarray.md new file mode 100644 index 0000000000000..e3c6b13a22a58 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.typesregistry.toarray.md @@ -0,0 +1,15 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [TypesRegistry](./kibana-plugin-plugins-expressions-server.typesregistry.md) > [toArray](./kibana-plugin-plugins-expressions-server.typesregistry.toarray.md) + +## TypesRegistry.toArray() method + +Signature: + +```typescript +toArray(): ExpressionType[]; +``` +Returns: + +`ExpressionType[]` + diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.typesregistry.tojs.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.typesregistry.tojs.md new file mode 100644 index 0000000000000..2ff258bd54e44 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.typesregistry.tojs.md @@ -0,0 +1,15 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [TypesRegistry](./kibana-plugin-plugins-expressions-server.typesregistry.md) > [toJS](./kibana-plugin-plugins-expressions-server.typesregistry.tojs.md) + +## TypesRegistry.toJS() method + +Signature: + +```typescript +toJS(): Record; +``` +Returns: + +`Record` + diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.typestring.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.typestring.md new file mode 100644 index 0000000000000..af4d5ae0bf814 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.typestring.md @@ -0,0 +1,15 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [TypeString](./kibana-plugin-plugins-expressions-server.typestring.md) + +## TypeString type + +If the type extends a Promise, we still need to return the string representation: + +`someArgument: Promise` results in `types: ['boolean', 'string']` + +Signature: + +```typescript +export declare type TypeString = KnownTypeToString>; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.typetostring.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.typetostring.md new file mode 100644 index 0000000000000..578438c03a0e5 --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.typetostring.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [TypeToString](./kibana-plugin-plugins-expressions-server.typetostring.md) + +## TypeToString type + +This can convert a type into a known Expression string representation of that type. For example, `TypeToString` will resolve to `'datatable'`. This allows Expression Functions to continue to specify their type in a simple string format. + +Signature: + +```typescript +export declare type TypeToString = KnownTypeToString | UnmappedTypeStrings; +``` diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.unmappedtypestrings.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.unmappedtypestrings.md new file mode 100644 index 0000000000000..da872bfabce4f --- /dev/null +++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.unmappedtypestrings.md @@ -0,0 +1,15 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [UnmappedTypeStrings](./kibana-plugin-plugins-expressions-server.unmappedtypestrings.md) + +## UnmappedTypeStrings type + +Types used in Expressions that don't map to a primitive cleanly: + +`date` is typed as a number or string, and represents a date + +Signature: + +```typescript +export declare type UnmappedTypeStrings = 'date' | 'filter'; +``` diff --git a/docs/development/plugins/ui_actions/public/index.md b/docs/development/plugins/ui_actions/public/index.md new file mode 100644 index 0000000000000..cbc7035b880fa --- /dev/null +++ b/docs/development/plugins/ui_actions/public/index.md @@ -0,0 +1,12 @@ + + +[Home](./index.md) + +## API Reference + +## Packages + +| Package | Description | +| --- | --- | +| [kibana-plugin-plugins-ui\_actions-public](./kibana-plugin-plugins-ui_actions-public.md) | | + diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.action.execute.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.action.execute.md new file mode 100644 index 0000000000000..22a520123cf3f --- /dev/null +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.action.execute.md @@ -0,0 +1,24 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-ui\_actions-public](./kibana-plugin-plugins-ui_actions-public.md) > [Action](./kibana-plugin-plugins-ui_actions-public.action.md) > [execute](./kibana-plugin-plugins-ui_actions-public.action.execute.md) + +## Action.execute() method + +Executes the action. + +Signature: + +```typescript +execute(context: ActionExecutionContext): Promise; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| context | ActionExecutionContext<Context> | | + +Returns: + +`Promise` + diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.action.getdisplayname.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.action.getdisplayname.md new file mode 100644 index 0000000000000..cd8cc527e96ec --- /dev/null +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.action.getdisplayname.md @@ -0,0 +1,24 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-ui\_actions-public](./kibana-plugin-plugins-ui_actions-public.md) > [Action](./kibana-plugin-plugins-ui_actions-public.action.md) > [getDisplayName](./kibana-plugin-plugins-ui_actions-public.action.getdisplayname.md) + +## Action.getDisplayName() method + +Returns a title to be displayed to the user. + +Signature: + +```typescript +getDisplayName(context: ActionExecutionContext): string; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| context | ActionExecutionContext<Context> | | + +Returns: + +`string` + diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.action.gethref.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.action.gethref.md new file mode 100644 index 0000000000000..5ad9d5e24cf87 --- /dev/null +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.action.gethref.md @@ -0,0 +1,24 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-ui\_actions-public](./kibana-plugin-plugins-ui_actions-public.md) > [Action](./kibana-plugin-plugins-ui_actions-public.action.md) > [getHref](./kibana-plugin-plugins-ui_actions-public.action.gethref.md) + +## Action.getHref() method + +This method should return a link if this item can be clicked on. The link is used to navigate user if user middle-clicks it or Ctrl + clicks or right-clicks and selects "Open in new tab". + +Signature: + +```typescript +getHref?(context: ActionExecutionContext): Promise; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| context | ActionExecutionContext<Context> | | + +Returns: + +`Promise` + diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.action.geticontype.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.action.geticontype.md new file mode 100644 index 0000000000000..34d45c4ec75c2 --- /dev/null +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.action.geticontype.md @@ -0,0 +1,24 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-ui\_actions-public](./kibana-plugin-plugins-ui_actions-public.md) > [Action](./kibana-plugin-plugins-ui_actions-public.action.md) > [getIconType](./kibana-plugin-plugins-ui_actions-public.action.geticontype.md) + +## Action.getIconType() method + +Optional EUI icon type that can be displayed along with the title. + +Signature: + +```typescript +getIconType(context: ActionExecutionContext): string | undefined; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| context | ActionExecutionContext<Context> | | + +Returns: + +`string | undefined` + diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.action.id.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.action.id.md new file mode 100644 index 0000000000000..e32a5c8592cce --- /dev/null +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.action.id.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-ui\_actions-public](./kibana-plugin-plugins-ui_actions-public.md) > [Action](./kibana-plugin-plugins-ui_actions-public.action.md) > [id](./kibana-plugin-plugins-ui_actions-public.action.id.md) + +## Action.id property + +A unique identifier for this action instance. + +Signature: + +```typescript +id: string; +``` diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.action.iscompatible.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.action.iscompatible.md new file mode 100644 index 0000000000000..7a1f6cd23be17 --- /dev/null +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.action.iscompatible.md @@ -0,0 +1,24 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-ui\_actions-public](./kibana-plugin-plugins-ui_actions-public.md) > [Action](./kibana-plugin-plugins-ui_actions-public.action.md) > [isCompatible](./kibana-plugin-plugins-ui_actions-public.action.iscompatible.md) + +## Action.isCompatible() method + +Returns a promise that resolves to true if this action is compatible given the context, otherwise resolves to false. + +Signature: + +```typescript +isCompatible(context: ActionExecutionContext): Promise; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| context | ActionExecutionContext<Context> | | + +Returns: + +`Promise` + diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.action.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.action.md new file mode 100644 index 0000000000000..19af63a679de8 --- /dev/null +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.action.md @@ -0,0 +1,32 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-ui\_actions-public](./kibana-plugin-plugins-ui_actions-public.md) > [Action](./kibana-plugin-plugins-ui_actions-public.action.md) + +## Action interface + +Signature: + +```typescript +export interface Action extends Partial>> +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [id](./kibana-plugin-plugins-ui_actions-public.action.id.md) | string | A unique identifier for this action instance. | +| [MenuItem](./kibana-plugin-plugins-ui_actions-public.action.menuitem.md) | UiComponent<{
    context: ActionExecutionContext<Context>;
    }> | UiComponent to render when displaying this action as a context menu item. If not provided, getDisplayName will be used instead. | +| [order](./kibana-plugin-plugins-ui_actions-public.action.order.md) | number | Determined the order when there is more than one action matched to a trigger. Higher numbers are displayed first. | +| [type](./kibana-plugin-plugins-ui_actions-public.action.type.md) | T | The action type is what determines the context shape. | + +## Methods + +| Method | Description | +| --- | --- | +| [execute(context)](./kibana-plugin-plugins-ui_actions-public.action.execute.md) | Executes the action. | +| [getDisplayName(context)](./kibana-plugin-plugins-ui_actions-public.action.getdisplayname.md) | Returns a title to be displayed to the user. | +| [getHref(context)](./kibana-plugin-plugins-ui_actions-public.action.gethref.md) | This method should return a link if this item can be clicked on. The link is used to navigate user if user middle-clicks it or Ctrl + clicks or right-clicks and selects "Open in new tab". | +| [getIconType(context)](./kibana-plugin-plugins-ui_actions-public.action.geticontype.md) | Optional EUI icon type that can be displayed along with the title. | +| [isCompatible(context)](./kibana-plugin-plugins-ui_actions-public.action.iscompatible.md) | Returns a promise that resolves to true if this action is compatible given the context, otherwise resolves to false. | +| [shouldAutoExecute(context)](./kibana-plugin-plugins-ui_actions-public.action.shouldautoexecute.md) | Determines if action should be executed automatically, without first showing up in context menu. false by default. | + diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.action.menuitem.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.action.menuitem.md new file mode 100644 index 0000000000000..ac2168b88e3be --- /dev/null +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.action.menuitem.md @@ -0,0 +1,15 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-ui\_actions-public](./kibana-plugin-plugins-ui_actions-public.md) > [Action](./kibana-plugin-plugins-ui_actions-public.action.md) > [MenuItem](./kibana-plugin-plugins-ui_actions-public.action.menuitem.md) + +## Action.MenuItem property + +`UiComponent` to render when displaying this action as a context menu item. If not provided, `getDisplayName` will be used instead. + +Signature: + +```typescript +MenuItem?: UiComponent<{ + context: ActionExecutionContext; + }>; +``` diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.action.order.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.action.order.md new file mode 100644 index 0000000000000..ce9f66cfe5143 --- /dev/null +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.action.order.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-ui\_actions-public](./kibana-plugin-plugins-ui_actions-public.md) > [Action](./kibana-plugin-plugins-ui_actions-public.action.md) > [order](./kibana-plugin-plugins-ui_actions-public.action.order.md) + +## Action.order property + +Determined the order when there is more than one action matched to a trigger. Higher numbers are displayed first. + +Signature: + +```typescript +order?: number; +``` diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.action.shouldautoexecute.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.action.shouldautoexecute.md new file mode 100644 index 0000000000000..1a784f5dad2d5 --- /dev/null +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.action.shouldautoexecute.md @@ -0,0 +1,24 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-ui\_actions-public](./kibana-plugin-plugins-ui_actions-public.md) > [Action](./kibana-plugin-plugins-ui_actions-public.action.md) > [shouldAutoExecute](./kibana-plugin-plugins-ui_actions-public.action.shouldautoexecute.md) + +## Action.shouldAutoExecute() method + +Determines if action should be executed automatically, without first showing up in context menu. false by default. + +Signature: + +```typescript +shouldAutoExecute?(context: ActionExecutionContext): Promise; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| context | ActionExecutionContext<Context> | | + +Returns: + +`Promise` + diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.action.type.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.action.type.md new file mode 100644 index 0000000000000..c423df9d1324c --- /dev/null +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.action.type.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-ui\_actions-public](./kibana-plugin-plugins-ui_actions-public.md) > [Action](./kibana-plugin-plugins-ui_actions-public.action.md) > [type](./kibana-plugin-plugins-ui_actions-public.action.type.md) + +## Action.type property + +The action type is what determines the context shape. + +Signature: + +```typescript +readonly type: T; +``` diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.action_visualize_field.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.action_visualize_field.md new file mode 100644 index 0000000000000..25788d7aecc9f --- /dev/null +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.action_visualize_field.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-ui\_actions-public](./kibana-plugin-plugins-ui_actions-public.md) > [ACTION\_VISUALIZE\_FIELD](./kibana-plugin-plugins-ui_actions-public.action_visualize_field.md) + +## ACTION\_VISUALIZE\_FIELD variable + +Signature: + +```typescript +ACTION_VISUALIZE_FIELD = "ACTION_VISUALIZE_FIELD" +``` diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.action_visualize_geo_field.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.action_visualize_geo_field.md new file mode 100644 index 0000000000000..c9ef93eff934b --- /dev/null +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.action_visualize_geo_field.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-ui\_actions-public](./kibana-plugin-plugins-ui_actions-public.md) > [ACTION\_VISUALIZE\_GEO\_FIELD](./kibana-plugin-plugins-ui_actions-public.action_visualize_geo_field.md) + +## ACTION\_VISUALIZE\_GEO\_FIELD variable + +Signature: + +```typescript +ACTION_VISUALIZE_GEO_FIELD = "ACTION_VISUALIZE_GEO_FIELD" +``` diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.action_visualize_lens_field.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.action_visualize_lens_field.md new file mode 100644 index 0000000000000..b00618f510510 --- /dev/null +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.action_visualize_lens_field.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-ui\_actions-public](./kibana-plugin-plugins-ui_actions-public.md) > [ACTION\_VISUALIZE\_LENS\_FIELD](./kibana-plugin-plugins-ui_actions-public.action_visualize_lens_field.md) + +## ACTION\_VISUALIZE\_LENS\_FIELD variable + +Signature: + +```typescript +ACTION_VISUALIZE_LENS_FIELD = "ACTION_VISUALIZE_LENS_FIELD" +``` diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.actionbytype.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.actionbytype.md new file mode 100644 index 0000000000000..3ceb96adadb1a --- /dev/null +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.actionbytype.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-ui\_actions-public](./kibana-plugin-plugins-ui_actions-public.md) > [ActionByType](./kibana-plugin-plugins-ui_actions-public.actionbytype.md) + +## ActionByType type + +Signature: + +```typescript +export declare type ActionByType = Action; +``` diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.actioncontextmapping.__.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.actioncontextmapping.__.md new file mode 100644 index 0000000000000..eb7b1e5954ed2 --- /dev/null +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.actioncontextmapping.__.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-ui\_actions-public](./kibana-plugin-plugins-ui_actions-public.md) > [ActionContextMapping](./kibana-plugin-plugins-ui_actions-public.actioncontextmapping.md) > [""](./kibana-plugin-plugins-ui_actions-public.actioncontextmapping.__.md) + +## ActionContextMapping."" property + +Signature: + +```typescript +[DEFAULT_ACTION]: BaseContext; +``` diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.actioncontextmapping.action_visualize_field.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.actioncontextmapping.action_visualize_field.md new file mode 100644 index 0000000000000..eb0547bbf8261 --- /dev/null +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.actioncontextmapping.action_visualize_field.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-ui\_actions-public](./kibana-plugin-plugins-ui_actions-public.md) > [ActionContextMapping](./kibana-plugin-plugins-ui_actions-public.actioncontextmapping.md) > [ACTION\_VISUALIZE\_FIELD](./kibana-plugin-plugins-ui_actions-public.actioncontextmapping.action_visualize_field.md) + +## ActionContextMapping.ACTION\_VISUALIZE\_FIELD property + +Signature: + +```typescript +[ACTION_VISUALIZE_FIELD]: VisualizeFieldContext; +``` diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.actioncontextmapping.action_visualize_geo_field.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.actioncontextmapping.action_visualize_geo_field.md new file mode 100644 index 0000000000000..b44ed75106423 --- /dev/null +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.actioncontextmapping.action_visualize_geo_field.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-ui\_actions-public](./kibana-plugin-plugins-ui_actions-public.md) > [ActionContextMapping](./kibana-plugin-plugins-ui_actions-public.actioncontextmapping.md) > [ACTION\_VISUALIZE\_GEO\_FIELD](./kibana-plugin-plugins-ui_actions-public.actioncontextmapping.action_visualize_geo_field.md) + +## ActionContextMapping.ACTION\_VISUALIZE\_GEO\_FIELD property + +Signature: + +```typescript +[ACTION_VISUALIZE_GEO_FIELD]: VisualizeFieldContext; +``` diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.actioncontextmapping.action_visualize_lens_field.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.actioncontextmapping.action_visualize_lens_field.md new file mode 100644 index 0000000000000..96370a07806d3 --- /dev/null +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.actioncontextmapping.action_visualize_lens_field.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-ui\_actions-public](./kibana-plugin-plugins-ui_actions-public.md) > [ActionContextMapping](./kibana-plugin-plugins-ui_actions-public.actioncontextmapping.md) > [ACTION\_VISUALIZE\_LENS\_FIELD](./kibana-plugin-plugins-ui_actions-public.actioncontextmapping.action_visualize_lens_field.md) + +## ActionContextMapping.ACTION\_VISUALIZE\_LENS\_FIELD property + +Signature: + +```typescript +[ACTION_VISUALIZE_LENS_FIELD]: VisualizeFieldContext; +``` diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.actioncontextmapping.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.actioncontextmapping.md new file mode 100644 index 0000000000000..f83632dea0aa9 --- /dev/null +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.actioncontextmapping.md @@ -0,0 +1,21 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-ui\_actions-public](./kibana-plugin-plugins-ui_actions-public.md) > [ActionContextMapping](./kibana-plugin-plugins-ui_actions-public.actioncontextmapping.md) + +## ActionContextMapping interface + +Signature: + +```typescript +export interface ActionContextMapping +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [""](./kibana-plugin-plugins-ui_actions-public.actioncontextmapping.__.md) | BaseContext | | +| [ACTION\_VISUALIZE\_FIELD](./kibana-plugin-plugins-ui_actions-public.actioncontextmapping.action_visualize_field.md) | VisualizeFieldContext | | +| [ACTION\_VISUALIZE\_GEO\_FIELD](./kibana-plugin-plugins-ui_actions-public.actioncontextmapping.action_visualize_geo_field.md) | VisualizeFieldContext | | +| [ACTION\_VISUALIZE\_LENS\_FIELD](./kibana-plugin-plugins-ui_actions-public.actioncontextmapping.action_visualize_lens_field.md) | VisualizeFieldContext | | + diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.actiondefinitionbytype.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.actiondefinitionbytype.md new file mode 100644 index 0000000000000..ba4dc39088fe4 --- /dev/null +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.actiondefinitionbytype.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-ui\_actions-public](./kibana-plugin-plugins-ui_actions-public.md) > [ActionDefinitionByType](./kibana-plugin-plugins-ui_actions-public.actiondefinitionbytype.md) + +## ActionDefinitionByType type + +Signature: + +```typescript +export declare type ActionDefinitionByType = ActionDefinition; +``` diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.actionexecutioncontext.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.actionexecutioncontext.md new file mode 100644 index 0000000000000..3271d86779959 --- /dev/null +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.actionexecutioncontext.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-ui\_actions-public](./kibana-plugin-plugins-ui_actions-public.md) > [ActionExecutionContext](./kibana-plugin-plugins-ui_actions-public.actionexecutioncontext.md) + +## ActionExecutionContext type + +Action methods are executed with Context from trigger + [ActionExecutionMeta](./kibana-plugin-plugins-ui_actions-public.actionexecutionmeta.md) + +Signature: + +```typescript +export declare type ActionExecutionContext = Context & ActionExecutionMeta; +``` diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.actionexecutionmeta.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.actionexecutionmeta.md new file mode 100644 index 0000000000000..2056d8f9c7fc6 --- /dev/null +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.actionexecutionmeta.md @@ -0,0 +1,20 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-ui\_actions-public](./kibana-plugin-plugins-ui_actions-public.md) > [ActionExecutionMeta](./kibana-plugin-plugins-ui_actions-public.actionexecutionmeta.md) + +## ActionExecutionMeta interface + +During action execution we can provide additional information, for example, trigger, that caused the action execution + +Signature: + +```typescript +export interface ActionExecutionMeta +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [trigger](./kibana-plugin-plugins-ui_actions-public.actionexecutionmeta.trigger.md) | Trigger | Trigger that executed the action | + diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.actionexecutionmeta.trigger.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.actionexecutionmeta.trigger.md new file mode 100644 index 0000000000000..530c2fe514d2c --- /dev/null +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.actionexecutionmeta.trigger.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-ui\_actions-public](./kibana-plugin-plugins-ui_actions-public.md) > [ActionExecutionMeta](./kibana-plugin-plugins-ui_actions-public.actionexecutionmeta.md) > [trigger](./kibana-plugin-plugins-ui_actions-public.actionexecutionmeta.trigger.md) + +## ActionExecutionMeta.trigger property + +Trigger that executed the action + +Signature: + +```typescript +trigger: Trigger; +``` diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.actiontype.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.actiontype.md new file mode 100644 index 0000000000000..4916585531004 --- /dev/null +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.actiontype.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-ui\_actions-public](./kibana-plugin-plugins-ui_actions-public.md) > [ActionType](./kibana-plugin-plugins-ui_actions-public.actiontype.md) + +## ActionType type + +Signature: + +```typescript +export declare type ActionType = keyof ActionContextMapping; +``` diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.apply_filter_trigger.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.apply_filter_trigger.md new file mode 100644 index 0000000000000..94e66bf404f5c --- /dev/null +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.apply_filter_trigger.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-ui\_actions-public](./kibana-plugin-plugins-ui_actions-public.md) > [APPLY\_FILTER\_TRIGGER](./kibana-plugin-plugins-ui_actions-public.apply_filter_trigger.md) + +## APPLY\_FILTER\_TRIGGER variable + +Signature: + +```typescript +APPLY_FILTER_TRIGGER = "FILTER_TRIGGER" +``` diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.applyfiltertrigger.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.applyfiltertrigger.md new file mode 100644 index 0000000000000..e1fb6d342457e --- /dev/null +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.applyfiltertrigger.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-ui\_actions-public](./kibana-plugin-plugins-ui_actions-public.md) > [applyFilterTrigger](./kibana-plugin-plugins-ui_actions-public.applyfiltertrigger.md) + +## applyFilterTrigger variable + +Signature: + +```typescript +applyFilterTrigger: Trigger<'FILTER_TRIGGER'> +``` diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.buildcontextmenuforactions.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.buildcontextmenuforactions.md new file mode 100644 index 0000000000000..2d6c0ff106072 --- /dev/null +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.buildcontextmenuforactions.md @@ -0,0 +1,24 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-ui\_actions-public](./kibana-plugin-plugins-ui_actions-public.md) > [buildContextMenuForActions](./kibana-plugin-plugins-ui_actions-public.buildcontextmenuforactions.md) + +## buildContextMenuForActions() function + +Transforms an array of Actions to the shape EuiContextMenuPanel expects. + +Signature: + +```typescript +export declare function buildContextMenuForActions({ actions, title, closeMenu, }: BuildContextMenuParams): Promise; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| { actions, title, closeMenu, } | BuildContextMenuParams | | + +Returns: + +`Promise` + diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.createaction.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.createaction.md new file mode 100644 index 0000000000000..04ab36c2e3f58 --- /dev/null +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.createaction.md @@ -0,0 +1,22 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-ui\_actions-public](./kibana-plugin-plugins-ui_actions-public.md) > [createAction](./kibana-plugin-plugins-ui_actions-public.createaction.md) + +## createAction() function + +Signature: + +```typescript +export declare function createAction(action: ActionDefinitionByType): ActionByType; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| action | ActionDefinitionByType<T> | | + +Returns: + +`ActionByType` + diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.incompatibleactionerror._constructor_.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.incompatibleactionerror._constructor_.md new file mode 100644 index 0000000000000..f06bb05270ff0 --- /dev/null +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.incompatibleactionerror._constructor_.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-ui\_actions-public](./kibana-plugin-plugins-ui_actions-public.md) > [IncompatibleActionError](./kibana-plugin-plugins-ui_actions-public.incompatibleactionerror.md) > [(constructor)](./kibana-plugin-plugins-ui_actions-public.incompatibleactionerror._constructor_.md) + +## IncompatibleActionError.(constructor) + +Constructs a new instance of the `IncompatibleActionError` class + +Signature: + +```typescript +constructor(); +``` diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.incompatibleactionerror.code.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.incompatibleactionerror.code.md new file mode 100644 index 0000000000000..f16aa47438d72 --- /dev/null +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.incompatibleactionerror.code.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-ui\_actions-public](./kibana-plugin-plugins-ui_actions-public.md) > [IncompatibleActionError](./kibana-plugin-plugins-ui_actions-public.incompatibleactionerror.md) > [code](./kibana-plugin-plugins-ui_actions-public.incompatibleactionerror.code.md) + +## IncompatibleActionError.code property + +Signature: + +```typescript +code: string; +``` diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.incompatibleactionerror.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.incompatibleactionerror.md new file mode 100644 index 0000000000000..7c9943a53c2bb --- /dev/null +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.incompatibleactionerror.md @@ -0,0 +1,24 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-ui\_actions-public](./kibana-plugin-plugins-ui_actions-public.md) > [IncompatibleActionError](./kibana-plugin-plugins-ui_actions-public.incompatibleactionerror.md) + +## IncompatibleActionError class + +Signature: + +```typescript +export declare class IncompatibleActionError extends Error +``` + +## Constructors + +| Constructor | Modifiers | Description | +| --- | --- | --- | +| [(constructor)()](./kibana-plugin-plugins-ui_actions-public.incompatibleactionerror._constructor_.md) | | Constructs a new instance of the IncompatibleActionError class | + +## Properties + +| Property | Modifiers | Type | Description | +| --- | --- | --- | --- | +| [code](./kibana-plugin-plugins-ui_actions-public.incompatibleactionerror.code.md) | | string | | + diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.md new file mode 100644 index 0000000000000..5e10de4e0f2a5 --- /dev/null +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.md @@ -0,0 +1,67 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-ui\_actions-public](./kibana-plugin-plugins-ui_actions-public.md) + +## kibana-plugin-plugins-ui\_actions-public package + +## Classes + +| Class | Description | +| --- | --- | +| [IncompatibleActionError](./kibana-plugin-plugins-ui_actions-public.incompatibleactionerror.md) | | +| [UiActionsService](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.md) | | + +## Functions + +| Function | Description | +| --- | --- | +| [buildContextMenuForActions({ actions, title, closeMenu, })](./kibana-plugin-plugins-ui_actions-public.buildcontextmenuforactions.md) | Transforms an array of Actions to the shape EuiContextMenuPanel expects. | +| [createAction(action)](./kibana-plugin-plugins-ui_actions-public.createaction.md) | | +| [plugin(initializerContext)](./kibana-plugin-plugins-ui_actions-public.plugin.md) | | + +## Interfaces + +| Interface | Description | +| --- | --- | +| [Action](./kibana-plugin-plugins-ui_actions-public.action.md) | | +| [ActionContextMapping](./kibana-plugin-plugins-ui_actions-public.actioncontextmapping.md) | | +| [ActionExecutionMeta](./kibana-plugin-plugins-ui_actions-public.actionexecutionmeta.md) | During action execution we can provide additional information, for example, trigger, that caused the action execution | +| [Trigger](./kibana-plugin-plugins-ui_actions-public.trigger.md) | This is a convenience interface used to register a \*trigger\*.Trigger specifies a named anchor to which Action can be attached. When Trigger is being \*called\* it creates a Context object and passes it to the execute method of an Action.More than one action can be attached to a single trigger, in which case when trigger is \*called\* it first displays a context menu for user to pick a single action to execute. | +| [TriggerContextMapping](./kibana-plugin-plugins-ui_actions-public.triggercontextmapping.md) | | +| [UiActionsActionDefinition](./kibana-plugin-plugins-ui_actions-public.uiactionsactiondefinition.md) | A convenience interface used to register an action. | +| [UiActionsPresentable](./kibana-plugin-plugins-ui_actions-public.uiactionspresentable.md) | Represents something that can be displayed to user in UI. | +| [UiActionsServiceParams](./kibana-plugin-plugins-ui_actions-public.uiactionsserviceparams.md) | | +| [VisualizeFieldContext](./kibana-plugin-plugins-ui_actions-public.visualizefieldcontext.md) | | + +## Variables + +| Variable | Description | +| --- | --- | +| [ACTION\_VISUALIZE\_FIELD](./kibana-plugin-plugins-ui_actions-public.action_visualize_field.md) | | +| [ACTION\_VISUALIZE\_GEO\_FIELD](./kibana-plugin-plugins-ui_actions-public.action_visualize_geo_field.md) | | +| [ACTION\_VISUALIZE\_LENS\_FIELD](./kibana-plugin-plugins-ui_actions-public.action_visualize_lens_field.md) | | +| [APPLY\_FILTER\_TRIGGER](./kibana-plugin-plugins-ui_actions-public.apply_filter_trigger.md) | | +| [applyFilterTrigger](./kibana-plugin-plugins-ui_actions-public.applyfiltertrigger.md) | | +| [SELECT\_RANGE\_TRIGGER](./kibana-plugin-plugins-ui_actions-public.select_range_trigger.md) | | +| [selectRangeTrigger](./kibana-plugin-plugins-ui_actions-public.selectrangetrigger.md) | | +| [VALUE\_CLICK\_TRIGGER](./kibana-plugin-plugins-ui_actions-public.value_click_trigger.md) | | +| [valueClickTrigger](./kibana-plugin-plugins-ui_actions-public.valueclicktrigger.md) | | +| [VISUALIZE\_FIELD\_TRIGGER](./kibana-plugin-plugins-ui_actions-public.visualize_field_trigger.md) | | +| [VISUALIZE\_GEO\_FIELD\_TRIGGER](./kibana-plugin-plugins-ui_actions-public.visualize_geo_field_trigger.md) | | +| [visualizeFieldTrigger](./kibana-plugin-plugins-ui_actions-public.visualizefieldtrigger.md) | | +| [visualizeGeoFieldTrigger](./kibana-plugin-plugins-ui_actions-public.visualizegeofieldtrigger.md) | | + +## Type Aliases + +| Type Alias | Description | +| --- | --- | +| [ActionByType](./kibana-plugin-plugins-ui_actions-public.actionbytype.md) | | +| [ActionDefinitionByType](./kibana-plugin-plugins-ui_actions-public.actiondefinitionbytype.md) | | +| [ActionExecutionContext](./kibana-plugin-plugins-ui_actions-public.actionexecutioncontext.md) | Action methods are executed with Context from trigger + [ActionExecutionMeta](./kibana-plugin-plugins-ui_actions-public.actionexecutionmeta.md) | +| [ActionType](./kibana-plugin-plugins-ui_actions-public.actiontype.md) | | +| [TriggerContext](./kibana-plugin-plugins-ui_actions-public.triggercontext.md) | | +| [TriggerId](./kibana-plugin-plugins-ui_actions-public.triggerid.md) | | +| [UiActionsPresentableGrouping](./kibana-plugin-plugins-ui_actions-public.uiactionspresentablegrouping.md) | | +| [UiActionsSetup](./kibana-plugin-plugins-ui_actions-public.uiactionssetup.md) | | +| [UiActionsStart](./kibana-plugin-plugins-ui_actions-public.uiactionsstart.md) | | + diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.plugin.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.plugin.md new file mode 100644 index 0000000000000..d9427317d4fc6 --- /dev/null +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.plugin.md @@ -0,0 +1,22 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-ui\_actions-public](./kibana-plugin-plugins-ui_actions-public.md) > [plugin](./kibana-plugin-plugins-ui_actions-public.plugin.md) + +## plugin() function + +Signature: + +```typescript +export declare function plugin(initializerContext: PluginInitializerContext): UiActionsPlugin; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| initializerContext | PluginInitializerContext | | + +Returns: + +`UiActionsPlugin` + diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.select_range_trigger.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.select_range_trigger.md new file mode 100644 index 0000000000000..fd784ff17fa84 --- /dev/null +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.select_range_trigger.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-ui\_actions-public](./kibana-plugin-plugins-ui_actions-public.md) > [SELECT\_RANGE\_TRIGGER](./kibana-plugin-plugins-ui_actions-public.select_range_trigger.md) + +## SELECT\_RANGE\_TRIGGER variable + +Signature: + +```typescript +SELECT_RANGE_TRIGGER = "SELECT_RANGE_TRIGGER" +``` diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.selectrangetrigger.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.selectrangetrigger.md new file mode 100644 index 0000000000000..0d9fa2d83ee57 --- /dev/null +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.selectrangetrigger.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-ui\_actions-public](./kibana-plugin-plugins-ui_actions-public.md) > [selectRangeTrigger](./kibana-plugin-plugins-ui_actions-public.selectrangetrigger.md) + +## selectRangeTrigger variable + +Signature: + +```typescript +selectRangeTrigger: Trigger<'SELECT_RANGE_TRIGGER'> +``` diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.trigger.description.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.trigger.description.md new file mode 100644 index 0000000000000..76faaf8e1a691 --- /dev/null +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.trigger.description.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-ui\_actions-public](./kibana-plugin-plugins-ui_actions-public.md) > [Trigger](./kibana-plugin-plugins-ui_actions-public.trigger.md) > [description](./kibana-plugin-plugins-ui_actions-public.trigger.description.md) + +## Trigger.description property + +A longer user friendly description of the trigger. + +Signature: + +```typescript +description?: string; +``` diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.trigger.id.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.trigger.id.md new file mode 100644 index 0000000000000..426f17f9a0352 --- /dev/null +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.trigger.id.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-ui\_actions-public](./kibana-plugin-plugins-ui_actions-public.md) > [Trigger](./kibana-plugin-plugins-ui_actions-public.trigger.md) > [id](./kibana-plugin-plugins-ui_actions-public.trigger.id.md) + +## Trigger.id property + +Unique name of the trigger as identified in `ui_actions` plugin trigger registry, such as "SELECT\_RANGE\_TRIGGER" or "VALUE\_CLICK\_TRIGGER". + +Signature: + +```typescript +id: ID; +``` diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.trigger.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.trigger.md new file mode 100644 index 0000000000000..b69bba892f475 --- /dev/null +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.trigger.md @@ -0,0 +1,26 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-ui\_actions-public](./kibana-plugin-plugins-ui_actions-public.md) > [Trigger](./kibana-plugin-plugins-ui_actions-public.trigger.md) + +## Trigger interface + +This is a convenience interface used to register a \*trigger\*. + +`Trigger` specifies a named anchor to which `Action` can be attached. When `Trigger` is being \*called\* it creates a `Context` object and passes it to the `execute` method of an `Action`. + +More than one action can be attached to a single trigger, in which case when trigger is \*called\* it first displays a context menu for user to pick a single action to execute. + +Signature: + +```typescript +export interface Trigger +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [description](./kibana-plugin-plugins-ui_actions-public.trigger.description.md) | string | A longer user friendly description of the trigger. | +| [id](./kibana-plugin-plugins-ui_actions-public.trigger.id.md) | ID | Unique name of the trigger as identified in ui_actions plugin trigger registry, such as "SELECT\_RANGE\_TRIGGER" or "VALUE\_CLICK\_TRIGGER". | +| [title](./kibana-plugin-plugins-ui_actions-public.trigger.title.md) | string | User friendly name of the trigger. | + diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.trigger.title.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.trigger.title.md new file mode 100644 index 0000000000000..ded71c8d0c437 --- /dev/null +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.trigger.title.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-ui\_actions-public](./kibana-plugin-plugins-ui_actions-public.md) > [Trigger](./kibana-plugin-plugins-ui_actions-public.trigger.md) > [title](./kibana-plugin-plugins-ui_actions-public.trigger.title.md) + +## Trigger.title property + +User friendly name of the trigger. + +Signature: + +```typescript +title?: string; +``` diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.triggercontext.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.triggercontext.md new file mode 100644 index 0000000000000..4ce95d27ecffa --- /dev/null +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.triggercontext.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-ui\_actions-public](./kibana-plugin-plugins-ui_actions-public.md) > [TriggerContext](./kibana-plugin-plugins-ui_actions-public.triggercontext.md) + +## TriggerContext type + +Signature: + +```typescript +export declare type TriggerContext = T extends TriggerId ? TriggerContextMapping[T] : never; +``` diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.triggercontextmapping.__.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.triggercontextmapping.__.md new file mode 100644 index 0000000000000..17ad926f8ee82 --- /dev/null +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.triggercontextmapping.__.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-ui\_actions-public](./kibana-plugin-plugins-ui_actions-public.md) > [TriggerContextMapping](./kibana-plugin-plugins-ui_actions-public.triggercontextmapping.md) > [""](./kibana-plugin-plugins-ui_actions-public.triggercontextmapping.__.md) + +## TriggerContextMapping."" property + +Signature: + +```typescript +[DEFAULT_TRIGGER]: TriggerContext; +``` diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.triggercontextmapping.filter_trigger.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.triggercontextmapping.filter_trigger.md new file mode 100644 index 0000000000000..0ccf8aa3d7415 --- /dev/null +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.triggercontextmapping.filter_trigger.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-ui\_actions-public](./kibana-plugin-plugins-ui_actions-public.md) > [TriggerContextMapping](./kibana-plugin-plugins-ui_actions-public.triggercontextmapping.md) > [FILTER\_TRIGGER](./kibana-plugin-plugins-ui_actions-public.triggercontextmapping.filter_trigger.md) + +## TriggerContextMapping.FILTER\_TRIGGER property + +Signature: + +```typescript +[APPLY_FILTER_TRIGGER]: ApplyGlobalFilterActionContext; +``` diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.triggercontextmapping.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.triggercontextmapping.md new file mode 100644 index 0000000000000..9db44d4dc7b05 --- /dev/null +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.triggercontextmapping.md @@ -0,0 +1,23 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-ui\_actions-public](./kibana-plugin-plugins-ui_actions-public.md) > [TriggerContextMapping](./kibana-plugin-plugins-ui_actions-public.triggercontextmapping.md) + +## TriggerContextMapping interface + +Signature: + +```typescript +export interface TriggerContextMapping +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [""](./kibana-plugin-plugins-ui_actions-public.triggercontextmapping.__.md) | TriggerContext | | +| [FILTER\_TRIGGER](./kibana-plugin-plugins-ui_actions-public.triggercontextmapping.filter_trigger.md) | ApplyGlobalFilterActionContext | | +| [SELECT\_RANGE\_TRIGGER](./kibana-plugin-plugins-ui_actions-public.triggercontextmapping.select_range_trigger.md) | RangeSelectContext | | +| [VALUE\_CLICK\_TRIGGER](./kibana-plugin-plugins-ui_actions-public.triggercontextmapping.value_click_trigger.md) | ValueClickContext | | +| [VISUALIZE\_FIELD\_TRIGGER](./kibana-plugin-plugins-ui_actions-public.triggercontextmapping.visualize_field_trigger.md) | VisualizeFieldContext | | +| [VISUALIZE\_GEO\_FIELD\_TRIGGER](./kibana-plugin-plugins-ui_actions-public.triggercontextmapping.visualize_geo_field_trigger.md) | VisualizeFieldContext | | + diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.triggercontextmapping.select_range_trigger.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.triggercontextmapping.select_range_trigger.md new file mode 100644 index 0000000000000..c5ef6843390b3 --- /dev/null +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.triggercontextmapping.select_range_trigger.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-ui\_actions-public](./kibana-plugin-plugins-ui_actions-public.md) > [TriggerContextMapping](./kibana-plugin-plugins-ui_actions-public.triggercontextmapping.md) > [SELECT\_RANGE\_TRIGGER](./kibana-plugin-plugins-ui_actions-public.triggercontextmapping.select_range_trigger.md) + +## TriggerContextMapping.SELECT\_RANGE\_TRIGGER property + +Signature: + +```typescript +[SELECT_RANGE_TRIGGER]: RangeSelectContext; +``` diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.triggercontextmapping.value_click_trigger.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.triggercontextmapping.value_click_trigger.md new file mode 100644 index 0000000000000..129144a66cee5 --- /dev/null +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.triggercontextmapping.value_click_trigger.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-ui\_actions-public](./kibana-plugin-plugins-ui_actions-public.md) > [TriggerContextMapping](./kibana-plugin-plugins-ui_actions-public.triggercontextmapping.md) > [VALUE\_CLICK\_TRIGGER](./kibana-plugin-plugins-ui_actions-public.triggercontextmapping.value_click_trigger.md) + +## TriggerContextMapping.VALUE\_CLICK\_TRIGGER property + +Signature: + +```typescript +[VALUE_CLICK_TRIGGER]: ValueClickContext; +``` diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.triggercontextmapping.visualize_field_trigger.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.triggercontextmapping.visualize_field_trigger.md new file mode 100644 index 0000000000000..feaaffac8a234 --- /dev/null +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.triggercontextmapping.visualize_field_trigger.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-ui\_actions-public](./kibana-plugin-plugins-ui_actions-public.md) > [TriggerContextMapping](./kibana-plugin-plugins-ui_actions-public.triggercontextmapping.md) > [VISUALIZE\_FIELD\_TRIGGER](./kibana-plugin-plugins-ui_actions-public.triggercontextmapping.visualize_field_trigger.md) + +## TriggerContextMapping.VISUALIZE\_FIELD\_TRIGGER property + +Signature: + +```typescript +[VISUALIZE_FIELD_TRIGGER]: VisualizeFieldContext; +``` diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.triggercontextmapping.visualize_geo_field_trigger.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.triggercontextmapping.visualize_geo_field_trigger.md new file mode 100644 index 0000000000000..023490a2ae027 --- /dev/null +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.triggercontextmapping.visualize_geo_field_trigger.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-ui\_actions-public](./kibana-plugin-plugins-ui_actions-public.md) > [TriggerContextMapping](./kibana-plugin-plugins-ui_actions-public.triggercontextmapping.md) > [VISUALIZE\_GEO\_FIELD\_TRIGGER](./kibana-plugin-plugins-ui_actions-public.triggercontextmapping.visualize_geo_field_trigger.md) + +## TriggerContextMapping.VISUALIZE\_GEO\_FIELD\_TRIGGER property + +Signature: + +```typescript +[VISUALIZE_GEO_FIELD_TRIGGER]: VisualizeFieldContext; +``` diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.triggerid.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.triggerid.md new file mode 100644 index 0000000000000..6e5a234e286f9 --- /dev/null +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.triggerid.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-ui\_actions-public](./kibana-plugin-plugins-ui_actions-public.md) > [TriggerId](./kibana-plugin-plugins-ui_actions-public.triggerid.md) + +## TriggerId type + +Signature: + +```typescript +export declare type TriggerId = keyof TriggerContextMapping; +``` diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsactiondefinition.execute.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsactiondefinition.execute.md new file mode 100644 index 0000000000000..a2cf61ecc1306 --- /dev/null +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsactiondefinition.execute.md @@ -0,0 +1,24 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-ui\_actions-public](./kibana-plugin-plugins-ui_actions-public.md) > [UiActionsActionDefinition](./kibana-plugin-plugins-ui_actions-public.uiactionsactiondefinition.md) > [execute](./kibana-plugin-plugins-ui_actions-public.uiactionsactiondefinition.execute.md) + +## UiActionsActionDefinition.execute() method + +Executes the action. + +Signature: + +```typescript +execute(context: ActionDefinitionContext): Promise; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| context | ActionDefinitionContext<Context> | | + +Returns: + +`Promise` + diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsactiondefinition.gethref.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsactiondefinition.gethref.md new file mode 100644 index 0000000000000..83fee1233a206 --- /dev/null +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsactiondefinition.gethref.md @@ -0,0 +1,24 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-ui\_actions-public](./kibana-plugin-plugins-ui_actions-public.md) > [UiActionsActionDefinition](./kibana-plugin-plugins-ui_actions-public.uiactionsactiondefinition.md) > [getHref](./kibana-plugin-plugins-ui_actions-public.uiactionsactiondefinition.gethref.md) + +## UiActionsActionDefinition.getHref() method + +This method should return a link if this item can be clicked on. The link is used to navigate user if user middle-clicks it or Ctrl + clicks or right-clicks and selects "Open in new tab". + +Signature: + +```typescript +getHref?(context: ActionDefinitionContext): Promise; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| context | ActionDefinitionContext<Context> | | + +Returns: + +`Promise` + diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsactiondefinition.id.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsactiondefinition.id.md new file mode 100644 index 0000000000000..01fa6abce3b4a --- /dev/null +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsactiondefinition.id.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-ui\_actions-public](./kibana-plugin-plugins-ui_actions-public.md) > [UiActionsActionDefinition](./kibana-plugin-plugins-ui_actions-public.uiactionsactiondefinition.md) > [id](./kibana-plugin-plugins-ui_actions-public.uiactionsactiondefinition.id.md) + +## UiActionsActionDefinition.id property + +ID of the action that uniquely identifies this action in the actions registry. + +Signature: + +```typescript +readonly id: string; +``` diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsactiondefinition.iscompatible.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsactiondefinition.iscompatible.md new file mode 100644 index 0000000000000..736cc40c4243f --- /dev/null +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsactiondefinition.iscompatible.md @@ -0,0 +1,24 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-ui\_actions-public](./kibana-plugin-plugins-ui_actions-public.md) > [UiActionsActionDefinition](./kibana-plugin-plugins-ui_actions-public.uiactionsactiondefinition.md) > [isCompatible](./kibana-plugin-plugins-ui_actions-public.uiactionsactiondefinition.iscompatible.md) + +## UiActionsActionDefinition.isCompatible() method + +Returns a promise that resolves to true if this item is compatible given the context and should be displayed to user, otherwise resolves to false. + +Signature: + +```typescript +isCompatible?(context: ActionDefinitionContext): Promise; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| context | ActionDefinitionContext<Context> | | + +Returns: + +`Promise` + diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsactiondefinition.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsactiondefinition.md new file mode 100644 index 0000000000000..7c873715795e9 --- /dev/null +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsactiondefinition.md @@ -0,0 +1,30 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-ui\_actions-public](./kibana-plugin-plugins-ui_actions-public.md) > [UiActionsActionDefinition](./kibana-plugin-plugins-ui_actions-public.uiactionsactiondefinition.md) + +## UiActionsActionDefinition interface + +A convenience interface used to register an action. + +Signature: + +```typescript +export interface ActionDefinition extends Partial>> +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [id](./kibana-plugin-plugins-ui_actions-public.uiactionsactiondefinition.id.md) | string | ID of the action that uniquely identifies this action in the actions registry. | +| [type](./kibana-plugin-plugins-ui_actions-public.uiactionsactiondefinition.type.md) | ActionType | ID of the factory for this action. Used to construct dynamic actions. | + +## Methods + +| Method | Description | +| --- | --- | +| [execute(context)](./kibana-plugin-plugins-ui_actions-public.uiactionsactiondefinition.execute.md) | Executes the action. | +| [getHref(context)](./kibana-plugin-plugins-ui_actions-public.uiactionsactiondefinition.gethref.md) | This method should return a link if this item can be clicked on. The link is used to navigate user if user middle-clicks it or Ctrl + clicks or right-clicks and selects "Open in new tab". | +| [isCompatible(context)](./kibana-plugin-plugins-ui_actions-public.uiactionsactiondefinition.iscompatible.md) | Returns a promise that resolves to true if this item is compatible given the context and should be displayed to user, otherwise resolves to false. | +| [shouldAutoExecute(context)](./kibana-plugin-plugins-ui_actions-public.uiactionsactiondefinition.shouldautoexecute.md) | Determines if action should be executed automatically, without first showing up in context menu. false by default. | + diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsactiondefinition.shouldautoexecute.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsactiondefinition.shouldautoexecute.md new file mode 100644 index 0000000000000..04b9975f3b92e --- /dev/null +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsactiondefinition.shouldautoexecute.md @@ -0,0 +1,24 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-ui\_actions-public](./kibana-plugin-plugins-ui_actions-public.md) > [UiActionsActionDefinition](./kibana-plugin-plugins-ui_actions-public.uiactionsactiondefinition.md) > [shouldAutoExecute](./kibana-plugin-plugins-ui_actions-public.uiactionsactiondefinition.shouldautoexecute.md) + +## UiActionsActionDefinition.shouldAutoExecute() method + +Determines if action should be executed automatically, without first showing up in context menu. false by default. + +Signature: + +```typescript +shouldAutoExecute?(context: ActionDefinitionContext): Promise; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| context | ActionDefinitionContext<Context> | | + +Returns: + +`Promise` + diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsactiondefinition.type.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsactiondefinition.type.md new file mode 100644 index 0000000000000..125f834e9036e --- /dev/null +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsactiondefinition.type.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-ui\_actions-public](./kibana-plugin-plugins-ui_actions-public.md) > [UiActionsActionDefinition](./kibana-plugin-plugins-ui_actions-public.uiactionsactiondefinition.md) > [type](./kibana-plugin-plugins-ui_actions-public.uiactionsactiondefinition.type.md) + +## UiActionsActionDefinition.type property + +ID of the factory for this action. Used to construct dynamic actions. + +Signature: + +```typescript +readonly type?: ActionType; +``` diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionspresentable.getdisplayname.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionspresentable.getdisplayname.md new file mode 100644 index 0000000000000..986ad4afa5a48 --- /dev/null +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionspresentable.getdisplayname.md @@ -0,0 +1,24 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-ui\_actions-public](./kibana-plugin-plugins-ui_actions-public.md) > [UiActionsPresentable](./kibana-plugin-plugins-ui_actions-public.uiactionspresentable.md) > [getDisplayName](./kibana-plugin-plugins-ui_actions-public.uiactionspresentable.getdisplayname.md) + +## UiActionsPresentable.getDisplayName() method + +Returns a title to be displayed to the user. + +Signature: + +```typescript +getDisplayName(context: Context): string; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| context | Context | | + +Returns: + +`string` + diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionspresentable.getdisplaynametooltip.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionspresentable.getdisplaynametooltip.md new file mode 100644 index 0000000000000..8fc859d5713e6 --- /dev/null +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionspresentable.getdisplaynametooltip.md @@ -0,0 +1,24 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-ui\_actions-public](./kibana-plugin-plugins-ui_actions-public.md) > [UiActionsPresentable](./kibana-plugin-plugins-ui_actions-public.uiactionspresentable.md) > [getDisplayNameTooltip](./kibana-plugin-plugins-ui_actions-public.uiactionspresentable.getdisplaynametooltip.md) + +## UiActionsPresentable.getDisplayNameTooltip() method + +Returns tooltip text which should be displayed when user hovers this object. Should return empty string if tooltip should not be displayed. + +Signature: + +```typescript +getDisplayNameTooltip(context: Context): string; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| context | Context | | + +Returns: + +`string` + diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionspresentable.gethref.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionspresentable.gethref.md new file mode 100644 index 0000000000000..0c9bd434ff331 --- /dev/null +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionspresentable.gethref.md @@ -0,0 +1,24 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-ui\_actions-public](./kibana-plugin-plugins-ui_actions-public.md) > [UiActionsPresentable](./kibana-plugin-plugins-ui_actions-public.uiactionspresentable.md) > [getHref](./kibana-plugin-plugins-ui_actions-public.uiactionspresentable.gethref.md) + +## UiActionsPresentable.getHref() method + +This method should return a link if this item can be clicked on. The link is used to navigate user if user middle-clicks it or Ctrl + clicks or right-clicks and selects "Open in new tab". + +Signature: + +```typescript +getHref?(context: Context): Promise; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| context | Context | | + +Returns: + +`Promise` + diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionspresentable.geticontype.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionspresentable.geticontype.md new file mode 100644 index 0000000000000..8bf5af0f3b7e2 --- /dev/null +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionspresentable.geticontype.md @@ -0,0 +1,24 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-ui\_actions-public](./kibana-plugin-plugins-ui_actions-public.md) > [UiActionsPresentable](./kibana-plugin-plugins-ui_actions-public.uiactionspresentable.md) > [getIconType](./kibana-plugin-plugins-ui_actions-public.uiactionspresentable.geticontype.md) + +## UiActionsPresentable.getIconType() method + +Optional EUI icon type that can be displayed along with the title. + +Signature: + +```typescript +getIconType(context: Context): string | undefined; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| context | Context | | + +Returns: + +`string | undefined` + diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionspresentable.grouping.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionspresentable.grouping.md new file mode 100644 index 0000000000000..6b160becf1afc --- /dev/null +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionspresentable.grouping.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-ui\_actions-public](./kibana-plugin-plugins-ui_actions-public.md) > [UiActionsPresentable](./kibana-plugin-plugins-ui_actions-public.uiactionspresentable.md) > [grouping](./kibana-plugin-plugins-ui_actions-public.uiactionspresentable.grouping.md) + +## UiActionsPresentable.grouping property + +Grouping where this item should appear as a submenu. Each entry is a new sub-menu level. For example, used to show drilldowns and sharing options in panel context menu in a sub-menu. + +Signature: + +```typescript +readonly grouping?: PresentableGrouping; +``` diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionspresentable.id.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionspresentable.id.md new file mode 100644 index 0000000000000..e98401d95cba8 --- /dev/null +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionspresentable.id.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-ui\_actions-public](./kibana-plugin-plugins-ui_actions-public.md) > [UiActionsPresentable](./kibana-plugin-plugins-ui_actions-public.uiactionspresentable.md) > [id](./kibana-plugin-plugins-ui_actions-public.uiactionspresentable.id.md) + +## UiActionsPresentable.id property + +ID that uniquely identifies this object. + +Signature: + +```typescript +readonly id: string; +``` diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionspresentable.iscompatible.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionspresentable.iscompatible.md new file mode 100644 index 0000000000000..073f75c840bcd --- /dev/null +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionspresentable.iscompatible.md @@ -0,0 +1,24 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-ui\_actions-public](./kibana-plugin-plugins-ui_actions-public.md) > [UiActionsPresentable](./kibana-plugin-plugins-ui_actions-public.uiactionspresentable.md) > [isCompatible](./kibana-plugin-plugins-ui_actions-public.uiactionspresentable.iscompatible.md) + +## UiActionsPresentable.isCompatible() method + +Returns a promise that resolves to true if this item is compatible given the context and should be displayed to user, otherwise resolves to false. + +Signature: + +```typescript +isCompatible(context: Context): Promise; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| context | Context | | + +Returns: + +`Promise` + diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionspresentable.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionspresentable.md new file mode 100644 index 0000000000000..03fa7fb6e447e --- /dev/null +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionspresentable.md @@ -0,0 +1,33 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-ui\_actions-public](./kibana-plugin-plugins-ui_actions-public.md) > [UiActionsPresentable](./kibana-plugin-plugins-ui_actions-public.uiactionspresentable.md) + +## UiActionsPresentable interface + +Represents something that can be displayed to user in UI. + +Signature: + +```typescript +export interface Presentable +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [grouping](./kibana-plugin-plugins-ui_actions-public.uiactionspresentable.grouping.md) | PresentableGrouping<Context> | Grouping where this item should appear as a submenu. Each entry is a new sub-menu level. For example, used to show drilldowns and sharing options in panel context menu in a sub-menu. | +| [id](./kibana-plugin-plugins-ui_actions-public.uiactionspresentable.id.md) | string | ID that uniquely identifies this object. | +| [MenuItem](./kibana-plugin-plugins-ui_actions-public.uiactionspresentable.menuitem.md) | UiComponent<{
    context: Context;
    }> | UiComponent to render when displaying this entity as a context menu item. If not provided, getDisplayName will be used instead. | +| [order](./kibana-plugin-plugins-ui_actions-public.uiactionspresentable.order.md) | number | Determines the display order in relation to other items. Higher numbers are displayed first. | + +## Methods + +| Method | Description | +| --- | --- | +| [getDisplayName(context)](./kibana-plugin-plugins-ui_actions-public.uiactionspresentable.getdisplayname.md) | Returns a title to be displayed to the user. | +| [getDisplayNameTooltip(context)](./kibana-plugin-plugins-ui_actions-public.uiactionspresentable.getdisplaynametooltip.md) | Returns tooltip text which should be displayed when user hovers this object. Should return empty string if tooltip should not be displayed. | +| [getHref(context)](./kibana-plugin-plugins-ui_actions-public.uiactionspresentable.gethref.md) | This method should return a link if this item can be clicked on. The link is used to navigate user if user middle-clicks it or Ctrl + clicks or right-clicks and selects "Open in new tab". | +| [getIconType(context)](./kibana-plugin-plugins-ui_actions-public.uiactionspresentable.geticontype.md) | Optional EUI icon type that can be displayed along with the title. | +| [isCompatible(context)](./kibana-plugin-plugins-ui_actions-public.uiactionspresentable.iscompatible.md) | Returns a promise that resolves to true if this item is compatible given the context and should be displayed to user, otherwise resolves to false. | + diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionspresentable.menuitem.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionspresentable.menuitem.md new file mode 100644 index 0000000000000..42afe6b8361f0 --- /dev/null +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionspresentable.menuitem.md @@ -0,0 +1,15 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-ui\_actions-public](./kibana-plugin-plugins-ui_actions-public.md) > [UiActionsPresentable](./kibana-plugin-plugins-ui_actions-public.uiactionspresentable.md) > [MenuItem](./kibana-plugin-plugins-ui_actions-public.uiactionspresentable.menuitem.md) + +## UiActionsPresentable.MenuItem property + +`UiComponent` to render when displaying this entity as a context menu item. If not provided, `getDisplayName` will be used instead. + +Signature: + +```typescript +readonly MenuItem?: UiComponent<{ + context: Context; + }>; +``` diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionspresentable.order.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionspresentable.order.md new file mode 100644 index 0000000000000..0bbf80dc89211 --- /dev/null +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionspresentable.order.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-ui\_actions-public](./kibana-plugin-plugins-ui_actions-public.md) > [UiActionsPresentable](./kibana-plugin-plugins-ui_actions-public.uiactionspresentable.md) > [order](./kibana-plugin-plugins-ui_actions-public.uiactionspresentable.order.md) + +## UiActionsPresentable.order property + +Determines the display order in relation to other items. Higher numbers are displayed first. + +Signature: + +```typescript +readonly order: number; +``` diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionspresentablegrouping.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionspresentablegrouping.md new file mode 100644 index 0000000000000..a61ff65e39c69 --- /dev/null +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionspresentablegrouping.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-ui\_actions-public](./kibana-plugin-plugins-ui_actions-public.md) > [UiActionsPresentableGrouping](./kibana-plugin-plugins-ui_actions-public.uiactionspresentablegrouping.md) + +## UiActionsPresentableGrouping type + +Signature: + +```typescript +export declare type PresentableGrouping = Array>; +``` diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice._constructor_.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice._constructor_.md new file mode 100644 index 0000000000000..ff272245dbbf9 --- /dev/null +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice._constructor_.md @@ -0,0 +1,20 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-ui\_actions-public](./kibana-plugin-plugins-ui_actions-public.md) > [UiActionsService](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.md) > [(constructor)](./kibana-plugin-plugins-ui_actions-public.uiactionsservice._constructor_.md) + +## UiActionsService.(constructor) + +Constructs a new instance of the `UiActionsService` class + +Signature: + +```typescript +constructor({ triggers, actions, triggerToActions, }?: UiActionsServiceParams); +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| { triggers, actions, triggerToActions, } | UiActionsServiceParams | | + diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.actions.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.actions.md new file mode 100644 index 0000000000000..aaf4cebaf841c --- /dev/null +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.actions.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-ui\_actions-public](./kibana-plugin-plugins-ui_actions-public.md) > [UiActionsService](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.md) > [actions](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.actions.md) + +## UiActionsService.actions property + +Signature: + +```typescript +protected readonly actions: ActionRegistry; +``` diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.addtriggeraction.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.addtriggeraction.md new file mode 100644 index 0000000000000..ba9060e01e57d --- /dev/null +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.addtriggeraction.md @@ -0,0 +1,15 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-ui\_actions-public](./kibana-plugin-plugins-ui_actions-public.md) > [UiActionsService](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.md) > [addTriggerAction](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.addtriggeraction.md) + +## UiActionsService.addTriggerAction property + +`addTriggerAction` is similar to `attachAction` as it attaches action to a trigger, but it also registers the action, if it has not been registered, yet. + +`addTriggerAction` also infers better typing of the `action` argument. + +Signature: + +```typescript +readonly addTriggerAction: (triggerId: T, action: ActionDefinition | Action) => void; +``` diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.attachaction.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.attachaction.md new file mode 100644 index 0000000000000..19f215a96b23b --- /dev/null +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.attachaction.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-ui\_actions-public](./kibana-plugin-plugins-ui_actions-public.md) > [UiActionsService](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.md) > [attachAction](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.attachaction.md) + +## UiActionsService.attachAction property + +Signature: + +```typescript +readonly attachAction: (triggerId: T, actionId: string) => void; +``` diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.clear.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.clear.md new file mode 100644 index 0000000000000..024c7e3c3f85a --- /dev/null +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.clear.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-ui\_actions-public](./kibana-plugin-plugins-ui_actions-public.md) > [UiActionsService](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.md) > [clear](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.clear.md) + +## UiActionsService.clear property + +Removes all registered triggers and actions. + +Signature: + +```typescript +readonly clear: () => void; +``` diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.detachaction.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.detachaction.md new file mode 100644 index 0000000000000..a6ff2489c6f0e --- /dev/null +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.detachaction.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-ui\_actions-public](./kibana-plugin-plugins-ui_actions-public.md) > [UiActionsService](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.md) > [detachAction](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.detachaction.md) + +## UiActionsService.detachAction property + +Signature: + +```typescript +readonly detachAction: (triggerId: TriggerId, actionId: string) => void; +``` diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.executetriggeractions.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.executetriggeractions.md new file mode 100644 index 0000000000000..1bb6ca1115248 --- /dev/null +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.executetriggeractions.md @@ -0,0 +1,16 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-ui\_actions-public](./kibana-plugin-plugins-ui_actions-public.md) > [UiActionsService](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.md) > [executeTriggerActions](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.executetriggeractions.md) + +## UiActionsService.executeTriggerActions property + +> Warning: This API is now obsolete. +> +> Use `plugins.uiActions.getTrigger(triggerId).exec(params)` instead. +> + +Signature: + +```typescript +readonly executeTriggerActions: (triggerId: T, context: TriggerContext) => Promise; +``` diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.executionservice.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.executionservice.md new file mode 100644 index 0000000000000..06384cc110a59 --- /dev/null +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.executionservice.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-ui\_actions-public](./kibana-plugin-plugins-ui_actions-public.md) > [UiActionsService](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.md) > [executionService](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.executionservice.md) + +## UiActionsService.executionService property + +Signature: + +```typescript +readonly executionService: UiActionsExecutionService; +``` diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.fork.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.fork.md new file mode 100644 index 0000000000000..2b7a43a44cca6 --- /dev/null +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.fork.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-ui\_actions-public](./kibana-plugin-plugins-ui_actions-public.md) > [UiActionsService](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.md) > [fork](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.fork.md) + +## UiActionsService.fork property + +"Fork" a separate instance of `UiActionsService` that inherits all existing triggers and actions, but going forward all new triggers and actions added to this instance of `UiActionsService` are only available within this instance. + +Signature: + +```typescript +readonly fork: () => UiActionsService; +``` diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.getaction.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.getaction.md new file mode 100644 index 0000000000000..3e433809f9471 --- /dev/null +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.getaction.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-ui\_actions-public](./kibana-plugin-plugins-ui_actions-public.md) > [UiActionsService](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.md) > [getAction](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.getaction.md) + +## UiActionsService.getAction property + +Signature: + +```typescript +readonly getAction: >(id: string) => Action, "" | "ACTION_VISUALIZE_FIELD" | "ACTION_VISUALIZE_GEO_FIELD" | "ACTION_VISUALIZE_LENS_FIELD" | "ACTION_CUSTOMIZE_PANEL" | "ACTION_ADD_PANEL" | "openInspector" | "deletePanel" | "editPanel" | "togglePanel" | "replacePanel" | "clonePanel" | "addToFromLibrary" | "unlinkFromLibrary" | "ACTION_LIBRARY_NOTIFICATION" | "ACTION_GLOBAL_APPLY_FILTER" | "ACTION_SELECT_RANGE" | "ACTION_VALUE_CLICK">; +``` diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.gettrigger.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.gettrigger.md new file mode 100644 index 0000000000000..d44dc4e43a52e --- /dev/null +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.gettrigger.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-ui\_actions-public](./kibana-plugin-plugins-ui_actions-public.md) > [UiActionsService](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.md) > [getTrigger](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.gettrigger.md) + +## UiActionsService.getTrigger property + +Signature: + +```typescript +readonly getTrigger: (triggerId: T) => TriggerContract; +``` diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.gettriggeractions.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.gettriggeractions.md new file mode 100644 index 0000000000000..83afcab29689d --- /dev/null +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.gettriggeractions.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-ui\_actions-public](./kibana-plugin-plugins-ui_actions-public.md) > [UiActionsService](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.md) > [getTriggerActions](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.gettriggeractions.md) + +## UiActionsService.getTriggerActions property + +Signature: + +```typescript +readonly getTriggerActions: (triggerId: T) => Action[]; +``` diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.gettriggercompatibleactions.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.gettriggercompatibleactions.md new file mode 100644 index 0000000000000..879f5a3d8628a --- /dev/null +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.gettriggercompatibleactions.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-ui\_actions-public](./kibana-plugin-plugins-ui_actions-public.md) > [UiActionsService](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.md) > [getTriggerCompatibleActions](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.gettriggercompatibleactions.md) + +## UiActionsService.getTriggerCompatibleActions property + +Signature: + +```typescript +readonly getTriggerCompatibleActions: (triggerId: T, context: TriggerContextMapping[T]) => Promise[]>; +``` diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.hasaction.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.hasaction.md new file mode 100644 index 0000000000000..2287cb3052864 --- /dev/null +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.hasaction.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-ui\_actions-public](./kibana-plugin-plugins-ui_actions-public.md) > [UiActionsService](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.md) > [hasAction](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.hasaction.md) + +## UiActionsService.hasAction property + +Signature: + +```typescript +readonly hasAction: (actionId: string) => boolean; +``` diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.md new file mode 100644 index 0000000000000..7fade7c4c841b --- /dev/null +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.md @@ -0,0 +1,41 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-ui\_actions-public](./kibana-plugin-plugins-ui_actions-public.md) > [UiActionsService](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.md) + +## UiActionsService class + +Signature: + +```typescript +export declare class UiActionsService +``` + +## Constructors + +| Constructor | Modifiers | Description | +| --- | --- | --- | +| [(constructor)({ triggers, actions, triggerToActions, })](./kibana-plugin-plugins-ui_actions-public.uiactionsservice._constructor_.md) | | Constructs a new instance of the UiActionsService class | + +## Properties + +| Property | Modifiers | Type | Description | +| --- | --- | --- | --- | +| [actions](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.actions.md) | | ActionRegistry | | +| [addTriggerAction](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.addtriggeraction.md) | | <T extends "" | "SELECT_RANGE_TRIGGER" | "VALUE_CLICK_TRIGGER" | "FILTER_TRIGGER" | "VISUALIZE_FIELD_TRIGGER" | "VISUALIZE_GEO_FIELD_TRIGGER" | "CONTEXT_MENU_TRIGGER" | "PANEL_BADGE_TRIGGER" | "PANEL_NOTIFICATION_TRIGGER">(triggerId: T, action: ActionDefinition<TriggerContextMapping[T]> | Action<TriggerContextMapping[T], "" | "ACTION_VISUALIZE_FIELD" | "ACTION_VISUALIZE_GEO_FIELD" | "ACTION_VISUALIZE_LENS_FIELD" | "ACTION_CUSTOMIZE_PANEL" | "ACTION_ADD_PANEL" | "openInspector" | "deletePanel" | "editPanel" | "togglePanel" | "replacePanel" | "clonePanel" | "addToFromLibrary" | "unlinkFromLibrary" | "ACTION_LIBRARY_NOTIFICATION" | "ACTION_GLOBAL_APPLY_FILTER" | "ACTION_SELECT_RANGE" | "ACTION_VALUE_CLICK">) => void | addTriggerAction is similar to attachAction as it attaches action to a trigger, but it also registers the action, if it has not been registered, yet.addTriggerAction also infers better typing of the action argument. | +| [attachAction](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.attachaction.md) | | <T extends "" | "SELECT_RANGE_TRIGGER" | "VALUE_CLICK_TRIGGER" | "FILTER_TRIGGER" | "VISUALIZE_FIELD_TRIGGER" | "VISUALIZE_GEO_FIELD_TRIGGER" | "CONTEXT_MENU_TRIGGER" | "PANEL_BADGE_TRIGGER" | "PANEL_NOTIFICATION_TRIGGER">(triggerId: T, actionId: string) => void | | +| [clear](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.clear.md) | | () => void | Removes all registered triggers and actions. | +| [detachAction](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.detachaction.md) | | (triggerId: TriggerId, actionId: string) => void | | +| [executeTriggerActions](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.executetriggeractions.md) | | <T extends "" | "SELECT_RANGE_TRIGGER" | "VALUE_CLICK_TRIGGER" | "FILTER_TRIGGER" | "VISUALIZE_FIELD_TRIGGER" | "VISUALIZE_GEO_FIELD_TRIGGER" | "CONTEXT_MENU_TRIGGER" | "PANEL_BADGE_TRIGGER" | "PANEL_NOTIFICATION_TRIGGER">(triggerId: T, context: TriggerContext<T>) => Promise<void> | | +| [executionService](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.executionservice.md) | | UiActionsExecutionService | | +| [fork](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.fork.md) | | () => UiActionsService | "Fork" a separate instance of UiActionsService that inherits all existing triggers and actions, but going forward all new triggers and actions added to this instance of UiActionsService are only available within this instance. | +| [getAction](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.getaction.md) | | <T extends ActionDefinition<{}>>(id: string) => Action<ActionContext<T>, "" | "ACTION_VISUALIZE_FIELD" | "ACTION_VISUALIZE_GEO_FIELD" | "ACTION_VISUALIZE_LENS_FIELD" | "ACTION_CUSTOMIZE_PANEL" | "ACTION_ADD_PANEL" | "openInspector" | "deletePanel" | "editPanel" | "togglePanel" | "replacePanel" | "clonePanel" | "addToFromLibrary" | "unlinkFromLibrary" | "ACTION_LIBRARY_NOTIFICATION" | "ACTION_GLOBAL_APPLY_FILTER" | "ACTION_SELECT_RANGE" | "ACTION_VALUE_CLICK"> | | +| [getTrigger](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.gettrigger.md) | | <T extends "" | "SELECT_RANGE_TRIGGER" | "VALUE_CLICK_TRIGGER" | "FILTER_TRIGGER" | "VISUALIZE_FIELD_TRIGGER" | "VISUALIZE_GEO_FIELD_TRIGGER" | "CONTEXT_MENU_TRIGGER" | "PANEL_BADGE_TRIGGER" | "PANEL_NOTIFICATION_TRIGGER">(triggerId: T) => TriggerContract<T> | | +| [getTriggerActions](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.gettriggeractions.md) | | <T extends "" | "SELECT_RANGE_TRIGGER" | "VALUE_CLICK_TRIGGER" | "FILTER_TRIGGER" | "VISUALIZE_FIELD_TRIGGER" | "VISUALIZE_GEO_FIELD_TRIGGER" | "CONTEXT_MENU_TRIGGER" | "PANEL_BADGE_TRIGGER" | "PANEL_NOTIFICATION_TRIGGER">(triggerId: T) => Action<TriggerContextMapping[T], "" | "ACTION_VISUALIZE_FIELD" | "ACTION_VISUALIZE_GEO_FIELD" | "ACTION_VISUALIZE_LENS_FIELD" | "ACTION_CUSTOMIZE_PANEL" | "ACTION_ADD_PANEL" | "openInspector" | "deletePanel" | "editPanel" | "togglePanel" | "replacePanel" | "clonePanel" | "addToFromLibrary" | "unlinkFromLibrary" | "ACTION_LIBRARY_NOTIFICATION" | "ACTION_GLOBAL_APPLY_FILTER" | "ACTION_SELECT_RANGE" | "ACTION_VALUE_CLICK">[] | | +| [getTriggerCompatibleActions](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.gettriggercompatibleactions.md) | | <T extends "" | "SELECT_RANGE_TRIGGER" | "VALUE_CLICK_TRIGGER" | "FILTER_TRIGGER" | "VISUALIZE_FIELD_TRIGGER" | "VISUALIZE_GEO_FIELD_TRIGGER" | "CONTEXT_MENU_TRIGGER" | "PANEL_BADGE_TRIGGER" | "PANEL_NOTIFICATION_TRIGGER">(triggerId: T, context: TriggerContextMapping[T]) => Promise<Action<TriggerContextMapping[T], "" | "ACTION_VISUALIZE_FIELD" | "ACTION_VISUALIZE_GEO_FIELD" | "ACTION_VISUALIZE_LENS_FIELD" | "ACTION_CUSTOMIZE_PANEL" | "ACTION_ADD_PANEL" | "openInspector" | "deletePanel" | "editPanel" | "togglePanel" | "replacePanel" | "clonePanel" | "addToFromLibrary" | "unlinkFromLibrary" | "ACTION_LIBRARY_NOTIFICATION" | "ACTION_GLOBAL_APPLY_FILTER" | "ACTION_SELECT_RANGE" | "ACTION_VALUE_CLICK">[]> | | +| [hasAction](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.hasaction.md) | | (actionId: string) => boolean | | +| [registerAction](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.registeraction.md) | | <A extends ActionDefinition<{}>>(definition: A) => Action<ActionContext<A>, "" | "ACTION_VISUALIZE_FIELD" | "ACTION_VISUALIZE_GEO_FIELD" | "ACTION_VISUALIZE_LENS_FIELD" | "ACTION_CUSTOMIZE_PANEL" | "ACTION_ADD_PANEL" | "openInspector" | "deletePanel" | "editPanel" | "togglePanel" | "replacePanel" | "clonePanel" | "addToFromLibrary" | "unlinkFromLibrary" | "ACTION_LIBRARY_NOTIFICATION" | "ACTION_GLOBAL_APPLY_FILTER" | "ACTION_SELECT_RANGE" | "ACTION_VALUE_CLICK"> | | +| [registerTrigger](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.registertrigger.md) | | (trigger: Trigger) => void | | +| [triggers](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.triggers.md) | | TriggerRegistry | | +| [triggerToActions](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.triggertoactions.md) | | TriggerToActionsRegistry | | +| [unregisterAction](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.unregisteraction.md) | | (actionId: string) => void | | + diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.registeraction.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.registeraction.md new file mode 100644 index 0000000000000..eeda7b503037d --- /dev/null +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.registeraction.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-ui\_actions-public](./kibana-plugin-plugins-ui_actions-public.md) > [UiActionsService](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.md) > [registerAction](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.registeraction.md) + +## UiActionsService.registerAction property + +Signature: + +```typescript +readonly registerAction:
    >(definition: A) => Action, "" | "ACTION_VISUALIZE_FIELD" | "ACTION_VISUALIZE_GEO_FIELD" | "ACTION_VISUALIZE_LENS_FIELD" | "ACTION_CUSTOMIZE_PANEL" | "ACTION_ADD_PANEL" | "openInspector" | "deletePanel" | "editPanel" | "togglePanel" | "replacePanel" | "clonePanel" | "addToFromLibrary" | "unlinkFromLibrary" | "ACTION_LIBRARY_NOTIFICATION" | "ACTION_GLOBAL_APPLY_FILTER" | "ACTION_SELECT_RANGE" | "ACTION_VALUE_CLICK">; +``` diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.registertrigger.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.registertrigger.md new file mode 100644 index 0000000000000..3002409c02304 --- /dev/null +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.registertrigger.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-ui\_actions-public](./kibana-plugin-plugins-ui_actions-public.md) > [UiActionsService](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.md) > [registerTrigger](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.registertrigger.md) + +## UiActionsService.registerTrigger property + +Signature: + +```typescript +readonly registerTrigger: (trigger: Trigger) => void; +``` diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.triggers.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.triggers.md new file mode 100644 index 0000000000000..07d480286e771 --- /dev/null +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.triggers.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-ui\_actions-public](./kibana-plugin-plugins-ui_actions-public.md) > [UiActionsService](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.md) > [triggers](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.triggers.md) + +## UiActionsService.triggers property + +Signature: + +```typescript +protected readonly triggers: TriggerRegistry; +``` diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.triggertoactions.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.triggertoactions.md new file mode 100644 index 0000000000000..1b79a1dd84593 --- /dev/null +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.triggertoactions.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-ui\_actions-public](./kibana-plugin-plugins-ui_actions-public.md) > [UiActionsService](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.md) > [triggerToActions](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.triggertoactions.md) + +## UiActionsService.triggerToActions property + +Signature: + +```typescript +protected readonly triggerToActions: TriggerToActionsRegistry; +``` diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.unregisteraction.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.unregisteraction.md new file mode 100644 index 0000000000000..0e0eb971c1a7b --- /dev/null +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.unregisteraction.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-ui\_actions-public](./kibana-plugin-plugins-ui_actions-public.md) > [UiActionsService](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.md) > [unregisterAction](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.unregisteraction.md) + +## UiActionsService.unregisterAction property + +Signature: + +```typescript +readonly unregisterAction: (actionId: string) => void; +``` diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsserviceparams.actions.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsserviceparams.actions.md new file mode 100644 index 0000000000000..44d2957b0f8ba --- /dev/null +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsserviceparams.actions.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-ui\_actions-public](./kibana-plugin-plugins-ui_actions-public.md) > [UiActionsServiceParams](./kibana-plugin-plugins-ui_actions-public.uiactionsserviceparams.md) > [actions](./kibana-plugin-plugins-ui_actions-public.uiactionsserviceparams.actions.md) + +## UiActionsServiceParams.actions property + +Signature: + +```typescript +readonly actions?: ActionRegistry; +``` diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsserviceparams.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsserviceparams.md new file mode 100644 index 0000000000000..756cd3de92ef8 --- /dev/null +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsserviceparams.md @@ -0,0 +1,20 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-ui\_actions-public](./kibana-plugin-plugins-ui_actions-public.md) > [UiActionsServiceParams](./kibana-plugin-plugins-ui_actions-public.uiactionsserviceparams.md) + +## UiActionsServiceParams interface + +Signature: + +```typescript +export interface UiActionsServiceParams +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [actions](./kibana-plugin-plugins-ui_actions-public.uiactionsserviceparams.actions.md) | ActionRegistry | | +| [triggers](./kibana-plugin-plugins-ui_actions-public.uiactionsserviceparams.triggers.md) | TriggerRegistry | | +| [triggerToActions](./kibana-plugin-plugins-ui_actions-public.uiactionsserviceparams.triggertoactions.md) | TriggerToActionsRegistry | A 1-to-N mapping from Trigger to zero or more Action. | + diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsserviceparams.triggers.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsserviceparams.triggers.md new file mode 100644 index 0000000000000..061aa5eb68c5d --- /dev/null +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsserviceparams.triggers.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-ui\_actions-public](./kibana-plugin-plugins-ui_actions-public.md) > [UiActionsServiceParams](./kibana-plugin-plugins-ui_actions-public.uiactionsserviceparams.md) > [triggers](./kibana-plugin-plugins-ui_actions-public.uiactionsserviceparams.triggers.md) + +## UiActionsServiceParams.triggers property + +Signature: + +```typescript +readonly triggers?: TriggerRegistry; +``` diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsserviceparams.triggertoactions.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsserviceparams.triggertoactions.md new file mode 100644 index 0000000000000..bdf1acba484e6 --- /dev/null +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsserviceparams.triggertoactions.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-ui\_actions-public](./kibana-plugin-plugins-ui_actions-public.md) > [UiActionsServiceParams](./kibana-plugin-plugins-ui_actions-public.uiactionsserviceparams.md) > [triggerToActions](./kibana-plugin-plugins-ui_actions-public.uiactionsserviceparams.triggertoactions.md) + +## UiActionsServiceParams.triggerToActions property + +A 1-to-N mapping from `Trigger` to zero or more `Action`. + +Signature: + +```typescript +readonly triggerToActions?: TriggerToActionsRegistry; +``` diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionssetup.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionssetup.md new file mode 100644 index 0000000000000..d03d4cf9f1ee2 --- /dev/null +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionssetup.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-ui\_actions-public](./kibana-plugin-plugins-ui_actions-public.md) > [UiActionsSetup](./kibana-plugin-plugins-ui_actions-public.uiactionssetup.md) + +## UiActionsSetup type + +Signature: + +```typescript +export declare type UiActionsSetup = Pick; +``` diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsstart.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsstart.md new file mode 100644 index 0000000000000..41f5bbf705e20 --- /dev/null +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsstart.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-ui\_actions-public](./kibana-plugin-plugins-ui_actions-public.md) > [UiActionsStart](./kibana-plugin-plugins-ui_actions-public.uiactionsstart.md) + +## UiActionsStart type + +Signature: + +```typescript +export declare type UiActionsStart = PublicMethodsOf; +``` diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.value_click_trigger.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.value_click_trigger.md new file mode 100644 index 0000000000000..bd8d4dc50b8fd --- /dev/null +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.value_click_trigger.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-ui\_actions-public](./kibana-plugin-plugins-ui_actions-public.md) > [VALUE\_CLICK\_TRIGGER](./kibana-plugin-plugins-ui_actions-public.value_click_trigger.md) + +## VALUE\_CLICK\_TRIGGER variable + +Signature: + +```typescript +VALUE_CLICK_TRIGGER = "VALUE_CLICK_TRIGGER" +``` diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.valueclicktrigger.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.valueclicktrigger.md new file mode 100644 index 0000000000000..5c4fc284d83b1 --- /dev/null +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.valueclicktrigger.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-ui\_actions-public](./kibana-plugin-plugins-ui_actions-public.md) > [valueClickTrigger](./kibana-plugin-plugins-ui_actions-public.valueclicktrigger.md) + +## valueClickTrigger variable + +Signature: + +```typescript +valueClickTrigger: Trigger<'VALUE_CLICK_TRIGGER'> +``` diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.visualize_field_trigger.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.visualize_field_trigger.md new file mode 100644 index 0000000000000..c5d9f53557d6f --- /dev/null +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.visualize_field_trigger.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-ui\_actions-public](./kibana-plugin-plugins-ui_actions-public.md) > [VISUALIZE\_FIELD\_TRIGGER](./kibana-plugin-plugins-ui_actions-public.visualize_field_trigger.md) + +## VISUALIZE\_FIELD\_TRIGGER variable + +Signature: + +```typescript +VISUALIZE_FIELD_TRIGGER = "VISUALIZE_FIELD_TRIGGER" +``` diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.visualize_geo_field_trigger.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.visualize_geo_field_trigger.md new file mode 100644 index 0000000000000..a9396c1905485 --- /dev/null +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.visualize_geo_field_trigger.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-ui\_actions-public](./kibana-plugin-plugins-ui_actions-public.md) > [VISUALIZE\_GEO\_FIELD\_TRIGGER](./kibana-plugin-plugins-ui_actions-public.visualize_geo_field_trigger.md) + +## VISUALIZE\_GEO\_FIELD\_TRIGGER variable + +Signature: + +```typescript +VISUALIZE_GEO_FIELD_TRIGGER = "VISUALIZE_GEO_FIELD_TRIGGER" +``` diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.visualizefieldcontext.contextualfields.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.visualizefieldcontext.contextualfields.md new file mode 100644 index 0000000000000..681d4127e4030 --- /dev/null +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.visualizefieldcontext.contextualfields.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-ui\_actions-public](./kibana-plugin-plugins-ui_actions-public.md) > [VisualizeFieldContext](./kibana-plugin-plugins-ui_actions-public.visualizefieldcontext.md) > [contextualFields](./kibana-plugin-plugins-ui_actions-public.visualizefieldcontext.contextualfields.md) + +## VisualizeFieldContext.contextualFields property + +Signature: + +```typescript +contextualFields?: string[]; +``` diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.visualizefieldcontext.fieldname.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.visualizefieldcontext.fieldname.md new file mode 100644 index 0000000000000..95f45b1fbee4a --- /dev/null +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.visualizefieldcontext.fieldname.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-ui\_actions-public](./kibana-plugin-plugins-ui_actions-public.md) > [VisualizeFieldContext](./kibana-plugin-plugins-ui_actions-public.visualizefieldcontext.md) > [fieldName](./kibana-plugin-plugins-ui_actions-public.visualizefieldcontext.fieldname.md) + +## VisualizeFieldContext.fieldName property + +Signature: + +```typescript +fieldName: string; +``` diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.visualizefieldcontext.indexpatternid.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.visualizefieldcontext.indexpatternid.md new file mode 100644 index 0000000000000..588c115cd9885 --- /dev/null +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.visualizefieldcontext.indexpatternid.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-ui\_actions-public](./kibana-plugin-plugins-ui_actions-public.md) > [VisualizeFieldContext](./kibana-plugin-plugins-ui_actions-public.visualizefieldcontext.md) > [indexPatternId](./kibana-plugin-plugins-ui_actions-public.visualizefieldcontext.indexpatternid.md) + +## VisualizeFieldContext.indexPatternId property + +Signature: + +```typescript +indexPatternId: string; +``` diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.visualizefieldcontext.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.visualizefieldcontext.md new file mode 100644 index 0000000000000..7aeb254db7771 --- /dev/null +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.visualizefieldcontext.md @@ -0,0 +1,20 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-ui\_actions-public](./kibana-plugin-plugins-ui_actions-public.md) > [VisualizeFieldContext](./kibana-plugin-plugins-ui_actions-public.visualizefieldcontext.md) + +## VisualizeFieldContext interface + +Signature: + +```typescript +export interface VisualizeFieldContext +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [contextualFields](./kibana-plugin-plugins-ui_actions-public.visualizefieldcontext.contextualfields.md) | string[] | | +| [fieldName](./kibana-plugin-plugins-ui_actions-public.visualizefieldcontext.fieldname.md) | string | | +| [indexPatternId](./kibana-plugin-plugins-ui_actions-public.visualizefieldcontext.indexpatternid.md) | string | | + diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.visualizefieldtrigger.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.visualizefieldtrigger.md new file mode 100644 index 0000000000000..15510bd3eb4a3 --- /dev/null +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.visualizefieldtrigger.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-ui\_actions-public](./kibana-plugin-plugins-ui_actions-public.md) > [visualizeFieldTrigger](./kibana-plugin-plugins-ui_actions-public.visualizefieldtrigger.md) + +## visualizeFieldTrigger variable + +Signature: + +```typescript +visualizeFieldTrigger: Trigger<'VISUALIZE_FIELD_TRIGGER'> +``` diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.visualizegeofieldtrigger.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.visualizegeofieldtrigger.md new file mode 100644 index 0000000000000..faec6a69b71f9 --- /dev/null +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.visualizegeofieldtrigger.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-ui\_actions-public](./kibana-plugin-plugins-ui_actions-public.md) > [visualizeGeoFieldTrigger](./kibana-plugin-plugins-ui_actions-public.visualizegeofieldtrigger.md) + +## visualizeGeoFieldTrigger variable + +Signature: + +```typescript +visualizeGeoFieldTrigger: Trigger<'VISUALIZE_GEO_FIELD_TRIGGER'> +``` diff --git a/docs/discover/context.asciidoc b/docs/discover/context.asciidoc index 17ed78a163571..e26c91bfef075 100644 --- a/docs/discover/context.asciidoc +++ b/docs/discover/context.asciidoc @@ -16,7 +16,7 @@ The anchor document is highlighted in blue. [role="screenshot"] -image::images/Discover-ContextView.png[Context View] +image::images/Discover-ContextView.png[Image showing context view feature, with anchor documents highlighted in blue] [float] [[filter-context]] diff --git a/docs/discover/document-data.asciidoc b/docs/discover/document-data.asciidoc index ee130e8405483..dd245e4b4558f 100644 --- a/docs/discover/document-data.asciidoc +++ b/docs/discover/document-data.asciidoc @@ -44,7 +44,7 @@ immediately before and after your event. share the link for direct access to a particular document. [role="screenshot"] -image::images/Expanded-Document.png[] +image::images/Expanded-Document.png[Image showing expanded view, with JSON and table viewing options] [float] diff --git a/docs/discover/field-filter.asciidoc b/docs/discover/field-filter.asciidoc index 949cab2c2f976..0c521b401e4b8 100644 --- a/docs/discover/field-filter.asciidoc +++ b/docs/discover/field-filter.asciidoc @@ -19,7 +19,7 @@ the field, the top 5 values for the field, and the percentage of documents that contain each value. + [role="screenshot"] -image::images/filter-field.png[height=317] +image::images/filter-field.png[Picture showing top 5 values for each field, and correspnding percentage of documents that contain each value] . Use the image:images/PositiveFilter.jpg[Positive Filter] icon to show only documents that contain that value, diff --git a/docs/discover/images/kql-autocomplete.png b/docs/discover/images/kql-autocomplete.png new file mode 100644 index 0000000000000..60e2290c0bad7 Binary files /dev/null and b/docs/discover/images/kql-autocomplete.png differ diff --git a/docs/discover/kuery.asciidoc b/docs/discover/kuery.asciidoc index 1a481c46b3816..f306f2b8f763f 100644 --- a/docs/discover/kuery.asciidoc +++ b/docs/discover/kuery.asciidoc @@ -1,90 +1,170 @@ [[kuery-query]] === Kibana Query Language -In Kibana 6.3, we introduced a number of exciting experimental query language enhancements. These -features are now available by default in 7.0. Out of the box, Kibana's query language now includes scripted field support and a -simplified, easier to use syntax. If you have a Basic license or above, autocomplete functionality will also be enabled. +The Kibana Query Language (KQL) makes it easy to find +the fields and syntax for your {es} query. If you have the +https://www.elastic.co/subscriptions[Basic tier] or above, +simply place your cursor in the *Search* field. As you type, you’ll get suggestions for fields, +values, and operators. -==== Language syntax +[role="screenshot"] +image::images/kql-autocomplete.png[Autocomplete in Search bar] -If you're familiar with Kibana's old Lucene query syntax, you should feel right at home with the new syntax. The basics -stay the same, we've simply refined things to make the query language easier to use. +If you prefer to use Kibana’s legacy query language, based on the +<>, click *KQL* next to the *Search* field, and then turn off KQL. -`response:200` will match documents where the response field matches the value 200. +[discrete] +=== Terms query -Quotes around a search term will initiate a phrase search. For example, `message:"Quick brown fox"` will search -for the phrase "quick brown fox" in the message field. Without the quotes, your query will get broken down into tokens via -the message field's configured analyzer and will match documents that contain those tokens, regardless of the order in which -they appear. This means documents with "quick brown fox" will match, but so will "quick fox brown". Remember to use quotes if you want -to search for a phrase. +A terms query matches documents that contain one or more *exact* terms in a field. -The query parser will no longer split on whitespace. Multiple search terms must be separated by explicit -boolean operators. Lucene will combine search terms with an `or` by default, so `response:200 extension:php` would -become `response:200 or extension:php` in KQL. This will match documents where response matches 200, extension matches php, or both. -Note that boolean operators are not case sensitive. +To match documents where the response field is `200`: -We can make terms required by using `and`. +[source,yaml] +------------------- +response:200 +------------------- -`response:200 and extension:php` will match documents where response matches 200 and extension matches php. +To match documents with the phrase "quick brown fox" in the `message` field. -By default, `and` has a higher precedence than `or`. +[source,yaml] +------------------- +message:"quick brown fox" +------------------- -`response:200 and extension:php or extension:css` will match documents where response is 200 and extension is php OR documents where extension is css and response is anything. +Without the quotes, +the query matches documents regardless of the order in which +they appear. Documents with "quick brown fox" match, +and so does "quick fox brown". -We can override the default precedence with grouping. +NOTE: Terms without fields are matched against the default field in your index settings. +If a default field is not +set, terms are matched against all fields. For example, a query +for `response:200` searches for the value 200 +in the response field, but a query for just `200` searches for 200 +across all fields in your index. -`response:200 and (extension:php or extension:css)` will match documents where response is 200 and extension is either php or css. -A shorthand exists that allows us to easily search a single field for multiple values. +[discrete] +=== Boolean queries -`response:(200 or 404)` searches for docs where the `response` field matches 200 or 404. We can also search for docs -with multi-value fields that contain a list of terms, for example: `tags:(success and info and security)` +KQL supports `or`, `and`, and `not`. By default, `and` has a higher precedence than `or`. +To override the default precedence, group operators in parentheses. -Terms can be inverted by prefixing them with `not`. +To match documents where response is `200`, extension is `php`, or both: -`not response:200` will match all documents where response is not 200. +[source,yaml] +------------------- +response:200 or extension:php +------------------- -Entire groups can also be inverted. +To match documents where response is `200` and extension is `php`: -`response:200 and not (extension:php or extension:css)` +[source,yaml] +------------------- +response:200 and extension:php +------------------- -Ranges are similar to lucene with a small syntactical difference. +To match documents where response is `200` or `404`. -Instead of `bytes:>1000`, we omit the colon: `bytes > 1000`. +[source,yaml] +------------------- +response:(200 or 404) +------------------- -`>, >=, <, <=` are all valid range operators. +To match documents where response is `200` and extension is either `php` or `css`: -Exist queries are simple and do not require a special operator. `response:*` will find all docs where the response -field exists. +[source,yaml] +------------------- +response:200 and (extension:php or extension:css) +------------------- -Wildcard queries are available. `machine.os:win*` would match docs where the machine.os field starts with "win", which -would match values like "windows 7" and "windows 10". +To match documents where `response` is 200 and `extension` is +`php` or extension is `css`, and response is anything: -Wildcards also allow us to search multiple fields at once. This can come in handy when you have both `text` and `keyword` -versions of a field. Let's say we have `machine.os` and `machine.os.keyword` fields and we want to check both for the term -"windows 10". We can do it like this: `machine.os*:windows 10". +[source,yaml] +------------------- +response:200 and extension:php or extension:css +------------------- +To match documents where response is not `200`: -[NOTE] -============ -Terms without fields will be matched against the default field in your index settings. If a default field is not -set these terms will be matched against all fields. For example, a query for `response:200` will search for the value 200 -in the response field, but a query for just `200` will search for 200 across all fields in your index. -============ +[source,yaml] +------------------- +not response:200 +------------------- -==== Nested field support +To match documents where response is `200` but extension is not `php` or `css`. -KQL supports querying on {ref}/nested.html[nested fields] through a special syntax. You can query nested fields in subtly different -ways, depending on the results you want, so crafting nested queries requires extra thought. +[source,yaml] +------------------- +response:200 and not (extension:php or extension:css) +------------------- -One main consideration is how to match parts of the nested query to the individual nested documents. -There are two main approaches to take: +To match multi-value fields that contain a list of terms: -* *Parts of the query may only match a single nested document.* This is what most users want when querying on a nested field. -* *Parts of the query can match different nested documents.* This is how a regular object field works. - Although generally less useful, there might be occasions where you want to query a nested field in this way. +[source,yaml] +------------------- +tags:(success and info and security) +------------------- -Let's take a look at the first approach. In the following document, `items` is a nested field. Each document in the nested +[discrete] +=== Range queries + +KQL supports `>`, `>=`, `<`, and `<=`. For example: + +[source,yaml] +------------------- +account_number:>=100 and items_sold:<=200 +------------------- + +[discrete] +=== Exist queries + +An exist query matches documents that contain a value for a field, in this case, +response: + +[source,yaml] +------------------- +response:* +------------------- + +[discrete] +=== Wildcard queries + +To match documents where machine.os starts with `win`, such +as "windows 7" and "windows 10": + +[source,yaml] +------------------- +machine.os:win* +------------------- + +To match multiple fields: + +[source,yaml] +------------------- +machine.os*:windows 10 +------------------- + +This sytax is handy when you have text and keyword +versions of a field. The query checks machine.os and machine.os.keyword +for the term +`windows 10`. + + +[discrete] +=== Nested field queries + +A main consideration for querying {ref}/nested.html[nested fields] is how to +match parts of the nested query to the individual nested documents. +You can: + +* *Match parts of the query to a single nested document only.* This is what most users want when querying on a nested field. +* *Match parts of the query to different nested documents.* This is how a regular object field works. + This query is generally less useful than matching to a single document. + +In the following document, `items` is a nested field. Each document in the nested field contains a name, stock, and category. [source,json] @@ -116,40 +196,61 @@ field contains a name, stock, and category. } ---------------------------------- -===== Match a single nested document +[discrete] +==== Match a single document -To find stores that have more than 10 bananas in stock, you would write a query like this: +To match stores that have more than 10 bananas in stock: -`items:{ name:banana and stock > 10 }` +[source,yaml] +------------------- +items:{ name:banana and stock > 10 } +------------------- -`items` is the "nested path". Everything inside the curly braces (the "nested group") must match a single nested document. +`items` is the nested path. Everything inside the curly braces (the nested group) +must match a single nested document. -The following example returns no matches because no single nested document has bananas with a stock of 9. +The following query does not return any matches because no single nested +document has bananas with a stock of 9. -`items:{ name:banana and stock:9 }` +[source,yaml] +------------------- +items:{ name:banana and stock:9 } +------------------- -==== Match different nested documents +[discrete] +==== Match different documents -The subqueries in this example are in separate nested groups and can match different nested documents. +The following subqueries are in separate nested groups +and can match different nested documents: -`items:{ name:banana } and items:{ stock:9 }` +[source,yaml] +------------------- +items:{ name:banana } and items:{ stock:9 } +------------------- -`name:banana` matches the first document in the array and `stock:9` matches the third document in the array. +`name:banana` matches the first document in the array and `stock:9` +matches the third document in the array. -==== Combine approaches +[discrete] +==== Match single and different documents -You can combine these two approaches to create complex queries. What if you wanted to find a store with more than 10 -bananas that *also* stocks vegetables? You could do this: +To find a store with more than 10 +bananas that *also* stocks vegetables: -`items:{ name:banana and stock > 10 } and items:{ category:vegetable }` +[source,yaml] +------------------- +items:{ name:banana and stock > 10 } and items:{ category:vegetable } +------------------- -The first nested group (`name:banana and stock > 10`) must still match a single document, but the `category:vegetables` +The first nested group (`name:banana and stock > 10`) must match a single document, but the `category:vegetables` subquery can match a different nested document because it is in a separate group. +[discrete] ==== Nested fields inside other nested fields -KQL's syntax also supports nested fields inside of other nested fields—you simply have to specify the full path. Suppose you -have a document where `level1` and `level2` are both nested fields: +KQL supports nested fields inside other nested fields—you have to +specify the full path. In this document, +`level1` and `level2` are nested fields: [source,json] ---------------------------------- @@ -171,6 +272,9 @@ have a document where `level1` and `level2` are both nested fields: } ---------------------------------- -You can match on a single nested document by specifying the full path: +To match on a single nested document: -`level1.level2:{ prop1:foo and prop2:bar }` +[source,yaml] +------------------- +level1.level2:{ prop1:foo and prop2:bar } +------------------- diff --git a/docs/discover/search.asciidoc b/docs/discover/search.asciidoc index da58382deb89a..ee1e1526f9d6f 100644 --- a/docs/discover/search.asciidoc +++ b/docs/discover/search.asciidoc @@ -28,7 +28,7 @@ configure a refresh interval to periodically resubmit your searches to retrieve the latest results. [role="screenshot"] -image::images/autorefresh-interval.png[] +image::images/autorefresh-interval.png[Image showing what refresh interval option looks like. The configurable time interval is located in the dropdown] You can also manually refresh the search results by clicking the *Refresh* button. diff --git a/docs/discover/set-time-filter.asciidoc b/docs/discover/set-time-filter.asciidoc index a5b81b0fa461c..93fdf9ffd695a 100644 --- a/docs/discover/set-time-filter.asciidoc +++ b/docs/discover/set-time-filter.asciidoc @@ -14,7 +14,7 @@ range in the histogram. Use the time filter to change the time range. By default, the time filter is set to the last 15 minutes. -. Click image:images/time-filter-calendar.png[]. +. Click image:images/time-filter-calendar.png[Calendar icon]. . Choose one of the following: @@ -53,4 +53,4 @@ when you hover over a valid start point. * Click the dropdown, then select an interval. [role="screenshot"] -image::images/Histogram-Time.png[Time range selector in Histogram] +image::images/Histogram-Time.png[Time range selector in Histogram dropdown] diff --git a/docs/discover/viewing-field-stats.asciidoc b/docs/discover/viewing-field-stats.asciidoc index 5ada5839fd344..5c46177347530 100644 --- a/docs/discover/viewing-field-stats.asciidoc +++ b/docs/discover/viewing-field-stats.asciidoc @@ -11,4 +11,4 @@ they are available in the side bar if you uncheck "Hide missing fields". To view field data statistics, click the name of a field in the fields list. -image:images/filter-field.png[Field Statistics,height=317] +image:images/filter-field.png[Fields list that displays the top five search results] diff --git a/docs/fleet/fleet.asciidoc b/docs/fleet/fleet.asciidoc new file mode 100644 index 0000000000000..7039468f4b185 --- /dev/null +++ b/docs/fleet/fleet.asciidoc @@ -0,0 +1,29 @@ +[chapter] +[role="xpack"] +[[fleet]] += {fleet} + +experimental[] + +{fleet} in {kib} enables you to add and manage integrations for popular +services and platforms, as well as manage {elastic-agent} installations in +standalone or {fleet} mode. + +Standalone mode requires you to manually configure and manage the agent locally. + +{fleet} mode offers several advantages: + +* A central place to configure and monitor your {agent}s. +* An overview of the data ingest in your {es} cluster. +* Multiple integrations to collect and transform data. + +//TODO: Redo screen capture. + +[role="screenshot"] +image::fleet/images/fleet-start.png[{fleet} app in {kib}] + +[float] +== Get started + +To get started with {fleet}, refer to the +{ingest-guide}/index.html[Ingest Management Guide]. diff --git a/docs/fleet/images/fleet-start.png b/docs/fleet/images/fleet-start.png new file mode 100644 index 0000000000000..60e5416fde127 Binary files /dev/null and b/docs/fleet/images/fleet-start.png differ diff --git a/docs/getting-started/images/add-sample-data.png b/docs/getting-started/images/add-sample-data.png index 1878550bc3169..b8c2002b9c4cd 100644 Binary files a/docs/getting-started/images/add-sample-data.png and b/docs/getting-started/images/add-sample-data.png differ diff --git a/docs/getting-started/images/gs_maps_time_filter.png b/docs/getting-started/images/gs_maps_time_filter.png deleted file mode 100644 index 83e20c279906e..0000000000000 Binary files a/docs/getting-started/images/gs_maps_time_filter.png and /dev/null differ diff --git a/docs/getting-started/images/tutorial-dashboard.png b/docs/getting-started/images/tutorial-dashboard.png deleted file mode 100644 index 8193d410bc5f1..0000000000000 Binary files a/docs/getting-started/images/tutorial-dashboard.png and /dev/null differ diff --git a/docs/getting-started/images/tutorial-discover-2.png b/docs/getting-started/images/tutorial-discover-2.png index 681e4834de830..cf217562c37fd 100644 Binary files a/docs/getting-started/images/tutorial-discover-2.png and b/docs/getting-started/images/tutorial-discover-2.png differ diff --git a/docs/getting-started/images/tutorial-discover-3.png b/docs/getting-started/images/tutorial-discover-3.png index bbab47acaf9d4..b024ad6dc39fe 100644 Binary files a/docs/getting-started/images/tutorial-discover-3.png and b/docs/getting-started/images/tutorial-discover-3.png differ diff --git a/docs/getting-started/images/tutorial-discover-4.png b/docs/getting-started/images/tutorial-discover-4.png new file mode 100644 index 0000000000000..945a6155c02cd Binary files /dev/null and b/docs/getting-started/images/tutorial-discover-4.png differ diff --git a/docs/getting-started/images/tutorial-final-dashboard.gif b/docs/getting-started/images/tutorial-final-dashboard.gif new file mode 100644 index 0000000000000..53b7bc04c5f65 Binary files /dev/null and b/docs/getting-started/images/tutorial-final-dashboard.gif differ diff --git a/docs/getting-started/images/tutorial-full-inspect1.png b/docs/getting-started/images/tutorial-full-inspect1.png deleted file mode 100644 index 94c9f2566f624..0000000000000 Binary files a/docs/getting-started/images/tutorial-full-inspect1.png and /dev/null differ diff --git a/docs/getting-started/images/tutorial-pattern-1.png b/docs/getting-started/images/tutorial-pattern-1.png deleted file mode 100644 index 0026b18775518..0000000000000 Binary files a/docs/getting-started/images/tutorial-pattern-1.png and /dev/null differ diff --git a/docs/getting-started/images/tutorial-sample-dashboard.png b/docs/getting-started/images/tutorial-sample-dashboard.png index ccce8c3bb3208..9f287640f201c 100644 Binary files a/docs/getting-started/images/tutorial-sample-dashboard.png and b/docs/getting-started/images/tutorial-sample-dashboard.png differ diff --git a/docs/getting-started/images/tutorial-sample-discover1.png b/docs/getting-started/images/tutorial-sample-discover1.png deleted file mode 100644 index 1bad8774ba584..0000000000000 Binary files a/docs/getting-started/images/tutorial-sample-discover1.png and /dev/null differ diff --git a/docs/getting-started/images/tutorial-sample-discover2.png b/docs/getting-started/images/tutorial-sample-discover2.png deleted file mode 100644 index a439f1d76a991..0000000000000 Binary files a/docs/getting-started/images/tutorial-sample-discover2.png and /dev/null differ diff --git a/docs/getting-started/images/tutorial-sample-edit1.png b/docs/getting-started/images/tutorial-sample-edit1.png deleted file mode 100644 index b5ae56b5c0d83..0000000000000 Binary files a/docs/getting-started/images/tutorial-sample-edit1.png and /dev/null differ diff --git a/docs/getting-started/images/tutorial-sample-edit2.png b/docs/getting-started/images/tutorial-sample-edit2.png deleted file mode 100644 index 17a029a17e1b4..0000000000000 Binary files a/docs/getting-started/images/tutorial-sample-edit2.png and /dev/null differ diff --git a/docs/getting-started/images/tutorial-sample-filter.png b/docs/getting-started/images/tutorial-sample-filter.png index 770e26e951b3a..7c1d041448557 100644 Binary files a/docs/getting-started/images/tutorial-sample-filter.png and b/docs/getting-started/images/tutorial-sample-filter.png differ diff --git a/docs/getting-started/images/tutorial-sample-filter2.png b/docs/getting-started/images/tutorial-sample-filter2.png new file mode 100644 index 0000000000000..21402feacdecd Binary files /dev/null and b/docs/getting-started/images/tutorial-sample-filter2.png differ diff --git a/docs/getting-started/images/tutorial-sample-inspect1.png b/docs/getting-started/images/tutorial-sample-inspect1.png deleted file mode 100644 index 6a3d41ae03584..0000000000000 Binary files a/docs/getting-started/images/tutorial-sample-inspect1.png and /dev/null differ diff --git a/docs/getting-started/images/tutorial-sample-query.png b/docs/getting-started/images/tutorial-sample-query.png index 847542c0b17ff..4f1ca24924b28 100644 Binary files a/docs/getting-started/images/tutorial-sample-query.png and b/docs/getting-started/images/tutorial-sample-query.png differ diff --git a/docs/getting-started/images/tutorial-sample-query2.png b/docs/getting-started/images/tutorial-sample-query2.png new file mode 100644 index 0000000000000..0e91e1069a201 Binary files /dev/null and b/docs/getting-started/images/tutorial-sample-query2.png differ diff --git a/docs/getting-started/images/tutorial-treemap.png b/docs/getting-started/images/tutorial-treemap.png new file mode 100644 index 0000000000000..32e14fd2308e3 Binary files /dev/null and b/docs/getting-started/images/tutorial-treemap.png differ diff --git a/docs/getting-started/images/tutorial-visualization-dropdown.png b/docs/getting-started/images/tutorial-visualization-dropdown.png new file mode 100644 index 0000000000000..29d1b99700964 Binary files /dev/null and b/docs/getting-started/images/tutorial-visualization-dropdown.png differ diff --git a/docs/getting-started/images/tutorial-visualize-bar-1.5.png b/docs/getting-started/images/tutorial-visualize-bar-1.5.png deleted file mode 100644 index 009152f9407e4..0000000000000 Binary files a/docs/getting-started/images/tutorial-visualize-bar-1.5.png and /dev/null differ diff --git a/docs/getting-started/images/tutorial-visualize-map-2.png b/docs/getting-started/images/tutorial-visualize-map-2.png deleted file mode 100644 index ed2fd47cb27de..0000000000000 Binary files a/docs/getting-started/images/tutorial-visualize-map-2.png and /dev/null differ diff --git a/docs/getting-started/images/tutorial-visualize-md-2.png b/docs/getting-started/images/tutorial-visualize-md-2.png deleted file mode 100644 index af56faa3b0516..0000000000000 Binary files a/docs/getting-started/images/tutorial-visualize-md-2.png and /dev/null differ diff --git a/docs/getting-started/images/tutorial-visualize-pie-2.png b/docs/getting-started/images/tutorial-visualize-pie-2.png deleted file mode 100644 index ca8f5e92146bc..0000000000000 Binary files a/docs/getting-started/images/tutorial-visualize-pie-2.png and /dev/null differ diff --git a/docs/getting-started/images/tutorial-visualize-pie-3.png b/docs/getting-started/images/tutorial-visualize-pie-3.png deleted file mode 100644 index 59fce360096c0..0000000000000 Binary files a/docs/getting-started/images/tutorial-visualize-pie-3.png and /dev/null differ diff --git a/docs/getting-started/images/tutorial-visualize-wizard-step-1.png b/docs/getting-started/images/tutorial-visualize-wizard-step-1.png deleted file mode 100644 index afc9dda648265..0000000000000 Binary files a/docs/getting-started/images/tutorial-visualize-wizard-step-1.png and /dev/null differ diff --git a/docs/getting-started/images/tutorial_index_patterns.png b/docs/getting-started/images/tutorial_index_patterns.png deleted file mode 100644 index 430baf898b612..0000000000000 Binary files a/docs/getting-started/images/tutorial_index_patterns.png and /dev/null differ diff --git a/docs/getting-started/quick-start-guide.asciidoc b/docs/getting-started/quick-start-guide.asciidoc new file mode 100644 index 0000000000000..6386feac5ab49 --- /dev/null +++ b/docs/getting-started/quick-start-guide.asciidoc @@ -0,0 +1,142 @@ +[[get-started]] +== Quick start + +To quickly get up and running with {kib}, set up on Cloud, then add a sample data set that you can explore and analyze. + +When you've finished, you'll know how to: + +* <> + +* <> + +[float] +=== Before you begin +When security is enabled, you must have `read`, `write`, and `manage` privileges on the `kibana_sample_data_*` indices. For more information, refer to {ref}/security-privileges.html[Security privileges]. + +[float] +[[set-up-on-cloud]] +== Set up on cloud + +include::{docs-root}/shared/cloud/ess-getting-started.asciidoc[] + +[float] +[[gs-get-data-into-kibana]] +== Add the sample data + +Sample data sets come with sample visualizations, dashboards, and more to help you explore {kib} without adding your own data. + +. From the home page, click *Try our sample data*. + +. On the *Sample eCommerce orders* card, click *Add data*. ++ +[role="screenshot"] +image::getting-started/images/add-sample-data.png[] + +[float] +[[explore-the-data]] +== Explore the data + +*Discover* displays an interactive histogram that shows the distribution of of data, or documents, over time, and a table that lists the fields for each document that matches the index. By default, all fields are shown for each matching document. + +. Open the menu, then click *Discover*. + +. Change the <> to *Last 7 days*. ++ +[role="screenshot"] +image::images/tutorial-discover-2.png[] + +. To focus in on the documents you want to view, use the <>. In the *KQL* search field, enter: ++ +[source,text] +products.taxless_price >= 60 AND category : Women's Clothing ++ +The query returns the women's clothing orders for $60 and more. ++ +[role="screenshot"] +image::images/tutorial-discover-4.png[] + +. Hover over the list of *Available fields*, then click *+* next to the fields you want to view in the table. ++ +For example, when you add the *category* field, the table displays the product categories for the orders. ++ +[role="screenshot"] +image::images/tutorial-discover-3.png[] ++ +For more information, refer to <>. + +[float] +[[view-and-analyze-the-data]] +== View and analyze the data + +A dashboard is a collection of panels that you can use to view and analyze the data. Panels contain visualizations, interactive controls, Markdown, and more. + +. Open the menu, then click *Dashboard*. + +. Click *[eCommerce] Revenue Dashboard*. ++ +[role="screenshot"] +image::getting-started/images/tutorial-sample-dashboard.png[] + +[float] +[[filter-and-query-the-data]] +=== Filter the data + +To focus in on the data you want to view on the dashboard, use filters. + +. From the *Controls* visualization, make a selection from the *Manufacturer* and *Category* dropdowns, then click *Apply changes*. ++ +For example, the following dashboard shows the data for women's clothing from Gnomehouse. ++ +[role="screenshot"] +image::getting-started/images/tutorial-sample-filter.png[] + +. To manually add a filter, click *Add filter*, then specify the options. ++ +For example, to view the orders for Wednesday, select *day_of_week* from the *Field* dropdown, select *is* from the *Operator* dropdown, then select *Wednesday* from the *Value* dropdown. ++ +[role="screenshot"] +image::getting-started/images/tutorial-sample-filter2.png[] + +. When you are done, remove the filters. ++ +For more information, refer to <>. + +[float] +[[create-a-visualization]] +=== Create a visualization + +To create a treemap that shows the top regions and manufacturers, use *Lens*, then add the treemap to the dashboard. + +. From the {kib} toolbar, click *Edit*, then click *Create new*. + +. On the *New Visualization* window, click *Lens*. + +. From the *Available fields* list, drag and drop the following fields to the visualization builder: + +* *geoip.city_name* + +* *manufacturer.keyword* ++ +. From the visualization dropdown, select *Treemap*. ++ +[role="screenshot"] +image::getting-started/images/tutorial-visualization-dropdown.png[Visualization dropdown with Treemap selected] + +. Click *Save*. + +. On the *Save Lens visualization*, enter a title and make sure *Add to Dashboard after saving* is selected, then click *Save and return*. ++ +The treemap appears as the last visualization on the dashboard. ++ +[role="screenshot"] +image::getting-started/images/tutorial-final-dashboard.gif[Final dashboard with new treemap visualization] ++ +For more information, refer to <>. + +[float] +[[quick-start-whats-next]] +== What's next? + +If you are you ready to add your own data, refer to <>. + +If you want to ingest your data, refer to {ingest-guide}/ingest-management-getting-started.html[Quick start: Get logs and metrics into the Elastic Stack]. diff --git a/docs/getting-started/tutorial-define-index.asciidoc b/docs/getting-started/tutorial-define-index.asciidoc deleted file mode 100644 index fbe7450683dbc..0000000000000 --- a/docs/getting-started/tutorial-define-index.asciidoc +++ /dev/null @@ -1,51 +0,0 @@ -[[tutorial-define-index]] -=== Define your index patterns - -Index patterns tell {kib} which {es} indices you want to explore. -An index pattern can match the name of a single index, or include a wildcard -(*) to match multiple indices. - -For example, Logstash typically creates a -series of indices in the format `logstash-YYYY.MMM.DD`. To explore all -of the log data from May 2018, you could specify the index pattern -`logstash-2018.05*`. - -[float] -==== Create the index patterns - -First you'll create index patterns for the Shakespeare data set, which has an -index named `shakespeare,` and the accounts data set, which has an index named -`bank`. These data sets don't contain time series data. - -. Open the menu, then go to *Stack Management > {kib} > Index Patterns*. - -. If this is your first index pattern, the *Create index pattern* page opens. - -. In the *Index pattern name* field, enter `shakes*`. -+ -[role="screenshot"] -image::images/tutorial-pattern-1.png[shakes* index patterns] - -. Click *Next step*. - -. On the *Configure settings* page, *Create index pattern*. -+ -You’re presented a table of all fields and associated data types in the index. - -. Create a second index pattern named `ba*`. - -[float] -==== Create an index pattern for the time series data - -Create an index pattern for the Logstash index, which -contains the time series data. - -. Create an index pattern named `logstash*`, then click *Next step*. - -. From the *Time field* dropdown, select *@timestamp, then click *Create index pattern*. -+ -[role="screenshot"] -image::images/tutorial_index_patterns.png[All tutorial index patterns] - - - diff --git a/docs/getting-started/tutorial-discovering.asciidoc b/docs/getting-started/tutorial-discovering.asciidoc deleted file mode 100644 index ec07a74b8ac0d..0000000000000 --- a/docs/getting-started/tutorial-discovering.asciidoc +++ /dev/null @@ -1,35 +0,0 @@ -[[explore-your-data]] -=== Explore your data - -With *Discover*, you use {ref}/query-dsl-query-string-query.html#query-string-syntax[Elasticsearch -queries] to explore your data and narrow the results with filters. - -. Open the menu, then go to *Discover*. -+ -The `shakes*` index pattern appears. - -. To make `ba*` the index, click the *Change Index Pattern* dropdown, then select `ba*`. -+ -By default, all fields are shown for each matching document. - -. In the *Search* field, enter the following, then click *Update*: -+ -[source,text] -account_number<100 AND balance>47500 -+ -The search returns all account numbers between zero and 99 with balances in -excess of 47,500. Results appear for account numbers 8, 32, 78, 85, and 97. -+ -[role="screenshot"] -image::images/tutorial-discover-2.png[] -+ -. Hover over the list of *Available fields*, then -click *Add* next to each field you want include in the table. -+ -For example, when you add the `account_number` field, the display changes to a list of five -account numbers. -+ -[role="screenshot"] -image::images/tutorial-discover-3.png[] - -Now that you know what your documents contain, it's time to gain insight into your data with visualizations. diff --git a/docs/getting-started/tutorial-full-experience.asciidoc b/docs/getting-started/tutorial-full-experience.asciidoc deleted file mode 100644 index 1e6fe39dbd013..0000000000000 --- a/docs/getting-started/tutorial-full-experience.asciidoc +++ /dev/null @@ -1,212 +0,0 @@ -[[create-your-own-dashboard]] -== Create your own dashboard - -Ready to add data to {kib} and create your own dashboard? In this tutorial, you'll use three types of data sets that'll help you learn to: - -* <> -* <> -* <> -* <> - -[float] -[[download-the-data]] -=== Download the data - -To complete the tutorial, you'll download and use the following data sets: - -* The complete works of William Shakespeare, suitably parsed into fields -* A set of fictitious bank accounts with randomly generated data -* A set of randomly generated log files - -Create a new working directory where you want to download the files. From that directory, run the following commands: - -[source,shell] -curl -O https://download.elastic.co/demos/kibana/gettingstarted/8.x/shakespeare.json -curl -O https://download.elastic.co/demos/kibana/gettingstarted/8.x/accounts.zip -curl -O https://download.elastic.co/demos/kibana/gettingstarted/8.x/logs.jsonl.gz - -Two of the data sets are compressed. To extract the files, use the following commands: - -[source,shell] -unzip accounts.zip -gunzip logs.jsonl.gz - -[float] -==== Structure of the data sets - -The Shakespeare data set has the following structure: - -[source,json] -{ - "line_id": INT, - "play_name": "String", - "speech_number": INT, - "line_number": "String", - "speaker": "String", - "text_entry": "String", -} - -The accounts data set has the following structure: - -[source,json] -{ - "account_number": INT, - "balance": INT, - "firstname": "String", - "lastname": "String", - "age": INT, - "gender": "M or F", - "address": "String", - "employer": "String", - "email": "String", - "city": "String", - "state": "String" -} - -The logs data set has dozens of different fields. The notable fields include the following: - -[source,json] -{ - "memory": INT, - "geo.coordinates": "geo_point" - "@timestamp": "date" -} - -[float] -==== Set up mappings - -Before you load the Shakespeare and logs data sets, you must set up {ref}/mapping.html[_mappings_] for the fields. -Mappings divide the documents in the index into logical groups and specify the characteristics -of the fields. These characteristics include the searchability of the field -and whether it's _tokenized_, or broken up into separate words. - -NOTE: If security is enabled, you must have the `all` Kibana privilege to run this tutorial. -You must also have the `create`, `manage` `read`, `write,` and `delete` -index privileges. See {ref}/security-privileges.html[Security privileges] -for more information. - -Open the menu, then go to *Dev Tools*. On the *Console* page, set up a mapping for the Shakespeare data set: - -[source,js] -PUT /shakespeare -{ - "mappings": { - "properties": { - "speaker": {"type": "keyword"}, - "play_name": {"type": "keyword"}, - "line_id": {"type": "integer"}, - "speech_number": {"type": "integer"} - } - } -} - -//CONSOLE - -The mapping specifies field characteristics for the data set: - -* The `speaker` and `play_name` fields are keyword fields. These fields are not analyzed. -The strings are treated as a single unit even if they contain multiple words. - -* The `line_id` and `speech_number` fields are integers. - -The logs data set requires a mapping to label the latitude and longitude pairs -as geographic locations by applying the `geo_point` type. - -[source,js] -PUT /logstash-2015.05.18 -{ - "mappings": { - "properties": { - "geo": { - "properties": { - "coordinates": { - "type": "geo_point" - } - } - } - } - } -} - -//CONSOLE - -[source,js] -PUT /logstash-2015.05.19 -{ - "mappings": { - "properties": { - "geo": { - "properties": { - "coordinates": { - "type": "geo_point" - } - } - } - } - } -} - -//CONSOLE - -[source,js] -PUT /logstash-2015.05.20 -{ - "mappings": { - "properties": { - "geo": { - "properties": { - "coordinates": { - "type": "geo_point" - } - } - } - } - } -} - -//CONSOLE - -The accounts data set doesn't require any mappings. - -[float] -[[load-the-data-sets]] -==== Load the data sets - -At this point, you're ready to use the Elasticsearch {ref}/docs-bulk.html[bulk] -API to load the data sets: - -[source,shell] -curl -u elastic -H 'Content-Type: application/x-ndjson' -XPOST ':/bank/_bulk?pretty' --data-binary @accounts.json -curl -u elastic -H 'Content-Type: application/x-ndjson' -XPOST ':/shakespeare/_bulk?pretty' --data-binary @shakespeare.json -curl -u elastic -H 'Content-Type: application/x-ndjson' -XPOST ':/_bulk?pretty' --data-binary @logs.jsonl - -Or for Windows users, in Powershell: -[source,shell] -Invoke-RestMethod "http://:/bank/account/_bulk?pretty" -Method Post -ContentType 'application/x-ndjson' -InFile "accounts.json" -Invoke-RestMethod "http://:/shakespeare/_bulk?pretty" -Method Post -ContentType 'application/x-ndjson' -InFile "shakespeare.json" -Invoke-RestMethod "http://:/_bulk?pretty" -Method Post -ContentType 'application/x-ndjson' -InFile "logs.jsonl" - -These commands might take some time to execute, depending on the available computing resources. - -When you define an index pattern, the indices that match the pattern must -exist in {es} and contain data. - -To verify the availability of the indices, open the menu, go to *Dev Tools > Console*, then enter: - -[source,js] -GET /_cat/indices?v - -Alternately, use: - -[source,shell] -`curl -XGET "http://localhost:9200/_cat/indices"`. - -The output should look similar to: - -[source,shell] -health status index pri rep docs.count docs.deleted store.size pri.store.size -yellow open bank 1 1 1000 0 418.2kb 418.2kb -yellow open shakespeare 1 1 111396 0 17.6mb 17.6mb -yellow open logstash-2015.05.18 1 1 4631 0 15.6mb 15.6mb -yellow open logstash-2015.05.19 1 1 4624 0 15.7mb 15.7mb -yellow open logstash-2015.05.20 1 1 4750 0 16.4mb 16.4mb diff --git a/docs/getting-started/tutorial-sample-data.asciidoc b/docs/getting-started/tutorial-sample-data.asciidoc deleted file mode 100644 index 18ef862272f85..0000000000000 --- a/docs/getting-started/tutorial-sample-data.asciidoc +++ /dev/null @@ -1,159 +0,0 @@ -[[explore-kibana-using-sample-data]] -== Explore {kib} using sample data - -Ready to get some hands-on experience with {kib}? -In this tutorial, you’ll work with {kib} sample data and learn to: - -* <> - -* <> - -* <> - -NOTE: If security is enabled, you must have `read`, `write`, and `manage` privileges -on the `kibana_sample_data_*` indices. For more information, refer to -{ref}/security-privileges.html[Security privileges]. - -[float] -[[add-the-sample-data]] -=== Add the sample data - -Add the *Sample flight data*. - -. On the home page, click *Load a data set and a {kib} dashboard*. - -. On the *Sample flight data* card, click *Add data*. - -[float] -[[explore-the-data]] -=== Explore the data - -Explore the documents in the index that -match the selected index pattern. The index pattern tells {kib} which {es} index you want to -explore. - -. Open the menu, then go to *Discover*. - -. Make sure `kibana_sample_data_flights` is the current index pattern. -You might need to click *New* in the {kib} toolbar to refresh the data. -+ -You'll see a histogram that shows the distribution of -documents over time. A table lists the fields for -each document that matches the index. By default, all fields are shown. -+ -[role="screenshot"] -image::getting-started/images/tutorial-sample-discover1.png[] - -. Hover over the list of *Available fields*, then click *Add* next -to each field you want explore in the table. -+ -[role="screenshot"] -image::getting-started/images/tutorial-sample-discover2.png[] - -[float] -[[view-and-analyze-the-data]] -=== View and analyze the data - -A _dashboard_ is a collection of panels that provide you with an overview of your data that you can -use to analyze your data. Panels contain everything you need, including visualizations, -interactive controls, Markdown, and more. - -To open the *Global Flight* dashboard, open the menu, then go to *Dashboard*. - -[role="screenshot"] -image::getting-started/images/tutorial-sample-dashboard.png[] - -[float] -[[change-the-panel-data]] -==== Change the panel data - -To gain insights into your data, change the appearance and behavior of the panels. -For example, edit the metric panel to find the airline that has the lowest average fares. - -. In the {kib} toolbar, click *Edit*. - -. In the *Average Ticket Price* metric panel, open the panel menu, then select *Edit visualization*. - -. To change the data on the panel, use an {es} {ref}/search-aggregations.html[bucket aggregation], -which sorts the documents that match your search criteria into different categories or buckets. - -.. In the *Buckets* pane, select *Add > Split group*. - -.. From the *Aggregation* dropdown, select *Terms*. - -.. From the *Field* dropdown, select *Carrier*. - -.. Set *Descending* to *4*, then click *Update*. -+ -The average ticket price for all four airlines appear in the visualization builder. -+ -[role="screenshot"] -image::getting-started/images/tutorial-sample-edit1.png[] - -. To save your changes, click *Save and return* in the {kib} toolbar. - -. To save the dashboard, click *Save* in the {kib} toolbar. -+ -[role="screenshot"] -image::getting-started/images/tutorial-sample-edit2.png[] - -[float] -[[filter-and-query-the-data]] -==== Filter and query the data - -To focus in on the data you want to explore, use filters and queries. -For more information, refer to -{ref}/query-filter-context.html[Query and filter context]. - -To filter the data: - -. In the *Controls* visualization, select an *Origin City* and *Destination City*, then click *Apply changes*. -+ -The `OriginCityName` and the `DestCityName` fields filter the data in the panels. -+ -For example, the following dashboard shows the data for flights from London to Milan. -+ -[role="screenshot"] -image::getting-started/images/tutorial-sample-filter.png[] - -. To manually add a filter, click *Add filter*, -then specify the data you want to view. - -. When you are finished experimenting, remove all filters. - -[[query-the-data]] -To query the data: - -. To view all flights out of Rome, enter the following in the *KQL* query bar, then click *Update*: -+ -[source,text] -OriginCityName: Rome - -. For a more complex query with AND and OR, enter: -+ -[source,text] -OriginCityName:Rome AND (Carrier:JetBeats OR Carrier:"Kibana Airlines") -+ -The dashboard panels update to display the flights out of Rome on JetBeats and -{kib} Airlines. -+ -[role="screenshot"] -image::getting-started/images/tutorial-sample-query.png[] - -. When you are finished exploring, remove the query by -clearing the contents in the *KQL* query bar, then click *Update*. - -[float] -=== Next steps - -Now that you know the {kib} basics, try out the <> tutorial, where you'll learn to: - -* Add a data set to {kib} - -* Define an index pattern - -* Discover and explore data - -* Create and add panels to a dashboard - - diff --git a/docs/getting-started/tutorial-visualizing.asciidoc b/docs/getting-started/tutorial-visualizing.asciidoc deleted file mode 100644 index 33a7035160247..0000000000000 --- a/docs/getting-started/tutorial-visualizing.asciidoc +++ /dev/null @@ -1,193 +0,0 @@ -[[tutorial-visualizing]] -=== Visualize your data - -Shape your data using a variety -of {kib} supported visualizations, tables, and more. In this tutorial, you'll create four -visualizations that you'll use to create a dashboard. - -To begin, open the menu, go to *Dashboard*, then click *Create new dashboard*. - -[float] -[[compare-the-number-of-speaking-parts-in-the-play]] -=== Compare the number of speaking parts in the plays - -To visualize the Shakespeare data and compare the number of speaking parts in the plays, create a bar chart using *Lens*. - -. Click *Create new*, then click *Lens* on the *New Visualization* window. -+ -[role="screenshot"] -image::images/tutorial-visualize-wizard-step-1.png[Bar chart] - -. Make sure the index pattern is *shakes*. - -. Display the play data along the x-axis. - -.. From the *Available fields* list, drag and drop *play_name* to the *X-axis* field. - -.. Click *Top values of play_name*. - -.. From the *Order direction* dropdown, select *Ascending*. - -.. In the *Label* field, enter `Play Name`. - -. Display the number of speaking parts per play along the y-axis. - -.. From the *Available fields* list, drag and drop *speaker* to the *Y-axis* field. - -.. Click *Unique count of speaker*. - -.. In the *Label* field, enter `Speaking Parts`. -+ -[role="screenshot"] -image::images/tutorial-visualize-bar-1.5.png[Bar chart] - -. *Save* the chart with the name `Bar Example`. -+ -To show a tooltip with the number of speaking parts for that play, hover over a bar. -+ -Notice how the individual play names show up as whole phrases, instead of -broken up into individual words. This is the result of the mapping -you did at the beginning of the tutorial, when you marked the `play_name` field -as `not analyzed`. - -[float] -[[view-the-average-account-balance-by-age]] -=== View the average account balance by age - -To gain insight into the account balances in the bank account data, create a pie chart. In this tutorial, you'll use the {es} -{ref}/search-aggregations.html[bucket aggregation] to specify the pie slices to display. The bucket aggregation sorts the documents that match your search criteria into different -categories and establishes multiple ranges of account balances so that you can find how many accounts fall into each range. - -. Click *Create new*, then click *Pie* on the *New Visualization* window. - -. On the *Choose a source* window, select `ba*`. -+ -Since the default search matches all documents, the pie contains a single slice. - -. In the *Buckets* pane, click *Add > Split slices.* - -.. From the *Aggregation* dropdown, select *Range*. - -.. From the *Field* dropdown, select *balance*. - -.. Click *Add range* until there are six rows of fields, then define the following ranges: -+ -[source,text] -0 999 -1000 2999 -3000 6999 -7000 14999 -15000 30999 -31000 50000 - -. Click *Update*. -+ -The pie chart displays the proportion of the 1,000 accounts that fall into each of the ranges. -+ -[role="screenshot"] -image::images/tutorial-visualize-pie-2.png[Pie chart] - -. Add another bucket aggregation that displays the ages of the account holders. - -.. In the *Buckets* pane, click *Add*, then click *Split slices*. - -.. From the *Sub aggregation* dropdown, select *Terms*. - -.. From the *Field* dropdown, select *age*, then click *Update*. -+ -The break down of the ages of the account holders are displayed -in a ring around the balance ranges. -+ -[role="screenshot"] -image::images/tutorial-visualize-pie-3.png[Final pie chart] - -. Click *Save*, then enter `Pie Example` in the *Title* field. - -[float] -[role="xpack"] -[[visualize-geographic-information]] -=== Visualize geographic information - -To visualize geographic information in the log file data, use <>. - -. Click *Create new*, then click *Maps* on the *New Visualization* window. - -. To change the time, use the time filter. - -.. Set the *Start date* to `May 18, 2015 @ 12:00:00.000`. - -.. Set the *End date* to `May 20, 2015 @ 12:00:00.000`. -+ -[role="screenshot"] -image::images/gs_maps_time_filter.png[Time filter for Maps tutorial] - -.. Click *Update* - -. Map the geo coordinates from the log files. - -.. Click *Add layer > Clusters and grids*. - -.. From the *Index pattern* dropdown, select *logstash*. - -.. Click *Add layer*. - -. Specify the *Layer Style*. - -.. From the *Fill color* dropdown, select the yellow to red color ramp. - -.. In the *Border width* field, enter `3`. - -.. From the *Border color* dropdown, select *#FFF*, then click *Save & close*. -+ -[role="screenshot"] -image::images/tutorial-visualize-map-2.png[Map] - -. Click *Save*, then enter `Map Example` in the *Title* field. - -. Add the map to your dashboard. - -.. Open the menu, go to *Dashboard*, then click *Add*. - -.. On the *Add panels* flyout, click *Map Example*. - -[float] -[[tutorial-visualize-markdown]] -=== Add context to your visualizations with Markdown - -Add context to your new visualizations with Markdown text. - -. Click *Create new*, then click *Markdown* on the *New Visualization* window. - -. In the *Markdown* text field, enter: -+ -[source,markdown] -# This is a tutorial dashboard! -The Markdown widget uses **markdown** syntax. -> Blockquotes in Markdown use the > character. - -. Click *Update*. -+ -The Markdown renders in the preview pane. -+ -[role="screenshot"] -image::images/tutorial-visualize-md-2.png[] - -. Click *Save*, then enter `Markdown Example` in the *Title* field. - -[role="screenshot"] -image::images/tutorial-dashboard.png[] - -[float] -=== Next steps - -Now that you have the basics, you're ready to start exploring your own system data with {kib}. - -* To add your own data to {kib}, refer to <>. - -* To search and filter your data, refer to {kibana-ref}/discover.html[Discover]. - -* To create a dashboard with your own data, refer to <>. - -* To create maps that you can add to your dashboards, refer to <>. - -* To create presentations of your live data, refer to <>. diff --git a/docs/ingest_manager/images/ingest-manager-start.png b/docs/ingest_manager/images/ingest-manager-start.png deleted file mode 100644 index 89174686a9768..0000000000000 Binary files a/docs/ingest_manager/images/ingest-manager-start.png and /dev/null differ diff --git a/docs/ingest_manager/ingest-manager.asciidoc b/docs/ingest_manager/ingest-manager.asciidoc deleted file mode 100644 index 8f6e8036c68cd..0000000000000 --- a/docs/ingest_manager/ingest-manager.asciidoc +++ /dev/null @@ -1,27 +0,0 @@ -[chapter] -[role="xpack"] -[[ingest-manager]] -= {ingest-manager} - -experimental[] - -{ingest-manager} in {kib} enables you to add and manage integrations for popular -services and platforms, as well as manage {elastic-agent} installations in -standalone or {fleet} mode. - -Standalone mode requires you to manually configure and manage the agent locally. - -{fleet} mode offers several advantages: - -* A central place to configure and monitor your {agent}s. -* An overview of the data ingest in your {es} cluster. -* Multiple integrations to collect and transform data. - -[role="screenshot"] -image::ingest_manager/images/ingest-manager-start.png[{ingest-manager} app in {kib}] - -[float] -== Get started - -To get started with {ingest-management}, refer to the -{ingest-guide}/index.html[Ingest Management Guide]. diff --git a/docs/management/advanced-options.asciidoc b/docs/management/advanced-options.asciidoc index ed20166c87f29..8e8d0e5bf996e 100644 --- a/docs/management/advanced-options.asciidoc +++ b/docs/management/advanced-options.asciidoc @@ -1,9 +1,10 @@ [[advanced-options]] == Advanced Settings -The *Advanced Settings* UI enables you to edit settings that control the behavior of Kibana. -For example, you can change the format used to display dates, specify the default index pattern, and set the precision -for displayed decimal values. +The *Advanced Settings* UI enables you to edit settings that control the +behavior of Kibana. For example, you can change the format used to display dates, +specify the default index pattern, and set the precision for displayed decimal +values. . Open the menu, then go to *Stack Management > {kib} > Advanced Settings*. . Scroll or search for the setting you want to modify. @@ -15,8 +16,9 @@ for displayed decimal values. [[settings-read-only-access]] === [xpack]#Read only access# When you have insufficient privileges to edit advanced settings, the following -indicator in Kibana will be displayed. The buttons to edit settings won't be visible. -For more information on granting access to Kibana see <>. +indicator in Kibana will be displayed. The buttons to edit settings won't be +visible. For more information on granting access to Kibana, see +<>. [role="screenshot"] image::images/settings-read-only-badge.png[Example of Advanced Settings Management's read only access indicator in Kibana's header] @@ -25,12 +27,11 @@ image::images/settings-read-only-badge.png[Example of Advanced Settings Manageme [[kibana-settings-reference]] === Kibana settings reference -WARNING: Modifying a setting can affect {kib} -performance and cause problems that are -difficult to diagnose. Setting a property value to a blank field reverts -to the default behavior, which might not be -compatible with other configuration settings. Deleting a custom setting -removes it from {kib} permanently. +WARNING: Modifying a setting can affect {kib} performance and cause problems +that are difficult to diagnose. Setting a property value to a blank field +reverts to the default behavior, which might not be compatible with other +configuration settings. Deleting a custom setting removes it from {kib} +permanently. [float] @@ -38,72 +39,159 @@ removes it from {kib} permanently. ==== General [horizontal] -`csv:quoteValues`:: Set this property to `true` to quote exported values. -`csv:separator`:: A string that serves as the separator for exported values. -`dateFormat`:: The format to use for displaying https://momentjs.com/docs/#/displaying/format/[pretty formatted dates]. -`dateFormat:dow`:: The day that a week should start on. -`dateFormat:scaled`:: The values that define the format to use to render ordered time-based data. Formatted timestamps must -adapt to the interval between measurements. Keys are http://en.wikipedia.org/wiki/ISO_8601#Time_intervals[ISO8601 intervals]. -`dateFormat:tz`:: The timezone that Kibana uses. The default value of `Browser` uses the timezone detected by the browser. -`dateNanosFormat`:: The format to use for displaying https://momentjs.com/docs/#/displaying/format/[pretty formatted dates] of {ref}/date_nanos.html[Elasticsearch date_nanos type]. -`defaultIndex`:: The index to access if no index is set. The default is `null`. -`defaultRoute`:: The default route when opening Kibana. Use this setting to route users to a specific dashboard, application, or saved object as they enter each space. -`fields:popularLimit`:: The top N most popular fields to show. -`filterEditor:suggestValues`:: Set this property to `false` to prevent the filter editor from suggesting values for fields. -`filters:pinnedByDefault`:: Set this property to `true` to make filters have a global state (be pinned) by default. -`format:bytes:defaultPattern`:: The default <> format for the "bytes" format. -`format:currency:defaultPattern`:: The default <> format for the "currency" format. -`format:defaultTypeMap`:: A map of the default format name for each field type. Field types that are not explicitly -mentioned use "\_default_". -`format:number:defaultLocale`:: The <> locale. -`format:number:defaultPattern`:: The <> for the "number" format. -`format:percent:defaultPattern`:: The <> for the "percent" format. -`histogram:barTarget`:: When date histograms use the `auto` interval, Kibana attempts to generate this number of bars. -`histogram:maxBars`:: Date histograms are not generated with more bars than the value of this property, scaling values -when necessary. -`history:limit`:: In fields that have history, such as query inputs, show this many recent values. -`indexPattern:placeholder`:: The default placeholder value to use in Management > Index Patterns > Create Index Pattern. -`metaFields`:: Fields that exist outside of `_source`. Kibana merges these fields -into the document when displaying it. -`metrics:max_buckets`:: The maximum numbers of buckets that a single -data source can return. This might arise when the user selects a -short interval (for example, 1s) for a long time period (1 year). -`pageNavigation`:: The style of navigation menu for Kibana. -Choices are Legacy, the legacy style where every plugin is represented in the nav, -and Modern, a new format that bundles related plugins together in flyaway nested navigation. -`query:allowLeadingWildcards`:: Allows a wildcard (*) as the first character -in a query clause. Only applies when experimental query features are -enabled in the query bar. To disallow leading wildcards in Lucene queries, -use `query:queryString:options`. -`query:queryString:options`:: Options for the Lucene query string parser. Only -used when "Query language" is set to Lucene. -`savedObjects:listingLimit`:: The number of objects to fetch for lists of saved objects. -The default value is 1000. Do not set above 10000. -`savedObjects:perPage`:: The number of objects to show on each page of the -list of saved objects. The default is 5. -`search:queryLanguage`:: The query language to use in the query bar. -Choices are <>, a language built specifically for {kib}, and the <>. -`shortDots:enable`:: Set this property to `true` to shorten long -field names in visualizations. For example, show `f.b.baz` instead of `foo.bar.baz`. -`sort:options`:: Options for the Elasticsearch {ref}/search-request-body.html#request-body-search-sort[sort] parameter. -`state:storeInSessionStorage`:: [experimental] Kibana tracks UI state in the -URL, which can lead to problems when there is a lot of state information, -and the URL gets very long. -Enabling this setting stores part of the URL in your browser session to keep the -URL short. -`theme:darkMode`:: Set to `true` to enable a dark mode for the {kib} UI. You must -refresh the page to apply the setting. -`timepicker:quickRanges`:: The list of ranges to show in the Quick section of -the time filter. This should be an array of objects, with each object containing -`from`, `to` (see {ref}/common-options.html#date-math[accepted formats]), -and `display` (the title to be displayed). -`timepicker:refreshIntervalDefaults`:: The default refresh interval for the time filter. Example: `{ "display": "15 seconds", "pause": true, "value": 15000 }`. -`timepicker:timeDefaults`:: The default selection in the time filter. -`truncate:maxHeight`:: The maximum height that a cell occupies in a table. Set to 0 to disable +[[csv-quotevalues]]`csv:quoteValues`:: +Set this property to `true` to quote exported values. + +[[csv-separator]]`csv:separator`:: +A string that serves as the separator for exported values. + +[[dateformat]]`dateFormat`:: +The format to use for displaying +https://momentjs.com/docs/#/displaying/format/[pretty formatted dates]. + +[[dateformat-dow]]`dateFormat:dow`:: +The day that a week should start on. + +[[dateformat-scaled]]`dateFormat:scaled`:: +The values that define the format to use to render ordered time-based data. +Formatted timestamps must adapt to the interval between measurements. Keys are +http://en.wikipedia.org/wiki/ISO_8601#Time_intervals[ISO8601 intervals]. + +[[dateformat-tz]]`dateFormat:tz`:: +The timezone that Kibana uses. The default value of `Browser` uses the timezone +detected by the browser. + +[[datenanosformat]]`dateNanosFormat`:: +The format to use for displaying +https://momentjs.com/docs/#/displaying/format/[pretty formatted dates] of +{ref}/date_nanos.html[Elasticsearch date_nanos type]. + +[[defaultindex]]`defaultIndex`:: +The index to access if no index is set. The default is `null`. + +[[defaultroute]]`defaultRoute`:: +The default route when opening Kibana. Use this setting to route users to a +specific dashboard, application, or saved object as they enter each space. + +[[fields-popularlimit]]`fields:popularLimit`:: +The top N most popular fields to show. + +[[filtereditor-suggestvalues]]`filterEditor:suggestValues`:: +Set this property to `false` to prevent the filter editor from suggesting values +for fields. + +[[filters-pinnedbydefault]]`filters:pinnedByDefault`:: +Set this property to `true` to make filters have a global state (be pinned) by +default. + +[[format-bytes-defaultpattern]]`format:bytes:defaultPattern`:: +The default <> format for the "bytes" format. + +[[format-currency-defaultpattern]]`format:currency:defaultPattern`:: +The default <> format for the "currency" format. + +[[format-defaulttypemap]]`format:defaultTypeMap`:: +A map of the default format name for each field type. Field types that are not +explicitly mentioned use "\_default_". + +[[format-number-defaultlocale]]`format:number:defaultLocale`:: +The <> locale. + +[[format-number-defaultpattern]]`format:number:defaultPattern`:: +The <> for the "number" format. + +[[format-percent-defaultpattern]]`format:percent:defaultPattern`:: +The <> for the "percent" format. + +[[histogram-bartarget]]`histogram:barTarget`:: +When date histograms use the `auto` interval, Kibana attempts to generate this +number of bars. + +[[histogram-maxbars]]`histogram:maxBars`:: +Date histograms are not generated with more bars than the value of this property, +scaling values when necessary. + +[[history-limit]]`history:limit`:: +In fields that have history, such as query inputs, show this many recent values. + +[[indexpattern-placeholder]]`indexPattern:placeholder`:: +The default placeholder value to use in +*Management > Index Patterns > Create Index Pattern*. + +[[metafields]]`metaFields`:: +Fields that exist outside of `_source`. Kibana merges these fields into the +document when displaying it. + +[[metrics-maxbuckets]]`metrics:max_buckets`:: +The maximum numbers of buckets that a single data source can return. This might +arise when the user selects a short interval (for example, 1s) for a long time +period (1 year). + +[[pagenavigation]]`pageNavigation`:: +The style of navigation menu for Kibana. Choices are Legacy, the legacy style +where every plugin is represented in the nav, and Modern, a new format that +bundles related plugins together in flyaway nested navigation. + +[[query-allowleadingwildcards]]`query:allowLeadingWildcards`:: +Allows a wildcard (*) as the first character in a query clause. Only applies +when experimental query features are enabled in the query bar. To disallow +leading wildcards in Lucene queries, use `query:queryString:options`. + +[[query-querystring-options]]`query:queryString:options`:: +Options for the Lucene query string parser. Only used when "Query language" is +set to Lucene. + +[[savedobjects-listinglimit]]`savedObjects:listingLimit`:: +The number of objects to fetch for lists of saved objects. The default value +is 1000. Do not set above 10000. + +[[savedobjects-perpage]]`savedObjects:perPage`:: +The number of objects to show on each page of the list of saved objects. The +default is 5. + +[[search-querylanguage]]`search:queryLanguage`:: +The query language to use in the query bar. Choices are <>, a +language built specifically for {kib}, and the +<>. + +[[shortdots-enable]]`shortDots:enable`:: +Set this property to `true` to shorten long field names in visualizations. For +example, show `f.b.baz` instead of `foo.bar.baz`. + +[[sort-options]]`sort:options`:: Options for the Elasticsearch +{ref}/search-request-body.html#request-body-search-sort[sort] parameter. + +[[state-storeinsessionstorage]]`state:storeInSessionStorage`:: +experimental:[] +Kibana tracks UI state in the URL, which can lead to problems +when there is a lot of state information, and the URL gets very long. Enabling +this setting stores part of the URL in your browser session to keep the URL +short. + +[[theme-darkmode]]`theme:darkMode`:: +Set to `true` to enable a dark mode for the {kib} UI. You must refresh the page +to apply the setting. + +[[timepicker-quickranges]]`timepicker:quickRanges`:: +The list of ranges to show in the Quick section of the time filter. This should +be an array of objects, with each object containing `from`, `to` (see +{ref}/common-options.html#date-math[accepted formats]), and `display` (the title +to be displayed). + +[[timepicker-refreshintervaldefaults]]`timepicker:refreshIntervalDefaults`:: +The default refresh interval for the time filter. Example: +`{ "display": "15 seconds", "pause": true, "value": 15000 }`. + +[[timepicker-timedefaults]]`timepicker:timeDefaults`:: +The default selection in the time filter. + +[[truncate-maxheight]]`truncate:maxHeight`:: +The maximum height that a cell occupies in a table. Set to 0 to disable truncation. -`xPack:defaultAdminEmail`:: Email address for X-Pack admin operations, such as -cluster alert notifications from Monitoring. + +[[xpack-defaultadminemail]]`xPack:defaultAdminEmail`:: +Email address for {xpack} admin operations, such as cluster alert notifications +from *{stack-monitor-app}*. [float] @@ -111,15 +199,17 @@ cluster alert notifications from Monitoring. ==== Accessibility [horizontal] -`accessibility:disableAnimations`:: Turns off all unnecessary animations in the -{kib} UI. Refresh the page to apply the changes. +[[accessibility-disableanimations]]`accessibility:disableAnimations`:: +Turns off all unnecessary animations in the {kib} UI. Refresh the page to apply +the changes. [float] [[kibana-dashboard-settings]] ==== Dashboard [horizontal] -`xpackDashboardMode:roles`:: **Deprecated. Use <> instead.** +[[xpackdashboardmode-roles]]`xpackDashboardMode:roles`:: +**Deprecated. Use <> instead.** The roles that belong to <>. [float] @@ -127,38 +217,63 @@ The roles that belong to <>. ==== Discover [horizontal] -`context:defaultSize`:: The number of surrounding entries to display in the context view. The default value is 5. -`context:step`:: The number by which to increment or decrement the context size. The default value is 5. -`context:tieBreakerFields`:: A comma-separated list of fields to use -for breaking a tie between documents that have the same timestamp value. The first -field that is present and sortable in the current index pattern is used. -`defaultColumns`:: The columns that appear by default on the Discover page. -The default is `_source`. -`discover:aggs:terms:size`:: The number terms that are visualized when clicking -the Visualize button in the field drop down. The default is `20`. -`discover:sampleSize`:: The number of rows to show in the Discover table. -`discover:sort:defaultOrder`:: The default sort direction for time-based index patterns. -`discover:searchOnPageLoad`:: Controls whether a search is executed when Discover first loads. -This setting does not have an effect when loading a saved search. -`doc_table:hideTimeColumn`:: Hides the "Time" column in Discover and in all saved searches on dashboards. -`doc_table:highlight`:: Highlights results in Discover and saved searches on dashboards. -Highlighting slows requests when -working on big documents. +[[context-defaultsize]]`context:defaultSize`:: +The number of surrounding entries to display in the context view. The default +value is 5. + +[[context-step]]`context:step`:: +The number by which to increment or decrement the context size. The default +value is 5. + +[[context-tiebreakerfields]]`context:tieBreakerFields`:: +A comma-separated list of fields to use for breaking a tie between documents +that have the same timestamp value. The first field that is present and sortable +in the current index pattern is used. + +[[defaultcolumns]]`defaultColumns`:: +The columns that appear by default on the *Discover* page. The default is +`_source`. + +[[discover-aggs-terms-size]]`discover:aggs:terms:size`:: +The number terms that are visualized when clicking the *Visualize* button in the +field drop down. The default is `20`. + +[[discover-samplesize]]`discover:sampleSize`:: +The number of rows to show in the *Discover* table. + +[[discover-sort-defaultorder]]`discover:sort:defaultOrder`:: +The default sort direction for time-based index patterns. + +[[discover-searchonpageload]]`discover:searchOnPageLoad`:: +Controls whether a search is executed when *Discover* first loads. This setting +does not have an effect when loading a saved search. + +[[doctable-hidetimecolumn]]`doc_table:hideTimeColumn`:: +Hides the "Time" column in *Discover* and in all saved searches on dashboards. + +[[doctable-highlight]]`doc_table:highlight`:: +Highlights results in *Discover* and saved searches on dashboards. Highlighting +slows requests when working on big documents. [float] [[kibana-ml-settings]] ==== Machine learning [horizontal] -`ml:anomalyDetection:results:enableTimeDefaults`:: Use the default time filter -in the *Single Metric Viewer* and *Anomaly Explorer*. If this setting is -disabled, the results for the full time range are shown. -`ml:anomalyDetection:results:timeDefaults`:: Sets the default time filter for -viewing {anomaly-job} results. This setting must contain `from` and `to` values (see {ref}/common-options.html#date-math[accepted formats]). It is ignored -unless `ml:anomalyDetection:results:enableTimeDefaults` is enabled. -`ml:fileDataVisualizerMaxFileSize`:: Sets the file size limit when importing -data in the {data-viz}. The default value is `100MB`. The highest supported -value for this setting is `1GB`. +[[ml-anomalydetection-results-enabletimedefaults]]`ml:anomalyDetection:results:enableTimeDefaults`:: +Use the default time filter in the *Single Metric Viewer* and +*Anomaly Explorer*. If this setting is disabled, the results for the full time +range are shown. + +[[ml-anomalydetection-results-timedefaults]]`ml:anomalyDetection:results:timeDefaults`:: +Sets the default time filter for viewing {anomaly-job} results. This setting +must contain `from` and `to` values (see +{ref}/common-options.html#date-math[accepted formats]). It is ignored unless +`ml:anomalyDetection:results:enableTimeDefaults` is enabled. + +[[ml-filedatavisualizermaxfilesize]]`ml:fileDataVisualizerMaxFileSize`:: +Sets the file size limit when importing data in the {data-viz}. The default +value is `100MB`. The highest supported value for this setting is `1GB`. [float] @@ -166,18 +281,26 @@ value for this setting is `1GB`. ==== Notifications [horizontal] -`notifications:banner`:: A custom banner intended for temporary notices to all users. -Supports https://help.github.com/en/articles/basic-writing-and-formatting-syntax[Markdown]. -`notifications:lifetime:banner`:: The duration, in milliseconds, for banner -notification displays. The default value is 3000000. Set this field to `Infinity` -to disable banner notifications. -`notifications:lifetime:error`:: The duration, in milliseconds, for error -notification displays. The default value is 300000. Set this field to `Infinity` to disable error notifications. -`notifications:lifetime:info`:: The duration, in milliseconds, for information notification displays. -The default value is 5000. Set this field to `Infinity` to disable information notifications. -`notifications:lifetime:warning`:: The duration, in milliseconds, for warning notification -displays. The default value is 10000. Set this field to `Infinity` to disable warning notifications. +[[notifications-banner]]`notifications:banner`:: +A custom banner intended for temporary notices to all users. Supports +https://help.github.com/en/articles/basic-writing-and-formatting-syntax[Markdown]. + +[[notifications-lifetime-banner]]`notifications:lifetime:banner`:: +The duration, in milliseconds, for banner notification displays. The default +value is 3000000. Set this field to `Infinity` to disable banner notifications. + +[[notificatios-lifetime-error]]`notifications:lifetime:error`:: +The duration, in milliseconds, for error notification displays. The default +value is 300000. Set this field to `Infinity` to disable error notifications. +[[notifications-lifetime-info]]`notifications:lifetime:info`:: +The duration, in milliseconds, for information notification displays. The +default value is 5000. Set this field to `Infinity` to disable information +notifications. + +[[notifications-lifetime-warning]]`notifications:lifetime:warning`:: +The duration, in milliseconds, for warning notification displays. The default +value is 10000. Set this field to `Infinity` to disable warning notifications. [float] @@ -185,7 +308,8 @@ displays. The default value is 10000. Set this field to `Infinity` to disable wa ==== Reporting [horizontal] -`xpackReporting:customPdfLogo`:: A custom image to use in the footer of the PDF. +[[xpackreporting-custompdflogo]]`xpackReporting:customPdfLogo`:: +A custom image to use in the footer of the PDF. [float] @@ -193,9 +317,10 @@ displays. The default value is 10000. Set this field to `Infinity` to disable wa ==== Rollup [horizontal] -`rollups:enableIndexPatterns`:: Enables the creation of index patterns that -capture rollup indices, which in turn enables visualizations based on rollup data. -Refresh the page to apply the changes. +[[rollups-enableindexpatterns]]`rollups:enableIndexPatterns`:: +Enables the creation of index patterns that capture rollup indices, which in +turn enables visualizations based on rollup data. Refresh the page to apply the +changes. [float] @@ -203,67 +328,117 @@ Refresh the page to apply the changes. ==== Search [horizontal] -`courier:batchSearches`:: **Deprecated in 7.6. Starting in 8.0, this setting will be optimized internally.** -When disabled, dashboard panels will load individually, and search requests will terminate when -users navigate away or update the query. When enabled, dashboard panels will load together when all of the data is loaded, -and searches will not terminate. -`courier:customRequestPreference`:: {ref}/search-request-body.html#request-body-search-preference[Request preference] +[[courier-batchsearches]]`courier:batchSearches`:: +**Deprecated in 7.6. Starting in 8.0, this setting will be optimized internally.** +When disabled, dashboard panels will load individually, and search requests will +terminate when users navigate away or update the query. When enabled, dashboard +panels will load together when all of the data is loaded, and searches will not +terminate. + +[[courier-customrequestpreference]]`courier:customRequestPreference`:: +{ref}/search-request-body.html#request-body-search-preference[Request preference] to use when `courier:setRequestPreference` is set to "custom". -`courier:ignoreFilterIfFieldNotInIndex`:: Skips filters that apply to fields that don't exist in the index for a visualization. -Useful when dashboards consist of visualizations from multiple index patterns. -`courier:maxConcurrentShardRequests`:: Controls the {ref}/search-multi-search.html[max_concurrent_shard_requests] + +[[courier-ignorefilteriffieldnotinindex]]`courier:ignoreFilterIfFieldNotInIndex`:: +Skips filters that apply to fields that don't exist in the index for a +visualization. Useful when dashboards consist of visualizations from multiple +index patterns. + +[[courier-maxconcurrentshardrequests]]`courier:maxConcurrentShardRequests`:: +Controls the {ref}/search-multi-search.html[max_concurrent_shard_requests] setting used for `_msearch` requests sent by {kib}. Set to 0 to disable this config and use the {es} default. -`courier:setRequestPreference`:: Enables you to set which shards handle your search requests. -* *Session ID:* Restricts operations to execute all search requests on the same shards. -This has the benefit of reusing shard caches across requests. -* *Custom:* Allows you to define your own preference. Use `courier:customRequestPreference` -to customize your preference value. + +[[courier-setrequestpreference]]`courier:setRequestPreference`:: +Enables you to set which shards handle your search requests. +* *Session ID:* Restricts operations to execute all search requests on the same +shards. This has the benefit of reusing shard caches across requests. +* *Custom:* Allows you to define your own preference. Use +`courier:customRequestPreference` to customize your preference value. * *None:* Do not set a preference. This might provide better performance because requests can be spread across all shard copies. However, results might be inconsistent because different shards might be in different refresh states. -`search:includeFrozen`:: Includes {ref}/frozen-indices.html[frozen indices] in results. -Searching through frozen indices -might increase the search time. This setting is off by default. Users must opt-in to include frozen indices. -`search:timeout`:: Change the maximum timeout for a search session or set to 0 to disable the timeout and allow queries to run to completion. + +[[search-includefrozen]]`search:includeFrozen`:: +Includes {ref}/frozen-indices.html[frozen indices] in results. Searching through +frozen indices might increase the search time. This setting is off by default. +Users must opt-in to include frozen indices. + +[[search-timeout]]`search:timeout`:: Change the maximum timeout for a search +session or set to 0 to disable the timeout and allow queries to run to +completion. [float] [[kibana-siem-settings]] -==== Security Solution +==== Security solution [horizontal] -`securitySolution:defaultAnomalyScore`:: The threshold above which Machine Learning job anomalies are displayed in the Security app. -`securitySolution:defaultIndex`:: A comma-delimited list of Elasticsearch indices from which the Security app collects events. -`securitySolution:ipReputationLinks`:: A JSON array containing links for verifying the reputation of an IP address. The links are displayed on -{security-guide}/network-page-overview.html[IP detail] pages. -`securitySolution:enableNewsFeed`:: Enables the security news feed on the Security *Overview* -page. -`securitySolution:newsFeedUrl`:: The URL from which the security news feed content is -retrieved. -`securitySolution:refreshIntervalDefaults`:: The default refresh interval for the Security time filter, in milliseconds. -`securitySolution:timeDefaults`:: The default period of time in the Security time filter. +[[securitysolution-defaultanomalyscore]]`securitySolution:defaultAnomalyScore`:: +The threshold above which {ml} job anomalies are displayed in the {security-app}. + +[[securitysolution-defaultindex]]`securitySolution:defaultIndex`:: +A comma-delimited list of {es} indices from which the {security-app} collects +events. + +[[securitysolution-ipreputationlinks]]`securitySolution:ipReputationLinks`:: +A JSON array containing links for verifying the reputation of an IP address. The +links are displayed on {security-guide}/network-page-overview.html[IP detail] +pages. + +[[securitysolution-enablenewsfeed]]`securitySolution:enableNewsFeed`:: Enables +the security news feed on the Security *Overview* page. + +[[securitysolution-newsfeedurl]]`securitySolution:newsFeedUrl`:: +The URL from which the security news feed content is retrieved. + +[[securitysolution-refreshintervaldefaults]]`securitySolution:refreshIntervalDefaults`:: +The default refresh interval for the Security time filter, in milliseconds. + +[[securitysolution-timedefaults]]`securitySolution:timeDefaults`:: +The default period of time in the Security time filter. [float] [[kibana-timelion-settings]] ==== Timelion [horizontal] -`timelion:default_columns`:: The default number of columns to use on a Timelion sheet. -`timelion:default_rows`:: The default number of rows to use on a Timelion sheet. -`timelion:es.default_index`:: The default index when using the `.es()` query. -`timelion:es.timefield`:: The default field containing a timestamp when using the `.es()` query. -`timelion:graphite.url`:: [experimental] Used with graphite queries, this is the URL of your graphite host -in the form https://www.hostedgraphite.com/UID/ACCESS_KEY/graphite. This URL can be -selected from an allow-list configured in the `kibana.yml` under `timelion.graphiteUrls`. -`timelion:max_buckets`:: The maximum number of buckets a single data source can return. -This value is used for calculating automatic intervals in visualizations. -`timelion:min_interval`:: The smallest interval to calculate when using "auto". -`timelion:quandl.key`:: [experimental] Used with quandl queries, this is your API key from https://www.quandl.com/[www.quandl.com]. -`timelion:showTutorial`:: Shows the Timelion tutorial -to users when they first open the Timelion app. -`timelion:target_buckets`:: Used for calculating automatic intervals in visualizations, -this is the number of buckets to try to represent. +[[timelion-defaultcolumns]]`timelion:default_columns`:: +The default number of columns to use on a Timelion sheet. + +[[timelion-defaultrows]]`timelion:default_rows`:: +The default number of rows to use on a Timelion sheet. + +[[timelion-esdefaultindex]]`timelion:es.default_index`:: +The default index when using the `.es()` query. + +[[timelion-estimefield]]`timelion:es.timefield`:: +The default field containing a timestamp when using the `.es()` query. + +[[timelion-graphite-url]]`timelion:graphite.url`:: +experimental:[] +Used with graphite queries, this is the URL of your graphite host +in the form https://www.hostedgraphite.com/UID/ACCESS_KEY/graphite. This URL can +be selected from an allow-list configured in the `kibana.yml` under +`timelion.graphiteUrls`. +[[timelion-maxbuckets]]`timelion:max_buckets`:: +The maximum number of buckets a single data source can return. This value is +used for calculating automatic intervals in visualizations. + +[[timelion-mininterval]]`timelion:min_interval`:: +The smallest interval to calculate when using "auto". + +[[timelion-quandlkey]]`timelion:quandl.key`:: +experimental:[] +Used with quandl queries, this is your API key from +https://www.quandl.com/[www.quandl.com]. + +[[timelion-showtutorial]]`timelion:showTutorial`:: +Shows the Timelion tutorial to users when they first open the Timelion app. + +[[timelion-targetbuckets]]`timelion:target_buckets`:: +Used for calculating automatic intervals in visualizations, this is the number +of buckets to try to represent. [float] @@ -271,20 +446,29 @@ this is the number of buckets to try to represent. ==== Visualization [horizontal] -`visualization:colorMapping`:: Maps values to specified colors in visualizations. -`visualization:dimmingOpacity`:: The opacity of the chart items that are dimmed -when highlighting another element of the chart. The lower this number, the more -the highlighted element stands out. This must be a number between 0 and 1. -`visualization:loadingDelay`:: The time to wait before dimming visualizations -during a query. -`visualization:regionmap:showWarnings`:: Shows -a warning in a region map when terms cannot be joined to a shape. -`visualization:tileMap:WMSdefaults`:: The default properties for the WMS map server support in the coordinate map. -`visualization:tileMap:maxPrecision`:: The maximum geoHash precision displayed on tile maps: 7 is high, 10 is very high, +[[visualization-colormapping]]`visualization:colorMapping`:: +Maps values to specified colors in visualizations. + +[[visualization-dimmingopacity]]`visualization:dimmingOpacity`:: +The opacity of the chart items that are dimmed when highlighting another element +of the chart. The lower this number, the more the highlighted element stands out. +This must be a number between 0 and 1. + +[[visualization-regionmap-showwarnings]]`visualization:regionmap:showWarnings`:: +Shows a warning in a region map when terms cannot be joined to a shape. + +[[visualization-tilemap-wmsdefaults]]`visualization:tileMap:WMSdefaults`:: +The default properties for the WMS map server support in the coordinate map. + +[[visualization-tilemap-maxprecision]]`visualization:tileMap:maxPrecision`:: +The maximum geoHash precision displayed on tile maps: 7 is high, 10 is very high, and 12 is the maximum. See this {ref}/search-aggregations-bucket-geohashgrid-aggregation.html#_cell_dimensions_at_the_equator[explanation of cell dimensions]. -`visualize:enableLabs`:: Enables users to create, view, and edit experimental visualizations. -If disabled, only visualizations that are considered production-ready are available to the user. + +[[visualize-enablelabs]]`visualize:enableLabs`:: +Enables users to create, view, and edit experimental visualizations. If disabled, +only visualizations that are considered production-ready are available to the +user. [float] diff --git a/docs/management/images/add_remote_cluster.png b/docs/management/images/add_remote_cluster.png deleted file mode 100755 index 160d29b741c62..0000000000000 Binary files a/docs/management/images/add_remote_cluster.png and /dev/null differ diff --git a/docs/management/images/auto_follow_pattern.png b/docs/management/images/auto_follow_pattern.png deleted file mode 100755 index f80de9352280f..0000000000000 Binary files a/docs/management/images/auto_follow_pattern.png and /dev/null differ diff --git a/docs/management/images/cross-cluster-replication-list-view.png b/docs/management/images/cross-cluster-replication-list-view.png deleted file mode 100755 index 4c45174cff7f1..0000000000000 Binary files a/docs/management/images/cross-cluster-replication-list-view.png and /dev/null differ diff --git a/docs/management/images/remote-clusters-list-view.png b/docs/management/images/remote-clusters-list-view.png deleted file mode 100755 index c28379863b74b..0000000000000 Binary files a/docs/management/images/remote-clusters-list-view.png and /dev/null differ diff --git a/docs/management/managing-ccr.asciidoc b/docs/management/managing-ccr.asciidoc deleted file mode 100644 index 9c06e479e28b2..0000000000000 --- a/docs/management/managing-ccr.asciidoc +++ /dev/null @@ -1,80 +0,0 @@ -[role="xpack"] -[[managing-cross-cluster-replication]] -== Cross-Cluster Replication - -Use *Cross-Cluster Replication* to reproduce indices in -remote clusters on a local cluster. {ref}/xpack-ccr.html[Cross-cluster replication] -is commonly used to provide remote backups for disaster recovery and for -geo-proximite copies of data. - -To get started, open the menu, then go to *Stack Management > Data > Cross-Cluster Replication*. - -[role="screenshot"] -image::images/cross-cluster-replication-list-view.png[][Cross-cluster replication list view] - -[float] -=== Prerequisites - -* You must have a {ref}/modules-remote-clusters.html[remote cluster]. -* Leader indices must meet {ref}/ccr-requirements.html[these requirements]. -* The Elasticsearch version of the local cluster must be the same as or newer than the remote cluster. -Refer to {ref}/ccr-overview.html[this document] for more information. - -[float] -=== Required permissions - -The `manage` and `manage_ccr` cluster privileges are required to access *Cross-Cluster Replication*. - -You can add these privileges in *Stack Management > Security > Roles*. - -[float] -[[configure-replication]] -=== Configure replication - -Replication requires a leader index, the index being replicated, and a -follower index, which will contain the leader index's replicated data. -The follower index is passive in that it can read requests and searches, -but cannot accept direct writes. Only the leader index is active for direct writes. - -You can configure follower indices in two ways: - -* Create specific follower indices -* Create follower indices from an auto-follow pattern - -[float] -==== Create specific follower indices - -To replicate data from existing indices, or set up local followers on a case-by-case basis, -go to *Follower indices*. When you create the follower index, you must reference the -remote cluster and the leader index that you created in the remote cluster. - -[role="screenshot"] -image::images/follower_indices.png[][UI for adding follower indices] - -[float] -==== Create follower indices from an auto-follow pattern - -To automatically detect and follow new indices when they are created on a remote cluster, -go to *Auto-follow patterns*. Creating an auto-follow pattern is useful when you have -time series data, like event logs, on the remote cluster that is created or rolled over on a daily basis. - -When creating the pattern, you must reference the remote cluster that you -connected to your local cluster. You must also specify a collection of index patterns -that match the indices you want to automatically follow. - -Once you configure an -auto-follow pattern, any time a new index with a name that matches the pattern is -created in the remote cluster, a follower index is automatically configured in the local cluster. - -[role="screenshot"] -image::images/auto_follow_pattern.png[UI for adding an auto-follow pattern] - -[float] -[[manage-replication]] -=== Manage replication - -Use the list views in *Cross-Cluster Replication* to monitor whether the replication is active and -pause and resume replication. You can also edit and remove the follower indices and auto-follow patterns. - -For an example of cross-cluster replication, -refer to https://www.elastic.co/blog/bi-directional-replication-with-elasticsearch-cross-cluster-replication-ccr[Bi-directional replication with Elasticsearch cross-cluster replication]. diff --git a/docs/management/managing-remote-clusters.asciidoc b/docs/management/managing-remote-clusters.asciidoc deleted file mode 100644 index 92e0fa822b056..0000000000000 --- a/docs/management/managing-remote-clusters.asciidoc +++ /dev/null @@ -1,50 +0,0 @@ -[[working-remote-clusters]] -== Remote Clusters - -Use *Remote Clusters* to establish a unidirectional -connection from your cluster to other clusters. This functionality is -required for {ref}/xpack-ccr.html[cross-cluster replication] and -{ref}/modules-cross-cluster-search.html[cross-cluster search]. - -To get started, open the menu, then go to *Stack Management > Data > Remote Clusters*. - -[role="screenshot"] -image::images/remote-clusters-list-view.png[Remote Clusters list view, including Add a remote cluster button] - -[float] -=== Required permissions - -The `manage` cluster privilege is required to access *Remote Clusters*. - -You can add this privilege in *Stack Management > Security > Roles*. - -[float] -[[managing-remote-clusters]] -=== Add a remote cluster - -A {ref}/modules-remote-clusters.html[remote cluster] connection works by configuring a remote cluster and -connecting to a limited number of nodes, called {ref}/modules-remote-clusters.html#sniff-mode[seed nodes], -in that cluster. -Alternatively, you can define a single proxy address for the remote cluster. - -By default, a cross-cluster request, such as a cross-cluster search or -replication request, fails if any cluster in the request is unavailable. -To skip a cluster when its unavailable, -set *Skip if unavailable* to true. - -Once you add a remote cluster, you can configure <> -to reproduce indices in the remote cluster on a local cluster. - -[role="screenshot"] -image::images/add_remote_cluster.png[][UI for adding a remote cluster] - -To create an index pattern to search across clusters, -use the same syntax that you’d use in a raw cross-cluster search request in {es}: :. -See <> for examples. - -[float] -[[manage-remote-clusters]] -=== Manage remote clusters - -From the *Remote Clusters* list view, you can drill down into each cluster and -view its status. You can also edit and delete a cluster. diff --git a/docs/management/rollups/create_and_manage_rollups.asciidoc b/docs/management/rollups/create_and_manage_rollups.asciidoc index e20f384b5ed18..7324f45594bd7 100644 --- a/docs/management/rollups/create_and_manage_rollups.asciidoc +++ b/docs/management/rollups/create_and_manage_rollups.asciidoc @@ -67,7 +67,7 @@ You can read more at {ref}/rollup-job-config.html[rollup job configuration]. === Try it: Create and visualize rolled up data This example creates a rollup job to capture log data from sample web logs. -To follow along, add the <>. +To follow along, add the sample web logs data set. In this example, you want data that is older than 7 days in the target index pattern `kibana_sample_data_logs` to roll up once a day into the index `rollup_logstash`. You’ll bucket the diff --git a/docs/redirects.asciidoc b/docs/redirects.asciidoc index 42d1d89145d79..92e02de89f181 100644 --- a/docs/redirects.asciidoc +++ b/docs/redirects.asciidoc @@ -59,7 +59,7 @@ This page has moved. Please see <>. [role="exclude",id="add-sample-data"] == Add sample data -This page has moved. Please see <>. +This page has moved. Please see <>. [role="exclude",id="tilemap"] == Coordinate map @@ -100,3 +100,21 @@ This content has moved to the <> page. == TSVB This page was deleted. See <>. + +[role="exclude",id="managing-cross-cluster-replication"] +== Cross-Cluster Replication + +This content has moved. See +{ref}/ccr-getting-started.html[Set up cross-cluster replication]. + +[role="exclude",id="working-remote-clusters"] +== Remote clusters + +This content has moved. See +{ref}/ccr-getting-started.html#ccr-getting-started-remote-cluster[Connect to a remote cluster]. + +[role="exclude",id="tutorial-define-index"] +== Define your index patterns + +This content has moved. See +<>. diff --git a/docs/settings/fleet-settings.asciidoc b/docs/settings/fleet-settings.asciidoc new file mode 100644 index 0000000000000..9c28d28003175 --- /dev/null +++ b/docs/settings/fleet-settings.asciidoc @@ -0,0 +1,51 @@ +[role="xpack"] +[[fleet-settings-kb]] +=== {fleet} settings in {kib} +++++ +{fleet} settings +++++ + +experimental[] + +You can configure `xpack.fleet` settings in your `kibana.yml`. +By default, {fleet} is enabled. To use {fleet}, you also need to configure {kib} and {es} hosts. + +See the {ingest-guide}/index.html[Ingest Management] docs for more information. + +[[general-fleet-settings-kb]] +==== General {fleet} settings + +[cols="2*<"] +|=== +| `xpack.fleet.enabled` {ess-icon} + | Set to `true` (default) to enable {fleet}. +| `xpack.fleet.agents.enabled` {ess-icon} + | Set to `true` (default) to enable {fleet}. +|=== + +[[fleet-data-visualizer-settings]] + +==== {package-manager} settings + +[cols="2*<"] +|=== +| `xpack.fleet.registryUrl` + | The address to use to reach {package-manager} registry. +|=== + +==== {fleet} settings + +[cols="2*<"] +|=== +| `xpack.fleet.agents.kibana.host` + | The hostname used by {agent} for accessing {kib}. +| `xpack.fleet.agents.elasticsearch.host` + | The hostname used by {agent} for accessing {es}. +| `xpack.fleet.agents.tlsCheckDisabled` + | Set to `true` to allow {fleet} to run on a {kib} instance without TLS enabled. +|=== + +[NOTE] +==== +In {ecloud}, {fleet} flags are already configured. +==== diff --git a/docs/settings/ingest-manager-settings.asciidoc b/docs/settings/ingest-manager-settings.asciidoc deleted file mode 100644 index 30e11f726c26b..0000000000000 --- a/docs/settings/ingest-manager-settings.asciidoc +++ /dev/null @@ -1,51 +0,0 @@ -[role="xpack"] -[[ingest-manager-settings-kb]] -=== {ingest-manager} settings in {kib} -++++ -{ingest-manager} settings -++++ - -experimental[] - -You can configure `xpack.ingestManager` settings in your `kibana.yml`. -By default, {ingest-manager} is enabled. To use {fleet}, you also need to configure {kib} and {es} hosts. - -See the {ingest-guide}/index.html[Ingest Management] docs for more information. - -[[general-ingest-manager-settings-kb]] -==== General {ingest-manager} settings - -[cols="2*<"] -|=== -| `xpack.ingestManager.enabled` {ess-icon} - | Set to `true` (default) to enable {ingest-manager}. -| `xpack.ingestManager.fleet.enabled` {ess-icon} - | Set to `true` (default) to enable {fleet}. -|=== - -[[ingest-manager-data-visualizer-settings]] - -==== {package-manager} settings - -[cols="2*<"] -|=== -| `xpack.ingestManager.registryUrl` - | The address to use to reach {package-manager} registry. -|=== - -==== {fleet} settings - -[cols="2*<"] -|=== -| `xpack.ingestManager.fleet.kibana.host` - | The hostname used by {agent} for accessing {kib}. -| `xpack.ingestManager.fleet.elasticsearch.host` - | The hostname used by {agent} for accessing {es}. -| `xpack.ingestManager.fleet.tlsCheckDisabled` - | Set to `true` to allow {fleet} to run on a {kib} instance without TLS enabled. -|=== - -[NOTE] -==== -In {ecloud}, {fleet} flags are already configured. -==== diff --git a/docs/settings/monitoring-settings.asciidoc b/docs/settings/monitoring-settings.asciidoc index 6c8632efa9cc0..917821ad09e2f 100644 --- a/docs/settings/monitoring-settings.asciidoc +++ b/docs/settings/monitoring-settings.asciidoc @@ -33,7 +33,7 @@ For more information, see |=== | `monitoring.enabled` | Set to `true` (default) to enable the {monitor-features} in {kib}. Unlike the - `monitoring.ui.enabled` setting, when this setting is `false`, the + <> setting, when this setting is `false`, the monitoring back-end does not run and {kib} stats are not sent to the monitoring cluster. @@ -44,7 +44,7 @@ a|`monitoring.cluster_alerts.` | `monitoring.ui.elasticsearch.hosts` | Specifies the location of the {es} cluster where your monitoring data is stored. - By default, this is the same as `elasticsearch.hosts`. This setting enables + By default, this is the same as <>. This setting enables you to use a single {kib} instance to search and visualize data in your production cluster as well as monitor data sent to a dedicated monitoring cluster. @@ -58,7 +58,7 @@ a|`monitoring.cluster_alerts.` cluster uses the authenticated user's credentials, which must be the same on both the {es} monitoring cluster and the {es} production cluster. + + - If not set, {kib} uses the value of the `elasticsearch.username` setting. + If not set, {kib} uses the value of the <> setting. | `monitoring.ui.elasticsearch.password` | Specifies the password used by {kib} monitoring to establish a persistent connection @@ -69,11 +69,11 @@ a|`monitoring.cluster_alerts.` cluster uses the authenticated user's credentials, which must be the same on both the {es} monitoring cluster and the {es} production cluster. + + - If not set, {kib} uses the value of the `elasticsearch.password` setting. + If not set, {kib} uses the value of the <> setting. | `monitoring.ui.elasticsearch.pingTimeout` | Specifies the time in milliseconds to wait for {es} to respond to internal - health checks. By default, it matches the `elasticsearch.pingTimeout` setting, + health checks. By default, it matches the <> setting, which has a default value of `30000`. |=== @@ -112,7 +112,7 @@ about configuring {kib}, see | Specifies the number of log entries to display in *{stack-monitor-app}*. Defaults to `10`. The maximum value is `50`. -| `monitoring.ui.enabled` +|[[monitoring-ui-enabled]] `monitoring.ui.enabled` | Set to `false` to hide *{stack-monitor-app}*. The monitoring back-end continues to run as an agent for sending {kib} stats to the monitoring cluster. Defaults to `true`. diff --git a/docs/settings/reporting-settings.asciidoc b/docs/settings/reporting-settings.asciidoc index 3489dcd018293..adfc3964d4204 100644 --- a/docs/settings/reporting-settings.asciidoc +++ b/docs/settings/reporting-settings.asciidoc @@ -20,7 +20,7 @@ You can configure `xpack.reporting` settings in your `kibana.yml` to: | [[xpack-enable-reporting]]`xpack.reporting.enabled` {ess-icon} | Set to `false` to disable the {report-features}. -| `xpack.reporting.encryptionKey` {ess-icon} +|[[xpack-reporting-encryptionKey]] `xpack.reporting.encryptionKey` {ess-icon} | Set to an alphanumeric, at least 32 characters long text string. By default, {kib} will generate a random key when it starts, which will cause pending reports to fail after restart. Configure this setting to preserve the same key across multiple restarts and multiple instances of {kib}. @@ -53,20 +53,20 @@ proxy host requires that the {kib} server has network access to the proxy. [cols="2*<"] |=== | `xpack.reporting.kibanaServer.port` - | The port for accessing {kib}, if different from the `server.port` value. + | The port for accessing {kib}, if different from the <> value. | `xpack.reporting.kibanaServer.protocol` | The protocol for accessing {kib}, typically `http` or `https`. -| `xpack.reporting.kibanaServer.hostname` - | The hostname for accessing {kib}, if different from the `server.host` value. +|[[xpack-kibanaServer-hostname]] `xpack.reporting.kibanaServer.hostname` + | The hostname for accessing {kib}, if different from the <> value. |=== [NOTE] ============ Reporting authenticates requests on the Kibana page only when the hostname matches the -`xpack.reporting.kibanaServer.hostname` setting. Therefore Reporting would fail if the +<> setting. Therefore Reporting would fail if the set value redirects to another server. For that reason, `"0"` is an invalid setting because, in the Reporting browser, it becomes an automatic redirect to `"0.0.0.0"`. ============ @@ -97,8 +97,8 @@ reports, you might need to change the following settings. [NOTE] ============ Running multiple instances of {kib} in a cluster for load balancing of -reporting requires identical values for `xpack.reporting.encryptionKey` and, if -security is enabled, `xpack.security.encryptionKey`. +reporting requires identical values for <> and, if +security is enabled, <>. ============ [cols="2*<"] @@ -177,7 +177,7 @@ available, but there will likely be errors in the visualizations in the report. [[reporting-chromium-settings]] ==== Chromium settings -When `xpack.reporting.capture.browser.type` is set to `chromium` (default) you can also specify the following settings. +When <> is set to `chromium` (default) you can also specify the following settings. [cols="2*<"] |=== @@ -229,10 +229,10 @@ a| `xpack.reporting.capture.browser` See OWASP: https://www.owasp.org/index.php/CSV_Injection Defaults to `true`. -| `xpack.reporting.csv.enablePanelActionDownload` - | Enables CSV export from a saved search on a dashboard. This action is available in the dashboard - panel menu for the saved search. - Defaults to `true`. +| `xpack.reporting.csv` `.enablePanelActionDownload` + | Enables CSV export from a saved search on a dashboard. This action is available in the dashboard panel menu for the saved search. + *Note:* This setting exists for backwards compatibility, but is unused and hardcoded to `true`. CSV export from a saved search on a dashboard + is enabled when Reporting is enabled. |=== @@ -246,7 +246,7 @@ a| `xpack.reporting.capture.browser` | Reporting uses a weekly index in {es} to store the reporting job and the report content. The index is automatically created if it does not already exist. Configure this to a unique value, beginning with `.reporting-`, for every - {kib} instance that has a unique `kibana.index` setting. Defaults to `.reporting`. + {kib} instance that has a unique <> setting. Defaults to `.reporting`. | `xpack.reporting.roles.allow` | Specifies the roles in addition to superusers that can use reporting. diff --git a/docs/settings/security-settings.asciidoc b/docs/settings/security-settings.asciidoc index b6eecc6ea9f04..00e5f973f7d87 100644 --- a/docs/settings/security-settings.asciidoc +++ b/docs/settings/security-settings.asciidoc @@ -190,26 +190,26 @@ You can configure the following settings in the `kibana.yml` file. | `xpack.security.cookieName` | Sets the name of the cookie used for the session. The default value is `"sid"`. -| `xpack.security.encryptionKey` +|[[xpack-security-encryptionKey]] `xpack.security.encryptionKey` | An arbitrary string of 32 characters or more that is used to encrypt session information. Do **not** expose this key to users of {kib}. By default, a value is automatically generated in memory. If you use that default behavior, all sessions are invalidated when {kib} restarts. In addition, high-availability deployments of {kib} will behave unexpectedly if this setting isn't the same for all instances of {kib}. -| `xpack.security.secureCookies` +|[[xpack-security-secureCookies]] `xpack.security.secureCookies` | Sets the `secure` flag of the session cookie. The default value is `false`. It - is automatically set to `true` if `server.ssl.enabled` is set to `true`. Set + is automatically set to `true` if <> is set to `true`. Set this to `true` if SSL is configured outside of {kib} (for example, you are routing requests through a load balancer or proxy). | `xpack.security.sameSiteCookies` {ess-icon} | Sets the `SameSite` attribute of the session cookie. This allows you to declare whether your cookie should be restricted to a first-party or same-site context. Valid values are `Strict`, `Lax`, `None`. - This is *not set* by default, which modern browsers will treat as `Lax`. If you use Kibana embedded in an iframe in modern browsers, you might need to set it to `None`. Setting this value to `None` requires cookies to be sent over a secure connection by setting `xpack.security.secureCookies: true`. + This is *not set* by default, which modern browsers will treat as `Lax`. If you use Kibana embedded in an iframe in modern browsers, you might need to set it to `None`. Setting this value to `None` requires cookies to be sent over a secure connection by setting <>: `true`. -| `xpack.security.session.idleTimeout` {ess-icon} - | Ensures that user sessions will expire after a period of inactivity. This and `xpack.security.session.lifespan` are both +|[[xpack-session-idleTimeout]] `xpack.security.session.idleTimeout` {ess-icon} + | Ensures that user sessions will expire after a period of inactivity. This and <> are both highly recommended. By default, this setting is not set. 2+a| @@ -218,9 +218,9 @@ highly recommended. By default, this setting is not set. The format is a string of `[ms\|s\|m\|h\|d\|w\|M\|Y]` (e.g. '20m', '24h', '7d', '1w'). ============ -| `xpack.security.session.lifespan` {ess-icon} +|[[xpack-session-lifespan]] `xpack.security.session.lifespan` {ess-icon} | Ensures that user sessions will expire after the defined time period. This behavior also known as an "absolute timeout". If -this is _not_ set, user sessions could stay active indefinitely. This and `xpack.security.session.idleTimeout` are both highly +this is _not_ set, user sessions could stay active indefinitely. This and <> are both highly recommended. By default, this setting is not set. 2+a| diff --git a/docs/settings/settings-xkb.asciidoc b/docs/settings/settings-xkb.asciidoc index 04fed0d6204b7..9d9cc92401896 100644 --- a/docs/settings/settings-xkb.asciidoc +++ b/docs/settings/settings-xkb.asciidoc @@ -20,4 +20,4 @@ include::ml-settings.asciidoc[] include::reporting-settings.asciidoc[] include::spaces-settings.asciidoc[] include::i18n-settings.asciidoc[] -include::ingest-manager-settings.asciidoc[] +include::fleet-settings.asciidoc[] diff --git a/docs/settings/telemetry-settings.asciidoc b/docs/settings/telemetry-settings.asciidoc index 89c018a86eca6..0329e2f010e80 100644 --- a/docs/settings/telemetry-settings.asciidoc +++ b/docs/settings/telemetry-settings.asciidoc @@ -19,7 +19,7 @@ See our https://www.elastic.co/legal/privacy-statement[Privacy Statement] to lea [cols="2*<"] |=== -| `telemetry.enabled` +|[[telemetry-enabled]] `telemetry.enabled` | Set to `true` to send cluster statistics to Elastic. Reporting your cluster statistics helps us improve your user experience. Your data is never shared with anyone. Set to `false` to disable statistics reporting from any @@ -31,16 +31,16 @@ See our https://www.elastic.co/legal/privacy-statement[Privacy Statement] to lea it is behind a firewall and falls back to `'browser'` to send it from users' browsers when they are navigating through {kib}. Defaults to `'server'`. -| `telemetry.optIn` +|[[telemetry-optIn]] `telemetry.optIn` | Set to `true` to automatically opt into reporting cluster statistics. You can also opt out through *Advanced Settings* in {kib}. Defaults to `true`. | `telemetry.allowChangingOptInStatus` - | Set to `true` to allow overwriting the `telemetry.optIn` setting via the {kib} UI. Defaults to `true`. + + | Set to `true` to allow overwriting the <> setting via the {kib} UI. Defaults to `true`. + |=== [NOTE] ============ -When `false`, `telemetry.optIn` must be `true`. To disable telemetry and not allow users to change that parameter, use `telemetry.enabled`. +When `false`, <> must be `true`. To disable telemetry and not allow users to change that parameter, use <>. ============ diff --git a/docs/setup/connect-to-elasticsearch.asciidoc b/docs/setup/connect-to-elasticsearch.asciidoc index ea02afb8a9fda..0daa3f1e0e55e 100644 --- a/docs/setup/connect-to-elasticsearch.asciidoc +++ b/docs/setup/connect-to-elasticsearch.asciidoc @@ -11,7 +11,7 @@ To start working with your data in {kib}, you can: * Connect {kib} with existing {es} indices. -If you're not ready to use your own data, you can add a <> +If you're not ready to use your own data, you can add a <> to see all that you can do in {kib}. [float] diff --git a/docs/setup/production.asciidoc b/docs/setup/production.asciidoc index 3075220e3a47c..e097704e05d40 100644 --- a/docs/setup/production.asciidoc +++ b/docs/setup/production.asciidoc @@ -135,6 +135,7 @@ Settings that must be the same: xpack.security.encryptionKey //decrypting session information xpack.reporting.encryptionKey //decrypting reports xpack.encryptedSavedObjects.encryptionKey // decrypting saved objects +xpack.encryptedSavedObjects.keyRotation.decryptionOnlyKeys // saved objects encryption key rotation, if any -------- Separate configuration files can be used from the command line by using the `-c` flag: diff --git a/docs/setup/secure-settings.asciidoc b/docs/setup/secure-settings.asciidoc index 10380eb5d8fa4..840a18ac03bab 100644 --- a/docs/setup/secure-settings.asciidoc +++ b/docs/setup/secure-settings.asciidoc @@ -19,7 +19,7 @@ bin/kibana-keystore create ---------------------------------------------------------------- The file `kibana.keystore` will be created in the directory defined by the -`path.data` configuration setting. +<> configuration setting. [float] [[list-settings]] diff --git a/docs/setup/settings.asciidoc b/docs/setup/settings.asciidoc index f03022e9e9f00..2f2c87ca9c7d4 100644 --- a/docs/setup/settings.asciidoc +++ b/docs/setup/settings.asciidoc @@ -20,11 +20,11 @@ which may cause a delay before pages start being served. Set to `false` to disable Console. *Default: `true`* | `cpu.cgroup.path.override:` - | *deprecated* This setting has been renamed to `ops.cGroupOverrides.cpuPath` + | *deprecated* This setting has been renamed to <> and the old name will no longer be supported as of 8.0. | `cpuacct.cgroup.path.override:` - | *deprecated* This setting has been renamed to `ops.cGroupOverrides.cpuAcctPath` + | *deprecated* This setting has been renamed to <> and the old name will no longer be supported as of 8.0. | `csp.rules:` @@ -33,7 +33,7 @@ that disables certain unnecessary and potentially insecure capabilities in the browser. It is strongly recommended that you keep the default CSP rules that ship with {kib}. -| `csp.strict:` +|[[csp-strict]] `csp.strict:` | Blocks {kib} access to any browser that does not enforce even rudimentary CSP rules. In practice, this disables support for older, less safe browsers like Internet Explorer. @@ -43,44 +43,39 @@ For more information, refer to <>. | `csp.warnLegacyBrowsers:` | Shows a warning message after loading {kib} to any browser that does not enforce even rudimentary CSP rules, though {kib} is still accessible. This -configuration is effectively ignored when `csp.strict` is enabled. +configuration is effectively ignored when <> is enabled. *Default: `true`* | `elasticsearch.customHeaders:` | Header names and values to send to {es}. Any custom headers cannot be overwritten by client-side headers, regardless of the -`elasticsearch.requestHeadersWhitelist` configuration. *Default: `{}`* +<> configuration. *Default: `{}`* -| `elasticsearch.hosts:` +|[[elasticsearch-hosts]] `elasticsearch.hosts:` | The URLs of the {es} instances to use for all your queries. All nodes listed here must be on the same cluster. *Default: `[ "http://localhost:9200" ]`* -+ + To enable SSL/TLS for outbound connections to {es}, use the `https` protocol in this setting. | `elasticsearch.logQueries:` - | Log queries sent to {es}. Requires `logging.verbose` set to `true`. + | Log queries sent to {es}. Requires <> set to `true`. This is useful for seeing the query DSL generated by applications that currently do not have an inspector, for example Timelion and Monitoring. *Default: `false`* -| `elasticsearch.pingTimeout:` +|[[elasticsearch-pingTimeout]] `elasticsearch.pingTimeout:` | Time in milliseconds to wait for {es} to respond to pings. -*Default: the value of the `elasticsearch.requestTimeout` setting* - -| `elasticsearch.preserveHost:` - | When the value is `true`, {kib} uses the hostname specified in the -`server.host` setting. When the value is `false`, {kib} uses -the hostname of the host that connects to this {kib} instance. *Default: `true`* +*Default: the value of the <> setting* -| `elasticsearch.requestHeadersWhitelist:` +|[[elasticsearch-requestHeadersWhitelist]] `elasticsearch.requestHeadersWhitelist:` | List of {kib} client-side headers to send to {es}. To send *no* client-side headers, set this value to [] (an empty list). Removing the `authorization` header from being whitelisted means that you cannot use <> in {kib}. *Default: `[ 'authorization' ]`* -| `elasticsearch.requestTimeout:` +|[[elasticsearch-requestTimeout]] `elasticsearch.requestTimeout:` | Time in milliseconds to wait for responses from the back end or {es}. This value must be a positive integer. *Default: `30000`* @@ -99,7 +94,7 @@ nodes. *Default: `false`* | Update the list of {es} nodes immediately following a connection fault. *Default: `false`* -| `elasticsearch.ssl.alwaysPresentCertificate:` +|[[elasticsearch-ssl-alwaysPresentCertificate]] `elasticsearch.ssl.alwaysPresentCertificate:` | Controls {kib} behavior in regard to presenting a client certificate when requested by {es}. This setting applies to all outbound SSL/TLS connections to {es}, including requests that are proxied for end users. *Default: `false`* @@ -109,7 +104,7 @@ to {es}, including requests that are proxied for end users. *Default: `false`* [WARNING] ============ When {es} uses certificates to authenticate end users with a PKI realm -and `elasticsearch.ssl.alwaysPresentCertificate` is `true`, +and <> is `true`, proxied requests may be executed as the identity that is tied to the {kib} server. ============ @@ -117,7 +112,7 @@ server. [cols="2*<"] |=== -| `elasticsearch.ssl.certificate:` and `elasticsearch.ssl.key:` +|[[elasticsearch-ssl-cert-key]] `elasticsearch.ssl.certificate:` and `elasticsearch.ssl.key:` | Paths to a PEM-encoded X.509 client certificate and its corresponding private key. These are used by {kib} to authenticate itself when making outbound SSL/TLS connections to {es}. For this setting to take effect, the @@ -129,46 +124,48 @@ be set to `"required"` or `"optional"` to request a client certificate from [NOTE] ============ -These settings cannot be used in conjunction with `elasticsearch.ssl.keystore.path`. +These settings cannot be used in conjunction with +<>. ============ [cols="2*<"] |=== -| `elasticsearch.ssl.certificateAuthorities:` +|[[elasticsearch-ssl-certificateAuthorities]] `elasticsearch.ssl.certificateAuthorities:` | Paths to one or more PEM-encoded X.509 certificate authority (CA) certificates, which make up a trusted certificate chain for {es}. This chain is used by {kib} to establish trust when making outbound SSL/TLS connections to {es}. -+ + In addition to this setting, trusted certificates may be specified via -`elasticsearch.ssl.keystore.path` and/or `elasticsearch.ssl.truststore.path`. +<> and/or +<>. | `elasticsearch.ssl.keyPassphrase:` | The password that decrypts the private key that is specified -via `elasticsearch.ssl.key`. This value is optional, as the key may not be +via <>. This value is optional, as the key may not be encrypted. -| `elasticsearch.ssl.keystore.path:` +|[[elasticsearch-ssl-keystore-path]] `elasticsearch.ssl.keystore.path:` | Path to a PKCS#12 keystore that contains an X.509 client certificate and it's corresponding private key. These are used by {kib} to authenticate itself when making outbound SSL/TLS connections to {es}. For this setting, you must also set the `xpack.security.http.ssl.client_authentication` setting in {es} to `"required"` or `"optional"` to request a client certificate from {kib}. -+ + If the keystore contains any additional certificates, they are used as a trusted certificate chain for {es}. This chain is used by {kib} to establish trust when making outbound SSL/TLS connections to {es}. In addition to this setting, trusted certificates may be specified via -`elasticsearch.ssl.certificateAuthorities` and/or -`elasticsearch.ssl.truststore.path`. +<> and/or +<>. |=== [NOTE] ============ This setting cannot be used in conjunction with -`elasticsearch.ssl.certificate` or `elasticsearch.ssl.key`. +<> or <>. ============ [cols="2*<"] @@ -176,24 +173,24 @@ This setting cannot be used in conjunction with | `elasticsearch.ssl.keystore.password:` | The password that decrypts the keystore specified via -`elasticsearch.ssl.keystore.path`. If the keystore has no password, leave this +<>. If the keystore has no password, leave this as blank. If the keystore has an empty password, set this to `""`. -| `elasticsearch.ssl.truststore.path:`:: +|[[elasticsearch-ssl-truststore-path]] `elasticsearch.ssl.truststore.path:` | Path to a PKCS#12 trust store that contains one or more X.509 certificate authority (CA) certificates, which make up a trusted certificate chain for {es}. This chain is used by {kib} to establish trust when making outbound SSL/TLS connections to {es}. -+ + In addition to this setting, trusted certificates may be specified via -`elasticsearch.ssl.certificateAuthorities` and/or -`elasticsearch.ssl.keystore.path`. +<> and/or +<>. |`elasticsearch.ssl.truststore.password:` | The password that decrypts the trust store specified via -`elasticsearch.ssl.truststore.path`. If the trust store has no password, -leave this as blank. If the trust store has an empty password, set this to `""`. +<>. If the trust store +has no password, leave this as blank. If the trust store has an empty password, set this to `""`. | `elasticsearch.ssl.verificationMode:` | Controls the verification of the server certificate that {kib} receives when @@ -202,11 +199,7 @@ making an outbound SSL/TLS connection to {es}. Valid values are `"full"`, using `"certificate"` skips hostname verification, and using `"none"` skips verification entirely. *Default: `"full"`* -| `elasticsearch.startupTimeout:` - | Time in milliseconds to wait for {es} at {kib} startup before retrying. -*Default: `5000`* - -| `elasticsearch.username:` and `elasticsearch.password:` +|[[elasticsearch-user-passwd]] `elasticsearch.username:` and `elasticsearch.password:` | If your {es} is protected with basic authentication, these settings provide the username and password that the {kib} server uses to perform maintenance on the {kib} index at startup. {kib} users still need to authenticate with @@ -220,7 +213,7 @@ on the {kib} index at startup. {kib} users still need to authenticate with Please use the `defaultRoute` advanced setting instead. The default application to load. *Default: `"home"`* -| `kibana.index:` +|[[kibana-index]] `kibana.index:` | {kib} uses an index in {es} to store saved searches, visualizations, and dashboards. {kib} creates a new index if the index doesn’t already exist. If you configure a custom index, the name must be lowercase, and conform to the @@ -236,7 +229,7 @@ This value must be a whole number greater than zero. *Default: `"1000"`* suggestions. This value must be a whole number greater than zero. *Default: `"100000"`* -| `logging.dest:` +|[[logging-dest]] `logging.dest:` | Enables you to specify a file where {kib} stores log output. *Default: `stdout`* @@ -244,7 +237,7 @@ suggestions. This value must be a whole number greater than zero. | Logs output as JSON. When set to `true`, the logs are formatted as JSON strings that include timestamp, log level, context, message text, and any other metadata that may be associated with the log message. -When `logging.dest.stdout` is set, and there is no interactive terminal ("TTY"), +When <> is set, and there is no interactive terminal ("TTY"), this setting defaults to `true`. *Default: `false`* | `logging.quiet:` @@ -271,7 +264,7 @@ The following example shows a valid logging rotate configuration: | `logging.rotate.enabled:` | experimental[] Set the value of this setting to `true` to -enable log rotation. If you do not have a `logging.dest` set that is different from `stdout` +enable log rotation. If you do not have a <> set that is different from `stdout` that feature would not take any effect. *Default: `false`* | `logging.rotate.everyBytes:` @@ -286,9 +279,9 @@ option has to be in the range of 2 to 1024 files. *Default: `7`* | `logging.rotate.pollingInterval:` | experimental[] The number of milliseconds for the polling strategy in case -the `logging.rotate.usePolling` is enabled. `logging.rotate.usePolling` must be in the 5000 to 3600000 millisecond range. *Default: `10000`* +the <> is enabled. `logging.rotate.usePolling` must be in the 5000 to 3600000 millisecond range. *Default: `10000`* -| `logging.rotate.usePolling:` +|[[logging-rotate-usePolling]] `logging.rotate.usePolling:` | experimental[] By default we try to understand the best way to monitoring the log file and warning about it. Please be aware there are some systems where watch api is not accurate. In those cases, in order to get the feature working, the `polling` method could be used enabling that option. *Default: `false`* @@ -298,24 +291,25 @@ the `polling` method could be used enabling that option. *Default: `false`* suppress all logging output. *Default: `false`* | `logging.timezone` - | Set to the canonical timezone ID -(for example, `America/Los_Angeles`) to log events using that timezone. For a -list of timezones, refer to https://en.wikipedia.org/wiki/List_of_tz_database_time_zones. *Default: `UTC`* + | Set to the canonical time zone ID +(for example, `America/Los_Angeles`) to log events using that time zone. +For possible values, refer to +https://en.wikipedia.org/wiki/List_of_tz_database_time_zones[database time zones]. *Default: `UTC`* -| [[logging-verbose]] `logging.verbose:` {ece-icon} +| [[logging-verbose]] `logging.verbose:` {ess-icon} | Set to `true` to log all events, including system usage information and all requests. *Default: `false`* -| `map.includeElasticMapsService:` {ess-icon} +| [[regionmap-ES-map]] `map.includeElasticMapsService:` {ess-icon} | Set to `false` to disable connections to Elastic Maps Service. -When `includeElasticMapsService` is turned off, only the vector layers configured by `map.regionmap` -and the tile layer configured by `map.tilemap.url` are available in <>. *Default: `true`* +When `includeElasticMapsService` is turned off, only the vector layers configured by <> +and the tile layer configured by <> are available in <>. *Default: `true`* | `map.proxyElasticMapsServiceInMaps:` | Set to `true` to proxy all <> Elastic Maps Service requests through the {kib} server. *Default: `false`* -| [[regionmap-settings]] `map.regionmap:` {ess-icon} {ece-icon} +| [[regionmap-settings]] `map.regionmap:` {ess-icon} | Specifies additional vector layers for use in <> visualizations. Each layer object points to an external vector file that contains a geojson @@ -345,16 +339,10 @@ map.regionmap: [cols="2*<"] |=== -| [[regionmap-ES-map]] `map.includeElasticMapsService:` {ece-icon} - | Turns on or off whether layers from the Elastic Maps Service should be included in the vector -layer option list. By turning this off, -only the layers that are configured here will be included. The default is `true`. -This also affects whether tile-service from the Elastic Maps Service will be available. - -| [[regionmap-attribution]] `map.regionmap.layers[].attribution:` {ess-icon} {ece-icon} +| [[regionmap-attribution]] `map.regionmap.layers[].attribution:` {ess-icon} | Optional. References the originating source of the geojson file. -| [[regionmap-fields]] `map.regionmap.layers[].fields[]:` {ess-icon} {ece-icon} +| [[regionmap-fields]] `map.regionmap.layers[].fields[]:` {ess-icon} | Mandatory. Each layer can contain multiple fields to indicate what properties from the geojson features you wish to expose. The following shows how to define multiple @@ -380,11 +368,11 @@ map.regionmap: [cols="2*<"] |=== -| [[regionmap-field-description]] `map.regionmap.layers[].fields[].description:` {ess-icon} {ece-icon} +| [[regionmap-field-description]] `map.regionmap.layers[].fields[].description:` {ess-icon} | Mandatory. The human readable text that is shown under the Options tab when building the Region Map visualization. -| [[regionmap-field-name]] `map.regionmap.layers[].fields[].name:` {ess-icon} {ece-icon} +| [[regionmap-field-name]] `map.regionmap.layers[].fields[].name:` {ess-icon} | Mandatory. This value is used to do an inner-join between the document stored in {es} and the geojson file. For example, if the field in the geojson is @@ -392,30 +380,30 @@ called `Location` and has city names, there must be a field in {es} that holds the same values that {kib} can then use to lookup for the geoshape data. -| [[regionmap-name]] `map.regionmap.layers[].name:` {ess-icon} {ece-icon} +| [[regionmap-name]] `map.regionmap.layers[].name:` {ess-icon} | Mandatory. A description of the map being provided. -| [[regionmap-url]] `map.regionmap.layers[].url:` {ess-icon} {ece-icon} +| [[regionmap-url]] `map.regionmap.layers[].url:` {ess-icon} | Mandatory. The location of the geojson file as provided by a webserver. -| [[tilemap-settings]] `map.tilemap.options.attribution:` {ess-icon} {ece-icon} +| [[tilemap-settings]] `map.tilemap.options.attribution:` {ess-icon} | The map attribution string. *Default: `"© [Elastic Maps Service](https://www.elastic.co/elastic-maps-service)"`* -| [[tilemap-max-zoom]] `map.tilemap.options.maxZoom:` {ess-icon} {ece-icon} +| [[tilemap-max-zoom]] `map.tilemap.options.maxZoom:` {ess-icon} | The maximum zoom level. *Default: `10`* -| [[tilemap-min-zoom]] `map.tilemap.options.minZoom:` {ess-icon} {ece-icon} +| [[tilemap-min-zoom]] `map.tilemap.options.minZoom:` {ess-icon} | The minimum zoom level. *Default: `1`* -| [[tilemap-subdomains]] `map.tilemap.options.subdomains:` {ess-icon} {ece-icon} +| [[tilemap-subdomains]] `map.tilemap.options.subdomains:` {ess-icon} | An array of subdomains used by the tile service. Specify the position of the subdomain the URL with the token `{s}`. -| [[tilemap-url]] `map.tilemap.url:` {ess-icon} {ece-icon} +| [[tilemap-url]] `map.tilemap.url:` {ess-icon} | The URL to the tileservice that {kib} uses to display map tiles in tilemap visualizations. By default, {kib} reads this URL from an external metadata service, but users can @@ -427,7 +415,7 @@ override this parameter to use their own Tile Map Service. For example: system for the {kib} UI notification center. Set to `false` to disable the newsfeed system. *Default: `true`* -| `path.data:` +|[[path-data]] `path.data:` | The path where {kib} stores persistent data not saved in {es}. *Default: `data`* @@ -438,17 +426,17 @@ not saved in {es}. *Default: `data`* | Set the interval in milliseconds to sample system and process performance metrics. The minimum value is 100. *Default: `5000`* -| `ops.cGroupOverrides.cpuPath:` +|[[ops-cGroupOverrides-cpuPath]] `ops.cGroupOverrides.cpuPath:` | Override for cgroup cpu path when mounted in a manner that is inconsistent with `/proc/self/cgroup`. -| `ops.cGroupOverrides.cpuAcctPath:` +|[[ops-cGroupOverrides-cpuAcctPath]] `ops.cGroupOverrides.cpuAcctPath:` | Override for cgroup cpuacct path when mounted in a manner that is inconsistent with `/proc/self/cgroup`. -| `server.basePath:` +|[[server-basePath]] `server.basePath:` | Enables you to specify a path to mount {kib} at if you are -running behind a proxy. Use the `server.rewriteBasePath` setting to tell {kib} +running behind a proxy. Use the <> setting to tell {kib} if it should remove the basePath from requests it receives, and to prevent a deprecation warning at startup. This setting cannot end in a slash (`/`). @@ -458,19 +446,19 @@ deprecation warning at startup. This setting cannot end in a slash (`/`). | `server.compression.referrerWhitelist:` | Specifies an array of trusted hostnames, such as the {kib} host, or a reverse proxy sitting in front of it. This determines whether HTTP compression may be used for responses, based on the request `Referer` header. -This setting may not be used when `server.compression.enabled` is set to `false`. *Default: `none`* +This setting may not be used when <> is set to `false`. *Default: `none`* | `server.customResponseHeaders:` {ess-icon} | Header names and values to send on all responses to the client from the {kib} server. *Default: `{}`* -| `server.host:` +|[[server-host]] `server.host:` | This setting specifies the host of the back end server. To allow remote users to connect, set the value to the IP address or DNS name of the {kib} server. *Default: `"localhost"`* | `server.keepaliveTimeout:` | The number of milliseconds to wait for additional data before restarting -the `server.socketTimeout` counter. *Default: `"120000"`* +the <> counter. *Default: `"120000"`* | `server.maxPayloadBytes:` | The maximum payload size in bytes @@ -480,28 +468,28 @@ for incoming server requests. *Default: `1048576`* | A human-readable display name that identifies this {kib} instance. *Default: `"your-hostname"`* -| `server.port:` +|[[server-port]] `server.port:` | {kib} is served by a back end server. This setting specifies the port to use. *Default: `5601`* -| `server.requestId.allowFromAnyIp:` +|[[server-requestId-allowFromAnyIp]] `server.requestId.allowFromAnyIp:` | Sets whether or not the X-Opaque-Id header should be trusted from any IP address for identifying requests in logs and forwarded to Elasticsearch. | `server.requestId.ipAllowlist:` - | A list of IPv4 and IPv6 address which the `X-Opaque-Id` header should be trusted from. Normally this would be set to the IP addresses of the load balancers or reverse-proxy that end users use to access Kibana. If any are set, `server.requestId.allowFromAnyIp` must also be set to `false.` + | A list of IPv4 and IPv6 address which the `X-Opaque-Id` header should be trusted from. Normally this would be set to the IP addresses of the load balancers or reverse-proxy that end users use to access Kibana. If any are set, <> must also be set to `false.` -| `server.rewriteBasePath:` +|[[server-rewriteBasePath]] `server.rewriteBasePath:` | Specifies whether {kib} should -rewrite requests that are prefixed with `server.basePath` or require that they +rewrite requests that are prefixed with <> or require that they are rewritten by your reverse proxy. In {kib} 6.3 and earlier, the default is `false`. In {kib} 7.x, the setting is deprecated. In {kib} 8.0 and later, the default is `true`. *Default: `deprecated`* -| `server.socketTimeout:` +|[[server-socketTimeout]] `server.socketTimeout:` | The number of milliseconds to wait before closing an inactive socket. *Default: `"120000"`* -| `server.ssl.certificate:` and `server.ssl.key:` +|[[server-ssl-cert-key]] `server.ssl.certificate:` and `server.ssl.key:` | Paths to a PEM-encoded X.509 server certificate and its corresponding private key. These are used by {kib} to establish trust when receiving inbound SSL/TLS connections from users. @@ -509,18 +497,18 @@ are used by {kib} to establish trust when receiving inbound SSL/TLS connections [NOTE] ============ -These settings cannot be used in conjunction with `server.ssl.keystore.path`. +These settings cannot be used in conjunction with <>. ============ [cols="2*<"] |=== -| `server.ssl.certificateAuthorities:` +|[[server-ssl-certificateAuthorities]] `server.ssl.certificateAuthorities:` | Paths to one or more PEM-encoded X.509 certificate authority (CA) certificates which make up a trusted certificate chain for {kib}. This chain is used by {kib} to establish trust when receiving inbound SSL/TLS connections from end users. If PKI authentication is enabled, this chain is also used by {kib} to verify client certificates from end users. -+ -In addition to this setting, trusted certificates may be specified via `server.ssl.keystore.path` and/or `server.ssl.truststore.path`. + +In addition to this setting, trusted certificates may be specified via <> and/or <>. | `server.ssl.cipherSuites:` | Details on the format, and the valid options, are available via the @@ -533,53 +521,53 @@ connections. Valid values are `"required"`, `"optional"`, and `"none"`. Using `" client presents a certificate, using `"optional"` will allow a client to present a certificate if it has one, and using `"none"` will prevent a client from presenting a certificate. *Default: `"none"`* -| `server.ssl.enabled:` +|[[server-ssl-enabled]] `server.ssl.enabled:` | Enables SSL/TLS for inbound connections to {kib}. When set to `true`, a certificate and its -corresponding private key must be provided. These can be specified via `server.ssl.keystore.path` or the combination of -`server.ssl.certificate` and `server.ssl.key`. *Default: `false`* +corresponding private key must be provided. These can be specified via <> or the combination of +<> and <>. *Default: `false`* | `server.ssl.keyPassphrase:` - | The password that decrypts the private key that is specified via `server.ssl.key`. This value + | The password that decrypts the private key that is specified via <>. This value is optional, as the key may not be encrypted. -| `server.ssl.keystore.path:` +|[[server-ssl-keystore-path]] `server.ssl.keystore.path:` | Path to a PKCS#12 keystore that contains an X.509 server certificate and its corresponding private key. If the keystore contains any additional certificates, those will be used as a trusted certificate chain for {kib}. All of these are used by {kib} to establish trust when receiving inbound SSL/TLS connections from end users. The certificate chain is also used by {kib} to verify client certificates from end users when PKI authentication is enabled. -+ -In addition to this setting, trusted certificates may be specified via `server.ssl.certificateAuthorities` and/or -`server.ssl.truststore.path`. + +In addition to this setting, trusted certificates may be specified via <> and/or +<>. |=== [NOTE] ============ -This setting cannot be used in conjunction with `server.ssl.certificate` or `server.ssl.key` +This setting cannot be used in conjunction with <> or <> ============ [cols="2*<"] |=== | `server.ssl.keystore.password:` - | The password that will be used to decrypt the keystore specified via `server.ssl.keystore.path`. If the + | The password that will be used to decrypt the keystore specified via <>. If the keystore has no password, leave this unset. If the keystore has an empty password, set this to `""`. -| `server.ssl.truststore.path:` +|[[server-ssl-truststore-path]] `server.ssl.truststore.path:` | Path to a PKCS#12 trust store that contains one or more X.509 certificate authority (CA) certificates which make up a trusted certificate chain for {kib}. This chain is used by {kib} to establish trust when receiving inbound SSL/TLS connections from end users. If PKI authentication is enabled, this chain is also used by {kib} to verify client certificates from end users. -+ -In addition to this setting, trusted certificates may be specified via `server.ssl.certificateAuthorities` and/or -`server.ssl.keystore.path`. + +In addition to this setting, trusted certificates may be specified via <> and/or +<>. | `server.ssl.truststore.password:` - | The password that will be used to decrypt the trust store specified via `server.ssl.truststore.path`. If + | The password that will be used to decrypt the trust store specified via <>. If the trust store has no password, leave this unset. If the trust store has an empty password, set this to `""`. | `server.ssl.redirectHttpFromPort:` | {kib} binds to this port and redirects -all http requests to https over the port configured as `server.port`. +all http requests to https over the port configured as <>. | `server.ssl.supportedProtocols:` | An array of supported protocols with versions. @@ -588,7 +576,7 @@ Valid protocols: `TLSv1`, `TLSv1.1`, `TLSv1.2`. *Default: TLSv1.1, TLSv1.2* | [[settings-xsrf-whitelist]] `server.xsrf.whitelist:` | It is not recommended to disable protections for arbitrary API endpoints. Instead, supply the `kbn-xsrf` header. -The `server.xsrf.whitelist` setting requires the following format: +The <> setting requires the following format: |=== @@ -608,18 +596,18 @@ The `server.xsrf.whitelist` setting requires the following format: setting this to `true` enables unauthenticated users to access the {kib} server status API and status page. *Default: `false`* -| `telemetry.allowChangingOptInStatus` +|[[telemetry-allowChangingOptInStatus]] `telemetry.allowChangingOptInStatus` | When `true`, users are able to change the telemetry setting at a later time in <>. When `false`, -{kib} looks at the value of `telemetry.optIn` to determine whether to send -telemetry data or not. `telemetry.allowChangingOptInStatus` and `telemetry.optIn` +{kib} looks at the value of <> to determine whether to send +telemetry data or not. <> and <> cannot be `false` at the same time. *Default: `true`*. -| `telemetry.optIn` +|[[settings-telemetry-optIn]] `telemetry.optIn` | When `true`, telemetry data is sent to Elastic. When `false`, collection of telemetry data is disabled. To enable telemetry and prevent users from disabling it, -set `telemetry.allowChangingOptInStatus` to `false` and `telemetry.optIn` to `true`. +set <> to `false` and <> to `true`. *Default: `true`* | `telemetry.enabled` @@ -650,7 +638,7 @@ include::{kib-repo-dir}/settings/alert-action-settings.asciidoc[] include::{kib-repo-dir}/settings/apm-settings.asciidoc[] include::{kib-repo-dir}/settings/dev-settings.asciidoc[] include::{kib-repo-dir}/settings/graph-settings.asciidoc[] -include::{kib-repo-dir}/settings/ingest-manager-settings.asciidoc[] +include::{kib-repo-dir}/settings/fleet-settings.asciidoc[] include::{kib-repo-dir}/settings/i18n-settings.asciidoc[] include::{kib-repo-dir}/settings/logs-ui-settings.asciidoc[] include::{kib-repo-dir}/settings/infrastructure-ui-settings.asciidoc[] diff --git a/docs/user/alerting/action-types.asciidoc b/docs/user/alerting/action-types.asciidoc index be31458ff39fa..af80b17f8605f 100644 --- a/docs/user/alerting/action-types.asciidoc +++ b/docs/user/alerting/action-types.asciidoc @@ -11,10 +11,19 @@ a| <> | Send email from your server. +a| <> + +| Create an incident in IBM Resilient. + a| <> | Index data into Elasticsearch. +a| <> + +| Create an incident in Jira. + + a| <> | Send an event in PagerDuty. @@ -53,10 +62,12 @@ before {kib} starts. If you preconfigure a connector, you can also <>. include::action-types/email.asciidoc[] +include::action-types/resilient.asciidoc[] include::action-types/index.asciidoc[] +include::action-types/jira.asciidoc[] include::action-types/pagerduty.asciidoc[] include::action-types/server-log.asciidoc[] +include::action-types/servicenow.asciidoc[] include::action-types/slack.asciidoc[] include::action-types/webhook.asciidoc[] include::action-types/pre-configured-connectors.asciidoc[] -include::action-types/servicenow.asciidoc[] diff --git a/docs/user/alerting/action-types/jira.asciidoc b/docs/user/alerting/action-types/jira.asciidoc new file mode 100644 index 0000000000000..65e5ee4fc4a01 --- /dev/null +++ b/docs/user/alerting/action-types/jira.asciidoc @@ -0,0 +1,79 @@ +[role="xpack"] +[[jira-action-type]] +=== Jira action + +The Jira action type uses the https://developer.atlassian.com/cloud/jira/platform/rest/v2/[REST API v2] to create Jira issues. + +[float] +[[jira-connector-configuration]] +==== Connector configuration + +Jira connectors have the following configuration properties: + +Name:: The name of the connector. The name is used to identify a connector in the **Stack Management** UI connector listing, and in the connector list when configuring an action. +URL:: Jira instance URL. +Project key:: Jira project key. +Email (or username):: The account email (or username) for HTTP Basic authentication. +API token (or password):: Jira API authentication token (or password) for HTTP Basic authentication. + +[float] +[[Preconfigured-jira-configuration]] +==== Preconfigured action type + +[source,text] +-- + my-jira: + name: preconfigured-jira-action-type + actionTypeId: .jira + config: + apiUrl: https://elastic.atlassian.net + projectKey: ES + secrets: + email: testuser + apiToken: tokenkeystorevalue +-- + +`config` defines the action type specific to the configuration and contains the following properties: + +[cols="2*<"] +|=== + +| `apiUrl` +| An address that corresponds to *URL*. + +| `projectKey` +| A key that corresponds to *Project Key*. + +|=== + +`secrets` defines sensitive information for the action type: + +[cols="2*<"] +|=== + +| `email` +| A string that corresponds to *Email*. + +| `apiToken` +| A string that corresponds to *API Token*. Should be stored in the <>. + +|=== + +[[jira-action-configuration]] +==== Action configuration + +Jira actions have the following configuration properties: + +Issue type:: The type of the issue. +Priority:: The priority of the incident. +Labels:: The labels of the incident. +Title:: A title for the issue, used for searching the contents of the knowledge base. +Description:: The details about the incident. +Parent:: The parent issue id or key. Only for `Sub-task` issue types. +Priority:: The priority of the incident. +Additional comments:: Additional information for the client, such as how to troubleshoot the issue. + +[[configuring-jira]] +==== Configuring and testing Jira + +Jira offers free https://www.atlassian.com/software/jira/free[Instances], which you can use to test incidents. diff --git a/docs/user/alerting/action-types/pagerduty.asciidoc b/docs/user/alerting/action-types/pagerduty.asciidoc index 2c9add5233c91..9301224e6df48 100644 --- a/docs/user/alerting/action-types/pagerduty.asciidoc +++ b/docs/user/alerting/action-types/pagerduty.asciidoc @@ -36,7 +36,7 @@ This is required to encrypt parameters that must be secured, for example PagerDu If you have security enabled: * You must have -application privileges to access Metrics, APM, Uptime, or SIEM. +application privileges to access Metrics, APM, Uptime, or Security. * If you are using a self-managed deployment with security, you must have Transport Security Layer (TLS) enabled for communication <>. Alerts uses API keys to secure background alert checks and actions, diff --git a/docs/user/alerting/action-types/resilient.asciidoc b/docs/user/alerting/action-types/resilient.asciidoc new file mode 100644 index 0000000000000..b5ddb76d49b0c --- /dev/null +++ b/docs/user/alerting/action-types/resilient.asciidoc @@ -0,0 +1,76 @@ +[role="xpack"] +[[resilient-action-type]] +=== IBM Resilient action + +The IBM Resilient action type uses the https://developer.ibm.com/security/resilient/rest/[RESILIENT REST v2] to create IBM Resilient incidents. + +[float] +[[resilient-connector-configuration]] +==== Connector configuration + +IBM Resilient connectors have the following configuration properties: + +Name:: The name of the connector. The name is used to identify a connector in the **Stack Management** UI connector listing, and in the connector list when configuring an action. +URL:: IBM Resilient instance URL. +Organization ID:: IBM Resilient organization ID. +API key ID:: The authentication key ID for HTTP Basic authentication. +API key secret:: The authentication key secret for HTTP Basic authentication. + +[float] +[[Preconfigured-resilient-configuration]] +==== Preconfigured action type + +[source,text] +-- + my-resilient: + name: preconfigured-resilient-action-type + actionTypeId: .resilient + config: + apiUrl: https://elastic.resilient.net + orgId: ES + secrets: + apiKeyId: testuser + apiKeySecret: tokenkeystorevalue +-- + +`config` defines the action type specific to the configuration and contains the following properties: + +[cols="2*<"] +|=== + +| `apiUrl` +| An address that corresponds to *URL*. + +| `orgId` +| An ID that corresponds to *Organization ID*. + +|=== + +`secrets` defines sensitive information for the action type: + +[cols="2*<"] +|=== + +| `apiKeyId` +| A string that corresponds to *API key ID*. + +| `apiKeySecret` +| A string that corresponds to *API Key secret*. Should be stored in the <>. + +|=== + +[[resilient-action-configuration]] +==== Action configuration + +IBM Resilient actions have the following configuration properties: + +Incident types:: The incident types of the incident. +Severity code:: The severity of the incident. +Name:: A name for the issue, used for searching the contents of the knowledge base. +Description:: The details about the incident. +Additional comments:: Additional information for the client, such as how to troubleshoot the issue. + +[[configuring-resilient]] +==== Configuring and testing IBM Resilient + +IBM Resilient offers https://www.ibm.com/security/intelligent-orchestration/resilient[Instances], which you can use to test incidents. diff --git a/docs/user/alerting/action-types/servicenow.asciidoc b/docs/user/alerting/action-types/servicenow.asciidoc index 32f828aea2357..0acb92bcdb5ee 100644 --- a/docs/user/alerting/action-types/servicenow.asciidoc +++ b/docs/user/alerting/action-types/servicenow.asciidoc @@ -10,7 +10,7 @@ The ServiceNow action type uses the https://developer.servicenow.com/app.do#!/re ServiceNow connectors have the following configuration properties: -Name:: The name of the connector. The name is used to identify a connector in the management UI connector listing, or in the connector list when configuring an action. +Name:: The name of the connector. The name is used to identify a connector in the **Stack Management** UI connector listing, and in the connector list when configuring an action. URL:: ServiceNow instance URL. Username:: Username for HTTP Basic authentication. Password:: Password for HTTP Basic authentication. @@ -37,7 +37,7 @@ Password:: Password for HTTP Basic authentication. |=== | `apiUrl` -| An address that corresponds to *Sender*. +| An address that corresponds to *URL*. |=== @@ -47,7 +47,7 @@ Password:: Password for HTTP Basic authentication. |=== | `username` -| A string that corresponds to *User*. +| A string that corresponds to *Username*. | `password` | A string that corresponds to *Password*. Should be stored in the <>. @@ -62,7 +62,7 @@ ServiceNow actions have the following configuration properties: Urgency:: The extent to which the incident resolution can delay. Severity:: The severity of the incident. Impact:: The effect an incident has on business. Can be measured by the number of affected users or by how critical it is to the business in question. -Short description:: A short description of the incident, used for searching the contents of the knowledge base. +Short description:: A short description for the incident, used for searching the contents of the knowledge base. Description:: The details about the incident. Additional comments:: Additional information for the client, such as how to troubleshoot the issue. diff --git a/docs/user/alerting/alerting-getting-started.asciidoc b/docs/user/alerting/alerting-getting-started.asciidoc index 6bc085b0f78b9..bdb72b1658cd2 100644 --- a/docs/user/alerting/alerting-getting-started.asciidoc +++ b/docs/user/alerting/alerting-getting-started.asciidoc @@ -6,7 +6,7 @@ beta[] -- -Alerting allows you to detect complex conditions within different {kib} apps and trigger actions when those conditions are met. Alerting is integrated with <>, <>, <>, <>, can be centrally managed from the <> UI, and provides a set of built-in <> and <> for you to use. +Alerting allows you to detect complex conditions within different {kib} apps and trigger actions when those conditions are met. Alerting is integrated with <>, <>, <>, <>, can be centrally managed from the <> UI, and provides a set of built-in <> and <> for you to use. image::images/alerting-overview.png[Alerts and actions UI] @@ -148,7 +148,7 @@ Functionally, {kib} alerting differs in that: * {kib} alerts tracks and persists the state of each detected condition through *alert instances*. This makes it possible to mute and throttle individual instances, and detect changes in state such as resolution. * Actions are linked to *alert instances* in {kib} alerting. Actions are fired for each occurrence of a detected condition, rather than for the entire alert. -At a higher level, {kib} alerts allow rich integrations across use cases like <>, <>, <>, and <>. +At a higher level, {kib} alerts allow rich integrations across use cases like <>, <>, <>, and <>. Pre-packaged *alert types* simplify setup, hide the details complex domain-specific detections, while providing a consistent interface across {kib}. [float] @@ -171,7 +171,7 @@ To access alerting in a space, a user must have access to one of the following f * <> * <> -* <> +* <> * <> See <> for more information on configuring roles that provide access to these features. diff --git a/docs/user/alerting/defining-alerts.asciidoc b/docs/user/alerting/defining-alerts.asciidoc index d05a727016455..7f201d2c39e89 100644 --- a/docs/user/alerting/defining-alerts.asciidoc +++ b/docs/user/alerting/defining-alerts.asciidoc @@ -2,7 +2,7 @@ [[defining-alerts]] == Defining alerts -{kib} alerts can be created in a variety of apps including <>, <>, <>, <> and from <> UI. While alerting details may differ from app to app, they share a common interface for defining and configuring alerts that this section describes in more detail. +{kib} alerts can be created in a variety of apps including <>, <>, <>, <> and from <> UI. While alerting details may differ from app to app, they share a common interface for defining and configuring alerts that this section describes in more detail. [float] === Alert flyout diff --git a/docs/user/canvas.asciidoc b/docs/user/canvas.asciidoc index 0b0eb7a318495..297dfac5b10bd 100644 --- a/docs/user/canvas.asciidoc +++ b/docs/user/canvas.asciidoc @@ -17,6 +17,8 @@ With Canvas, you can: * Focus the data you want to display with filters. +To begin, open the menu, then go to *Canvas*. + [role="screenshot"] image::images/canvas-gs-example.png[Getting started example] @@ -26,7 +28,8 @@ For a quick overview of Canvas, watch link:https://www.youtube.com/watch?v=ZqvF_ [[create-workpads]] == Create workpads -A _workpad_ provides you with a space where you can build presentations of your live data. +A _workpad_ provides you with a space where you can build presentations of your live data. With Canvas, +you can create a workpad from scratch, start with a preconfigured workpad, import an existing workpad, or use a sample data workpad. [float] [[start-with-a-blank-workpad]] @@ -34,19 +37,15 @@ A _workpad_ provides you with a space where you can build presentations of your To use the background colors, images, and data of your choice, start with a blank workpad. -. Open the menu, then go to *Canvas*. - -. On the *Canvas workpads* view, click *Create workpad*. +. On the *Canvas workpads* page, click *Create workpad*. -. Add a *Name* to your workpad. +. Specify the *Workpad settings*. -. In the *Width* and *Height* fields, specify the size. +.. Add a *Name* to your workpad. -. Select the layout. -+ -For example, click *720p* for a traditional presentation layout. +.. In the *Width* and *Height* fields, specify the size, or select one of default layouts. -. Click the *Background color* picker, then select the background color for your workpad. +.. Click the *Background* color picker, then select the color for your workpad. + [role="screenshot"] image::images/canvas-background-color-picker.png[Canvas color picker] @@ -57,9 +56,7 @@ image::images/canvas-background-color-picker.png[Canvas color picker] If you're unsure about where to start, you can use one of the preconfigured templates that come with Canvas. -. Open the menu, then go to *Canvas*. - -. On the *Canvas workpads* view, select *Templates*. +. On the *Canvas workpads* page, select *Templates*. . Click the preconfigured template that you want to use. @@ -69,17 +66,15 @@ If you're unsure about where to start, you can use one of the preconfigured temp [[import-existing-workpads]] === Import existing workpads -When you want to use a workpad that someone else has already started, import the JSON file into Canvas. - -. Open the menu, then go to *Canvas*. +When you want to use a workpad that someone else has already started, import the JSON file. -. On the *Canvas workpads* view, click and drag the file to the *Import workpad JSON file* field. +To begin, drag the file to the *Import workpad JSON file* field on the *Canvas workpads* page. [float] [[use-sample-data-workpads]] === Use sample data workpads -Each of the sample data sets comes with a Canvas workpad that you can use for your own workpad inspiration. +Each of the {kib} sample data sets comes with a workpad that you can use for your own workpad inspiration. . Add a {kibana-ref}/add-sample-data.html[sample data set]. @@ -123,12 +118,12 @@ To save a group of elements, press and hold Shift, select the elements you want Elements are saved in *Add element > My elements*. [float] -[[add-existing-visuualizations]] -=== Add existing visualizations +[[add-saved-objects]] +=== Add saved objects Add <> to your workpad, such as maps and visualizations. -. Click *Add element > Add from Visualize Library*. +. Click *Add element > Add from {kib}*. . Select the saved object you want to add. + diff --git a/docs/user/dashboard/dashboard-drilldown.asciidoc b/docs/user/dashboard/dashboard-drilldown.asciidoc index 84701cae2ecc6..5e928fd731bb4 100644 --- a/docs/user/dashboard/dashboard-drilldown.asciidoc +++ b/docs/user/dashboard/dashboard-drilldown.asciidoc @@ -11,6 +11,26 @@ This example shows a dashboard panel that contains a pie chart with a configured [role="screenshot"] image::images/drilldown_on_piechart.gif[Drilldown on pie chart that navigates to another dashboard] +[float] +[[dashboard-drilldown-supported-panels]] +==== Supported panels + +The following panels support dashboard drilldowns: + +* Lens +* Area +* Data table +* Heat map +* Horizontal bar +* Line +* Maps +* Pie +* TSVB +* Tag cloud +* Timelion +* Vega +* Vertical bar + [float] [[drilldowns-example]] ==== Try it: Create a dashboard drilldown @@ -19,7 +39,7 @@ Create the *Host Overview* drilldown shown above. *Set up the dashboards* -. Add the <> data set. +. Add the sample web logs data set. . Create a new dashboard, called `Host Overview`, and include these visualizations from the sample data set: @@ -74,3 +94,4 @@ image::images/drilldown_on_panel.png[Drilldown on pie chart that navigates to an + You are navigated to your destination dashboard. Verify that the search query, filters, and time range are carried over. + diff --git a/docs/user/dashboard/dashboard.asciidoc b/docs/user/dashboard/dashboard.asciidoc index c8bff91be91a6..4fa4f9860c2bd 100644 --- a/docs/user/dashboard/dashboard.asciidoc +++ b/docs/user/dashboard/dashboard.asciidoc @@ -209,18 +209,18 @@ visualization, configure the customization options for your visualization. The data fields that are displayed are based on the selected <> and the <>. -To view the data fields in a different index pattern, click the index pattern, then select a new one. The data fields automatically update. +To view the data fields in a different index pattern, click the *Change Index Pattern* dropdown, then select a new one. To filter the data fields: -* Enter the name in the *Search field names*. -* Click *Field by type*, then select the filter. To show all fields in the index pattern, deselect *Only show fields with data*. +* Enter the data field name in *Search field names*. +* Click *Field filters*, then select the filter. [float] [[view-data-summaries]] -==== View data summaries +==== View data field summaries -To help you decide exactly the data you want to display, get a quick summary of each field. The summary shows the distribution of +To help you decide exactly the data you want to display, get a quick summary of each data field. The summary shows the distribution of values within the specified time range. To view the data field summary information, navigate to the field, then click *i*. @@ -252,11 +252,9 @@ When there is an exclamation point (!) next to a visualization type, *Lens* is u For each visualization type, you can customize the aggregation and labels. The options available depend on the selected visualization type. -. Click a data field name in the editor, or click *Drop a field here*. -. Change the options that appear. -+ -[role="screenshot"] -image::images/lens_aggregation_labels.png[Quick function options] +. From the editor, click a data field, or click *Drop a field or click to add*. + +. Change the options, then click *Close*. [float] [[add-layers-and-indices]] diff --git a/docs/user/dashboard/images/lens_aggregation_labels.png b/docs/user/dashboard/images/lens_aggregation_labels.png deleted file mode 100644 index 9dcf1d226a197..0000000000000 Binary files a/docs/user/dashboard/images/lens_aggregation_labels.png and /dev/null differ diff --git a/docs/user/dashboard/images/lens_drag_drop.gif b/docs/user/dashboard/images/lens_drag_drop.gif index ca62115e7ea3a..22939467daa12 100644 Binary files a/docs/user/dashboard/images/lens_drag_drop.gif and b/docs/user/dashboard/images/lens_drag_drop.gif differ diff --git a/docs/user/dashboard/images/lens_index_pattern.png b/docs/user/dashboard/images/lens_index_pattern.png index 90a34b7a5d225..0c89e7ab7f814 100644 Binary files a/docs/user/dashboard/images/lens_index_pattern.png and b/docs/user/dashboard/images/lens_index_pattern.png differ diff --git a/docs/user/dashboard/images/lens_layers.png b/docs/user/dashboard/images/lens_layers.png index 7410425a6977e..5bc4217b7fb7d 100644 Binary files a/docs/user/dashboard/images/lens_layers.png and b/docs/user/dashboard/images/lens_layers.png differ diff --git a/docs/user/dashboard/images/lens_suggestions.gif b/docs/user/dashboard/images/lens_suggestions.gif index 3258e924cb205..5ba6aa5dee14d 100644 Binary files a/docs/user/dashboard/images/lens_suggestions.gif and b/docs/user/dashboard/images/lens_suggestions.gif differ diff --git a/docs/user/dashboard/images/lens_tutorial_1.png b/docs/user/dashboard/images/lens_tutorial_1.png new file mode 100644 index 0000000000000..047701fa495a7 Binary files /dev/null and b/docs/user/dashboard/images/lens_tutorial_1.png differ diff --git a/docs/user/dashboard/images/lens_tutorial_2.png b/docs/user/dashboard/images/lens_tutorial_2.png new file mode 100644 index 0000000000000..c3e5992778985 Binary files /dev/null and b/docs/user/dashboard/images/lens_tutorial_2.png differ diff --git a/docs/user/dashboard/images/lens_tutorial_3.1.png b/docs/user/dashboard/images/lens_tutorial_3.1.png new file mode 100644 index 0000000000000..23d9491c315e4 Binary files /dev/null and b/docs/user/dashboard/images/lens_tutorial_3.1.png differ diff --git a/docs/user/dashboard/images/lens_tutorial_3.2.png b/docs/user/dashboard/images/lens_tutorial_3.2.png new file mode 100644 index 0000000000000..cfe10fa1acfcf Binary files /dev/null and b/docs/user/dashboard/images/lens_tutorial_3.2.png differ diff --git a/docs/user/dashboard/images/lens_tutorial_3.png b/docs/user/dashboard/images/lens_tutorial_3.png new file mode 100644 index 0000000000000..891f24334d720 Binary files /dev/null and b/docs/user/dashboard/images/lens_tutorial_3.png differ diff --git a/docs/user/dashboard/images/lens_viz_types.png b/docs/user/dashboard/images/lens_viz_types.png index 2ecfa6bd0e0e3..0060234667f4e 100644 Binary files a/docs/user/dashboard/images/lens_viz_types.png and b/docs/user/dashboard/images/lens_viz_types.png differ diff --git a/docs/user/dashboard/tutorials.asciidoc b/docs/user/dashboard/tutorials.asciidoc index 931720ccbe257..b04de5fd0da6f 100644 --- a/docs/user/dashboard/tutorials.asciidoc +++ b/docs/user/dashboard/tutorials.asciidoc @@ -6,13 +6,13 @@ Learn how to use *Lens*, *Vega*, and *Timelion* by going through one of the step [[lens-tutorial]] === Compare sales over time with Lens -Ready to create your own visualization with Lens? Use the following tutorial to create a visualization that lets you compare sales over time. +Ready to create your own visualization with *Lens*? Use the following tutorial to create a visualization that lets you compare sales over time. [float] [[lens-before-begin]] ==== Before you begin -To start, you'll need to add the <>. +To start, add the <>. [float] ==== Build the visualization @@ -23,16 +23,16 @@ Drag and drop your data onto the visualization builder pane. . Click image:images/time-filter-calendar.png[], then click *Last 7 days*. + -The fields in the data panel update. +The *Available fields* automatically update. . Drag and drop the *taxful_total_price* data field to the visualization builder pane. + [role="screenshot"] image::images/lens_tutorial_1.png[Lens tutorial] -To display the average order prices over time, *Lens* automatically added in *order_date* field. +To display the average order prices over time, *Lens* automatically added *order_date* to the *X-axis*. -To break down your data, drag the *category.keyword* field to the visualization builder pane. Lens +To break down your data, drag and drop the *category.keyword* field to the visualization builder pane. Lens knows that you want to show the top categories and compare them across the dates, and creates a chart that compares the sales for each of the top three categories: @@ -45,30 +45,33 @@ image::images/lens_tutorial_2.png[Lens tutorial] Make your visualization look exactly how you want with the customization options. -. Click *Average of taxful_total_price*, then change the *Label* to `Sales`. +. Click *Average of taxful_total_price*, then change the *Display name* to Sales. + [role="screenshot"] image::images/lens_tutorial_3.1.png[Lens tutorial] +. Click *Close*. + . Click *Top values of category.keyword*, then change *Number of values* to `10`. + [role="screenshot"] image::images/lens_tutorial_3.2.png[Lens tutorial] + +. Click *Close*. + The visualization updates to show there are only six available categories. -+ -Look at the *Suggestions*. An area chart is not an option, but for the sales data, a stacked area chart might be the best option. -. To switch the chart type, click *Stacked bar chart* in the column, then click *Stacked area* from the *Select a visualizations* window. +. Look at the *Suggestions*. An area chart is not an option, but for the sales data, a stacked area chart might be the best option. +To switch the chart type, click *Stacked bar chart*, then click *Stacked area* from the *Select a visualization* dropdown. + [role="screenshot"] image::images/lens_tutorial_3.png[Lens tutorial] [float] [[lens-tutorial-next-steps]] -==== Next steps +==== What's next? -Now that you've created your visualization, you can add it to a <> or <>. +Now that you've created your *Lens* visualization, add it to a <> or <>. [[vega-lite-tutorial-create-your-first-visualizations]] === Create your first visualization with Vega-Lite diff --git a/docs/user/dashboard/url-drilldown.asciidoc b/docs/user/dashboard/url-drilldown.asciidoc index e6daf89d72718..b71dfb016c765 100644 --- a/docs/user/dashboard/url-drilldown.asciidoc +++ b/docs/user/dashboard/url-drilldown.asciidoc @@ -14,13 +14,29 @@ image:images/url_drilldown_go_to_github.gif[Drilldown on pie chart that navigate NOTE: URL drilldown is available with the https://www.elastic.co/subscriptions[Gold subscription] and higher. +[float] +[[url-drilldown-supported-panels]] +==== Supported panels + +The following panels support URL drilldowns: + +* Lens +* Area +* Data table +* Heat map +* Horizontal bar +* Line +* Pie +* Tag cloud +* Vertical bar + [float] [[try-it]] ==== Try it: Create a URL drilldown This example shows how to create the "Show on Github" drilldown shown above. -. Add the <> data set. +. Add the sample web logs data set. . Open the *[Logs] Web traffic* dashboard. This isn’t data from Github, but it should work for demonstration purposes. . In the dashboard menu bar, click *Edit*. . In *[Logs] Visitors by OS*, open the panel menu, and then select *Create drilldown*. @@ -238,3 +254,14 @@ Tip: Consider using <> helper for date formatting. | Aggregation field behind the selected range, if available. |=== + +[float] +[[disable]] +==== Disable URL drilldown + +You can disable URL drilldown feature on your {kib} instance by disabling the plugin: + +["source","yml"] +----------- +url_drilldown.enabled: false +----------- diff --git a/docs/user/dashboard/vega-reference.asciidoc b/docs/user/dashboard/vega-reference.asciidoc index eed8d9a35b874..378f7a53a6650 100644 --- a/docs/user/dashboard/vega-reference.asciidoc +++ b/docs/user/dashboard/vega-reference.asciidoc @@ -11,10 +11,10 @@ For additional *Vega* and *Vega-Lite* information, refer to the reference sectio {kib} has extended Vega and Vega-Lite with extensions that support: -* Default height and width +* Automatic sizing * Default theme to match {kib} * Writing {es} queries using the time range and filters from dashboards -* Using the Elastic Map Service in Vega maps +* experimental[] Using the Elastic Map Service in Vega maps * Additional tooltip styling * Advanced setting to enable URL loading from any domain * Limited debugging support using the browser dev tools @@ -22,12 +22,35 @@ For additional *Vega* and *Vega-Lite* information, refer to the reference sectio [float] [[vega-sizing-and-positioning]] -==== Default height and width +==== Automatic sizing -By default, Vega visualizations use the `autosize = { type: 'fit', contains: 'padding' }` layout. -`fit` uses all available space, ignores `width` and `height` values, -and respects the padding values. To override this behavior, change the -`autosize` value. +Most users will want their Vega visualizations to take the full available space, so unlike +Vega examples, `width` and `height` are not required parameters in {kib}. To set the width +or height manually, set `autosize: none`. For example, to set the height to a specific pixel value: + +``` +autosize: none +width: container +height: 200 +``` + +The default {kib} settings which are inherited by your visualizations are: + +``` +autosize: { + type: fit + contains: padding +} +width: container +height: container +``` + +{kib} is able to merge your custom `autosize` settings with the defaults. The options `fit-x` +and `fit-y` are supported but not recommended over the default `fit` setting. + +To learn more, read about +https://vega.github.io/vega/docs/specification/#autosize[autosize] +in the Vega documentation. [float] [[vega-theme]] @@ -41,16 +64,17 @@ Override it by providing a different `stroke`, `fill`, or `color` (Vega-Lite) va [[vega-queries]] ==== Writing {es} queries in Vega -experimental[] {kib} extends the Vega https://vega.github.io/vega/docs/data/[data] elements -with support for direct {es} queries specified as a `url`. +{kib} extends the Vega https://vega.github.io/vega/docs/data/[data] elements +with support for direct {es} queries specified as `url`. -Because of this, {kib} is **unable to support dynamically loaded data**, +{kib} is **unable to support dynamically loaded data**, which would otherwise work in Vega. All data is fetched before it's passed to the Vega renderer. -To define an {es} query in Vega, set the `url` to an object. {kib} will parse +To define an {es} query in Vega, set the `url` to an object. {kib} parses the object looking for special tokens that allow your query to integrate with {kib}. -These tokens are: + +Tokens include the following: * `%context%: true`: Set at the top level, and replaces the `query` section with filters from dashboard * `%timefield%: `: Set at the top level, integrates the query with the dashboard time filter @@ -64,8 +88,7 @@ These tokens are: * `"%dashboard_context-filter_clause%"`: String replaced by an object containing filters * `"%dashboard_context-must_not_clause%"`: String replaced by an object containing filters -Putting this together, an example query that counts the number of documents in -a specific index: +For example, the following query counts the number of documents in a specific index: [source,yaml] ---- diff --git a/docs/user/getting-started.asciidoc b/docs/user/getting-started.asciidoc deleted file mode 100644 index a877f6a66a79a..0000000000000 --- a/docs/user/getting-started.asciidoc +++ /dev/null @@ -1,61 +0,0 @@ -[[get-started]] -= Get started - -[partintro] --- - -Ready to try out {kib} and see what it can do? The quickest way to get started with {kib} is to set up on Cloud, then add a sample data set to explore the full range of {kib} features. - -[float] -[[set-up-on-cloud]] -== Set up on cloud - -include::{docs-root}/shared/cloud/ess-getting-started.asciidoc[] - -[float] -[[gs-get-data-into-kibana]] -== Get data into {kib} - -The easiest way to get data into {kib} is to add a sample data set. - -{kib} has several sample data sets that you can use before loading your own data: - -* *Sample eCommerce orders* includes visualizations for tracking product-related information, -such as cost, revenue, and price. - -* *Sample flight data* includes visualizations for monitoring flight routes. - -* *Sample web logs* includes visualizations for monitoring website traffic. - -To use the sample data sets: - -. Go to the home page. - -. Click *Load a data set and a {kib} dashboard*. - -. Click *View data* and view the prepackaged dashboards, maps, and more. - -[role="screenshot"] -image::getting-started/images/add-sample-data.png[] - -NOTE: The timestamps in the sample data sets are relative to when they are installed. -If you uninstall and reinstall a data set, the timestamps change to reflect the most recent installation. - -[float] -== Next steps - -* To get a hands-on experience creating visualizations, follow the <> tutorial. - -* If you're ready to load an actual data set and build a dashboard, follow the <> tutorial. - --- - -include::{kib-repo-dir}/getting-started/tutorial-sample-data.asciidoc[] - -include::{kib-repo-dir}/getting-started/tutorial-full-experience.asciidoc[] - -include::{kib-repo-dir}/getting-started/tutorial-define-index.asciidoc[] - -include::{kib-repo-dir}/getting-started/tutorial-discovering.asciidoc[] - -include::{kib-repo-dir}/getting-started/tutorial-visualizing.asciidoc[] diff --git a/docs/user/index.asciidoc b/docs/user/index.asciidoc index e909626c5779c..c186704dd2f16 100644 --- a/docs/user/index.asciidoc +++ b/docs/user/index.asciidoc @@ -2,6 +2,8 @@ include::introduction.asciidoc[] include::whats-new.asciidoc[] +include::{kib-repo-dir}/getting-started/quick-start-guide.asciidoc[] + include::setup.asciidoc[] include::monitoring/configuring-monitoring.asciidoc[leveloffset=+1] @@ -11,8 +13,6 @@ include::monitoring/monitoring-kibana.asciidoc[leveloffset=+2] include::security/securing-kibana.asciidoc[] -include::getting-started.asciidoc[] - include::discover.asciidoc[] include::dashboard/dashboard.asciidoc[] @@ -43,7 +43,7 @@ include::monitoring/index.asciidoc[] include::management.asciidoc[] -include::{kib-repo-dir}/ingest_manager/ingest-manager.asciidoc[] +include::{kib-repo-dir}/fleet/fleet.asciidoc[] include::reporting/index.asciidoc[] diff --git a/docs/user/introduction.asciidoc b/docs/user/introduction.asciidoc index 079d183dd959d..7e5dc59b03a2c 100644 --- a/docs/user/introduction.asciidoc +++ b/docs/user/introduction.asciidoc @@ -155,6 +155,6 @@ and start exploring data in minutes. You can also <> — no code, no additional infrastructure required. -Our <> and in-product guidance can +Our <> and in-product guidance can help you get up and running, faster. Click the help icon image:images/intro-help-icon.png[] in the top navigation bar for help with questions or to provide feedback. diff --git a/docs/user/management.asciidoc b/docs/user/management.asciidoc index bc96463f6efba..e0d550a15a907 100644 --- a/docs/user/management.asciidoc +++ b/docs/user/management.asciidoc @@ -58,12 +58,12 @@ years of historical data in combination with your raw data. | {ref}/transforms.html[Transforms] |Use transforms to pivot existing {es} indices into summarized or entity-centric indices. -| <> +| {ref}/ccr-getting-started.html[Cross-Cluster Replication] |Replicate indices on a remote cluster and copy them to a follower index on a local cluster. This is important for disaster recovery. It also keeps data local for faster queries. -| <> +| {ref}/ccr-getting-started.html#ccr-getting-started-remote-cluster[Remote Clusters] |Manage your remote clusters for use with cross-cluster search and cross-cluster replication. You can add and remove remote clusters, and check their connectivity. |=== @@ -180,8 +180,6 @@ include::{kib-repo-dir}/management/alerting/connector-management.asciidoc[] include::{kib-repo-dir}/management/managing-beats.asciidoc[] -include::{kib-repo-dir}/management/managing-ccr.asciidoc[] - include::{kib-repo-dir}/management/index-lifecycle-policies/intro-to-lifecycle-policies.asciidoc[] include::{kib-repo-dir}/management/index-lifecycle-policies/create-policy.asciidoc[] @@ -200,8 +198,6 @@ include::{kib-repo-dir}/management/managing-licenses.asciidoc[] include::{kib-repo-dir}/management/numeral.asciidoc[] -include::{kib-repo-dir}/management/managing-remote-clusters.asciidoc[] - include::{kib-repo-dir}/management/rollups/create_and_manage_rollups.asciidoc[] include::{kib-repo-dir}/management/managing-saved-objects.asciidoc[] diff --git a/docs/user/monitoring/viewing-metrics.asciidoc b/docs/user/monitoring/viewing-metrics.asciidoc index f35caea025cdd..0c48e3b7d011d 100644 --- a/docs/user/monitoring/viewing-metrics.asciidoc +++ b/docs/user/monitoring/viewing-metrics.asciidoc @@ -13,13 +13,19 @@ At a minimum, you must have monitoring data for the {es} production cluster. Once that data exists, {kib} can display monitoring data for other products in the cluster. +TIP: If you use a separate monitoring cluster to store the monitoring data, it +is strongly recommended that you use a separate {kib} instance to view it. If +you log in to {kib} using SAML, Kerberos, PKI, OpenID Connect, or token +authentication providers, a dedicated {kib} instance is *required*. The security +tokens that are used in these contexts are cluster-specific, therefore you +cannot use a single {kib} instance to connect to both production and monitoring +clusters. For more information about the recommended configuration, see +{ref}/monitoring-overview.html[Monitoring overview]. + . Identify where to retrieve monitoring data from. + -- -The cluster that contains the monitoring data is referred to -as the _monitoring cluster_. - -TIP: If the monitoring data is stored on a *dedicated* monitoring cluster, it is +If the monitoring data is stored on a dedicated monitoring cluster, it is accessible even when the cluster you're monitoring is not. If you have at least a gold license, you can send data from multiple clusters to the same monitoring cluster and view them all through the same instance of {kib}. diff --git a/docs/user/reporting/reporting-troubleshooting.asciidoc b/docs/user/reporting/reporting-troubleshooting.asciidoc index 82f0aa7ca0f19..1f07b0b57d8c7 100644 --- a/docs/user/reporting/reporting-troubleshooting.asciidoc +++ b/docs/user/reporting/reporting-troubleshooting.asciidoc @@ -18,8 +18,11 @@ Having trouble? Here are solutions to common problems you might encounter while [float] [[reporting-diagnostics]] -=== Reporting Diagnostics -Reporting comes with a built-in utility to try to automatically find common issues. When Kibana is running, navigate to the Report Listing page, and click the "Run reporting diagnostics..." button. This will open up a diagnostic tool that checks various parts of the Kibana deployment to come up with any relevant recommendations. +=== Reporting diagnostics +Reporting comes with a built-in utility to try to automatically find common issues. +When {kib} is running, navigate to the Report Listing page, and click *Run reporting diagnostics*. +This will open up a diagnostic tool that checks various parts of the {kib} deployment and +come up with any relevant recommendations. [float] [[reporting-troubleshooting-system-dependencies]] diff --git a/docs/user/security/api-keys/index.asciidoc b/docs/user/security/api-keys/index.asciidoc index c93d7caec1b7d..7cf1b964082d9 100644 --- a/docs/user/security/api-keys/index.asciidoc +++ b/docs/user/security/api-keys/index.asciidoc @@ -72,9 +72,9 @@ The response should look something like this: "api_key" : "FD6P5UA4QCWlZZQhYF3YGw" } -Now, you can use the API key to request {kib} roles. You will need -to base64-encode the `id` and `api_key` provided in the response -and add it to your request as an authorization header. For example: +Now, you can use the API key to request {kib} roles. You'll need to send a request with a +`Authorization` header with a value having the prefix `ApiKey` followed by the credentials, +where credentials is the base64 encoding of `id` and `api_key` joined by a colon. For example: [source,js] curl --location --request GET 'http://localhost:5601/api/security/role' \ diff --git a/docs/user/security/authorization/index.asciidoc b/docs/user/security/authorization/index.asciidoc index 44ca96e4aece5..3af49753db664 100644 --- a/docs/user/security/authorization/index.asciidoc +++ b/docs/user/security/authorization/index.asciidoc @@ -2,11 +2,11 @@ [[xpack-security-authorization]] === Granting access to {kib} -The Elastic Stack comes with the `kibana_admin` {ref}/built-in-roles.html[built-in role], which you can use to grant access to all Kibana features in all spaces. To grant users access to a subset of spaces or features, you can create a custom role that grants the desired Kibana privileges. +The Elastic Stack comes with the `kibana_admin` {ref}/built-in-roles.html[built-in role], which you can use to grant access to all {kib} features in all spaces. To grant users access to a subset of spaces or features, you can create a custom role that grants the desired {kib} privileges. -When you assign a user multiple roles, the user receives a union of the roles’ privileges. Therefore, assigning the `kibana_admin` role in addition to a custom role that grants Kibana privileges is ineffective because `kibana_admin` has access to all the features in all spaces. +When you assign a user multiple roles, the user receives a union of the roles’ privileges. Therefore, assigning the `kibana_admin` role in addition to a custom role that grants {kib} privileges is ineffective because `kibana_admin` has access to all the features in all spaces. -NOTE: When running multiple tenants of Kibana by changing the `kibana.index` in your `kibana.yml`, you cannot use `kibana_admin` to grant access. You must create custom roles that authorize the user for that specific tenant. Although multi-tenant installations are supported, the recommended approach to securing access to Kibana segments is to grant users access to specific spaces. +NOTE: When running multiple tenants of {kib} by changing the `kibana.index` in your `kibana.yml`, you cannot use `kibana_admin` to grant access. You must create custom roles that authorize the user for that specific tenant. Although multi-tenant installations are supported, the recommended approach to securing access to {kib} segments is to grant users access to specific spaces. [role="xpack"] [[xpack-kibana-role-management]] @@ -17,26 +17,26 @@ To create a role that grants {kib} privileges, open the menu, go to *Stack Manag [[adding_kibana_privileges]] ==== Adding {kib} privileges -To assign {kib} privileges to the role, click **Add space privilege** in the Kibana section. +To assign {kib} privileges to the role, click **Add {kib} privilege** in the {kib} section. [role="screenshot"] -image::user/security/images/add-space-privileges.png[Add space privileges] +image::user/security/images/add-space-privileges.png[Add {kib} privileges] Open the **Spaces** selection control to specify whether to grant the role access to all spaces *** Global (all spaces)** or one or more individual spaces. If you select *** Global (all spaces)**, you can’t select individual spaces until you clear your selection. Use the **Privilege** menu to grant access to features. The default is **Custom**, which you can use to grant access to individual features. Otherwise, you can grant read and write access to all current and future features by selecting **All**, or grant read access to all current and future features by selecting **Read**. -When using the **Customize by feature** option, you can choose either **All**, **Read** or **None** for access to each feature. As new features are added to Kibana, roles that use the custom option do not automatically get access to the new features. You must manually update the roles. +When using the **Customize by feature** option, you can choose either **All**, **Read** or **None** for access to each feature. As new features are added to {kib}, roles that use the custom option do not automatically get access to the new features. You must manually update the roles. NOTE: *{stack-monitor-app}* relies on built-in roles to grant access. When a user is assigned the appropriate roles, the *{stack-monitor-app}* application is available; otherwise, it is not visible. -To apply your changes, click **Create space privilege**. The space privilege shows up under the Kibana privileges section of the role. +To apply your changes, click **Add {kib} privilege**. The privilege shows up under the {kib} privileges section of the role. [role="screenshot"] -image::user/security/images/create-space-privilege.png[Create space privilege] +image::user/security/images/create-space-privilege.png[Add {kib} privilege] ==== Feature availability @@ -64,9 +64,9 @@ Features are available to users when their roles grant access to the features, * ==== Assigning different privileges to different spaces -Using the same role, it’s possible to assign different privileges to different spaces. After you’ve added space privileges, click **Add space privilege**. If you’ve already added privileges for either *** Global (all spaces)** or an individual space, you will not be able to select these in the **Spaces** selection control. +Using the same role, it’s possible to assign different privileges to different spaces. After you’ve added privileges, click **Add {kib} privilege**. If you’ve already added privileges for either *** Global (all spaces)** or an individual space, you will not be able to select these in the **Spaces** selection control. -Additionally, if you’ve already assigned privileges at *** Global (all spaces)**, you are only able to assign additional privileges to individual spaces. Similar to the behavior of multiple roles granting the union of all privileges, space privileges are also a union. If you’ve already granted the user the **All** privilege at *** Global (all spaces)**, you’re not able to restrict the role to only the **Read** privilege at an individual space. +Additionally, if you’ve already assigned privileges at *** Global (all spaces)**, you are only able to assign additional privileges to individual spaces. Similar to the behavior of multiple roles granting the union of all privileges, {kib} privileges are also a union. If you’ve already granted the user the **All** privilege at *** Global (all spaces)**, you’re not able to restrict the role to only the **Read** privilege at an individual space. ==== Privilege summary @@ -78,39 +78,37 @@ image::user/security/images/view-privilege-summary.png[View privilege summary] ==== Example 1: Grant all access to Dashboard at an individual space -. Click **Add space privilege**. +. Click **Add {kib} privilege**. . For **Spaces**, select an individual space. . For **Privilege**, leave the default selection of **Custom**. . For the Dashboard feature, select **All** -. Click **Create space privilege**. +. Click **Add {kib} privilege**. [role="screenshot"] image::user/security/images/privilege-example-1.png[Privilege example 1] ==== Example 2: Grant all access to one space and read access to another -. Click **Add space privilege**. +. Click **Add {kib} privilege**. . For **Spaces**, select the first space. . For **Privilege**, select **All**. -. Click **Create space privilege**. -. Click **Add space privilege**. +. Click **Add {kib} privilege**. . For **Spaces**, select the second space. . For **Privilege**, select **Read**. -. Click **Create space privilege**. +. Click **Add {kib} privilege**. [role="screenshot"] image::user/security/images/privilege-example-2.png[Privilege example 2] ==== Example 3: Grant read access to all spaces and write access to an individual space -. Click **Add space privilege**. +. Click **Add {kib} privilege**. . For **Spaces**, select *** Global (all spaces)**. . For **Privilege**, select **Read**. -. Click **Create space privilege**. -. Click **Add space privilege**. +. Click **Add {kib} privilege**. . For **Spaces**, select the individual space. . For **Privilege**, select **All**. -. Click **Create space privilege**. +. Click **Add {kib} privilege**. [role="screenshot"] image::user/security/images/privilege-example-3.png[Privilege example 3] diff --git a/docs/user/security/rbac_tutorial.asciidoc b/docs/user/security/rbac_tutorial.asciidoc index cc4af9041bcd9..bf7be6284b1a9 100644 --- a/docs/user/security/rbac_tutorial.asciidoc +++ b/docs/user/security/rbac_tutorial.asciidoc @@ -28,7 +28,7 @@ To complete this tutorial, you'll need the following: * **A space**: In this tutorial, use `Dev Mortgage` as the space name. See <> for details on creating a space. -* **Data**: You can use <> or +* **Data**: You can use <> or live data. In the following steps, Filebeat and Metricbeat data are used. [float] diff --git a/docs/visualize/images/lens_aggregation_labels.png b/docs/visualize/images/lens_aggregation_labels.png deleted file mode 100644 index 9dcf1d226a197..0000000000000 Binary files a/docs/visualize/images/lens_aggregation_labels.png and /dev/null differ diff --git a/docs/visualize/images/lens_data_info.png b/docs/visualize/images/lens_data_info.png deleted file mode 100644 index 5ea6fc64a217d..0000000000000 Binary files a/docs/visualize/images/lens_data_info.png and /dev/null differ diff --git a/docs/visualize/images/lens_drag_drop.gif b/docs/visualize/images/lens_drag_drop.gif deleted file mode 100644 index 1f8580d462702..0000000000000 Binary files a/docs/visualize/images/lens_drag_drop.gif and /dev/null differ diff --git a/docs/visualize/images/lens_index_pattern.png b/docs/visualize/images/lens_index_pattern.png deleted file mode 100644 index 90a34b7a5d225..0000000000000 Binary files a/docs/visualize/images/lens_index_pattern.png and /dev/null differ diff --git a/docs/visualize/images/lens_layers.png b/docs/visualize/images/lens_layers.png deleted file mode 100644 index 7410425a6977e..0000000000000 Binary files a/docs/visualize/images/lens_layers.png and /dev/null differ diff --git a/docs/visualize/images/lens_suggestions.gif b/docs/visualize/images/lens_suggestions.gif deleted file mode 100644 index 3258e924cb205..0000000000000 Binary files a/docs/visualize/images/lens_suggestions.gif and /dev/null differ diff --git a/docs/visualize/images/lens_tutorial_1.png b/docs/visualize/images/lens_tutorial_1.png deleted file mode 100644 index 77c1532e0ddac..0000000000000 Binary files a/docs/visualize/images/lens_tutorial_1.png and /dev/null differ diff --git a/docs/visualize/images/lens_tutorial_2.png b/docs/visualize/images/lens_tutorial_2.png deleted file mode 100644 index e7b8a7b515f52..0000000000000 Binary files a/docs/visualize/images/lens_tutorial_2.png and /dev/null differ diff --git a/docs/visualize/images/lens_tutorial_3.1.png b/docs/visualize/images/lens_tutorial_3.1.png deleted file mode 100644 index e9ed365e64aec..0000000000000 Binary files a/docs/visualize/images/lens_tutorial_3.1.png and /dev/null differ diff --git a/docs/visualize/images/lens_tutorial_3.2.png b/docs/visualize/images/lens_tutorial_3.2.png deleted file mode 100644 index c19bcb05dcb00..0000000000000 Binary files a/docs/visualize/images/lens_tutorial_3.2.png and /dev/null differ diff --git a/docs/visualize/images/lens_tutorial_3.png b/docs/visualize/images/lens_tutorial_3.png deleted file mode 100644 index 35fb10d4985e1..0000000000000 Binary files a/docs/visualize/images/lens_tutorial_3.png and /dev/null differ diff --git a/docs/visualize/images/lens_viz_types.png b/docs/visualize/images/lens_viz_types.png deleted file mode 100644 index 2ecfa6bd0e0e3..0000000000000 Binary files a/docs/visualize/images/lens_viz_types.png and /dev/null differ diff --git a/examples/alerting_example/common/constants.ts b/examples/alerting_example/common/constants.ts deleted file mode 100644 index 5884eb3220519..0000000000000 --- a/examples/alerting_example/common/constants.ts +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -export const ALERTING_EXAMPLE_APP_ID = 'AlertingExample'; - -// always firing -export const DEFAULT_INSTANCES_TO_GENERATE = 5; - -// Astros -export enum Craft { - OuterSpace = 'Outer Space', - ISS = 'ISS', -} -export enum Operator { - AreAbove = 'Are above', - AreBelow = 'Are below', - AreExactly = 'Are exactly', -} diff --git a/examples/alerting_example/kibana.json b/examples/alerting_example/kibana.json deleted file mode 100644 index a2691c5fdcab7..0000000000000 --- a/examples/alerting_example/kibana.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "id": "alertingExample", - "version": "0.0.1", - "kibanaVersion": "kibana", - "server": true, - "ui": true, - "requiredPlugins": ["triggers_actions_ui", "charts", "data", "alerts", "actions", "features", "developerExamples"], - "optionalPlugins": [] -} diff --git a/examples/alerting_example/public/alert_types/always_firing.tsx b/examples/alerting_example/public/alert_types/always_firing.tsx deleted file mode 100644 index 130519308d3c3..0000000000000 --- a/examples/alerting_example/public/alert_types/always_firing.tsx +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import React, { Fragment } from 'react'; -import { EuiFlexGroup, EuiFlexItem, EuiFieldNumber, EuiFormRow } from '@elastic/eui'; -import { i18n } from '@kbn/i18n'; -import { AlertTypeModel } from '../../../../x-pack/plugins/triggers_actions_ui/public'; -import { DEFAULT_INSTANCES_TO_GENERATE } from '../../common/constants'; - -interface AlwaysFiringParamsProps { - alertParams: { instances?: number }; - setAlertParams: (property: string, value: any) => void; - errors: { [key: string]: string[] }; -} - -export function getAlertType(): AlertTypeModel { - return { - id: 'example.always-firing', - name: 'Always Fires', - iconClass: 'bolt', - alertParamsExpression: AlwaysFiringExpression, - validate: (alertParams: AlwaysFiringParamsProps['alertParams']) => { - const { instances } = alertParams; - const validationResult = { - errors: { - instances: new Array(), - }, - }; - if (instances && instances < 0) { - validationResult.errors.instances.push( - i18n.translate('AlertingExample.addAlert.error.invalidRandomInstances', { - defaultMessage: 'instances must be equal or greater than zero.', - }) - ); - } - return validationResult; - }, - requiresAppContext: false, - }; -} - -export const AlwaysFiringExpression: React.FunctionComponent = ({ - alertParams, - setAlertParams, -}) => { - const { instances = DEFAULT_INSTANCES_TO_GENERATE } = alertParams; - return ( - - - - - { - setAlertParams('instances', event.target.valueAsNumber); - }} - /> - - - - - ); -}; diff --git a/examples/alerting_example/public/alert_types/index.ts b/examples/alerting_example/public/alert_types/index.ts deleted file mode 100644 index db9f855b573e8..0000000000000 --- a/examples/alerting_example/public/alert_types/index.ts +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { registerNavigation as registerPeopleInSpaceNavigation } from './astros'; -import { ALERTING_EXAMPLE_APP_ID } from '../../common/constants'; -import { SanitizedAlert } from '../../../../x-pack/plugins/alerts/common'; -import { PluginSetupContract as AlertingSetup } from '../../../../x-pack/plugins/alerts/public'; - -export function registerNavigation(alerts: AlertingSetup) { - // register default navigation - alerts.registerDefaultNavigation( - ALERTING_EXAMPLE_APP_ID, - (alert: SanitizedAlert) => `/alert/${alert.id}` - ); - - registerPeopleInSpaceNavigation(alerts); -} diff --git a/examples/alerting_example/public/application.tsx b/examples/alerting_example/public/application.tsx deleted file mode 100644 index 23e9d19441002..0000000000000 --- a/examples/alerting_example/public/application.tsx +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import React from 'react'; -import ReactDOM from 'react-dom'; -import { BrowserRouter as Router, Route, RouteComponentProps } from 'react-router-dom'; -import { EuiPage } from '@elastic/eui'; -import { - AppMountParameters, - CoreStart, - IUiSettingsClient, - DocLinksStart, - ToastsSetup, - ApplicationStart, -} from '../../../src/core/public'; -import { DataPublicPluginStart } from '../../../src/plugins/data/public'; -import { ChartsPluginStart } from '../../../src/plugins/charts/public'; - -import { Page } from './components/page'; -import { DocumentationPage } from './components/documentation'; -import { ViewAlertPage } from './components/view_alert'; -import { TriggersAndActionsUIPublicPluginStart } from '../../../x-pack/plugins/triggers_actions_ui/public'; -import { AlertingExamplePublicStartDeps } from './plugin'; -import { ViewPeopleInSpaceAlertPage } from './components/view_astros_alert'; - -export interface AlertingExampleComponentParams { - application: CoreStart['application']; - http: CoreStart['http']; - basename: string; - triggers_actions_ui: TriggersAndActionsUIPublicPluginStart; - data: DataPublicPluginStart; - charts: ChartsPluginStart; - uiSettings: IUiSettingsClient; - docLinks: DocLinksStart; - toastNotifications: ToastsSetup; - capabilities: ApplicationStart['capabilities']; -} - -const AlertingExampleApp = (deps: AlertingExampleComponentParams) => { - const { basename, http } = deps; - return ( - - - ( - - - - )} - /> - ) => { - return ( - - - - ); - }} - /> - ) => { - return ( - - - - ); - }} - /> - - - ); -}; - -export const renderApp = ( - { application, notifications, http, uiSettings, docLinks }: CoreStart, - deps: AlertingExamplePublicStartDeps, - { appBasePath, element }: AppMountParameters -) => { - ReactDOM.render( - , - element - ); - - return () => ReactDOM.unmountComponentAtNode(element); -}; diff --git a/examples/alerting_example/public/components/create_alert.tsx b/examples/alerting_example/public/components/create_alert.tsx deleted file mode 100644 index 72e3835b100fe..0000000000000 --- a/examples/alerting_example/public/components/create_alert.tsx +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import React, { useState } from 'react'; - -import { EuiIcon, EuiFlexItem, EuiCard, EuiFlexGroup } from '@elastic/eui'; - -import { - AlertsContextProvider, - AlertAdd, -} from '../../../../x-pack/plugins/triggers_actions_ui/public'; -import { AlertingExampleComponentParams } from '../application'; -import { ALERTING_EXAMPLE_APP_ID } from '../../common/constants'; - -export const CreateAlert = ({ - http, - // eslint-disable-next-line @typescript-eslint/naming-convention - triggers_actions_ui, - charts, - uiSettings, - docLinks, - data, - toastNotifications, - capabilities, -}: AlertingExampleComponentParams) => { - const [alertFlyoutVisible, setAlertFlyoutVisibility] = useState(false); - - return ( - - - } - title={`Create Alert`} - description="Create an new Alert based on one of our example Alert Types ." - onClick={() => setAlertFlyoutVisibility(true)} - /> - - - - - - - - ); -}; diff --git a/examples/alerting_example/public/components/documentation.tsx b/examples/alerting_example/public/components/documentation.tsx deleted file mode 100644 index 17cc34959b010..0000000000000 --- a/examples/alerting_example/public/components/documentation.tsx +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -import React from 'react'; - -import { - EuiText, - EuiPageBody, - EuiPageContent, - EuiPageContentBody, - EuiPageContentHeader, - EuiPageContentHeaderSection, - EuiPageHeader, - EuiPageHeaderSection, - EuiTitle, - EuiSpacer, -} from '@elastic/eui'; -import { CreateAlert } from './create_alert'; -import { AlertingExampleComponentParams } from '../application'; - -export const DocumentationPage = (deps: AlertingExampleComponentParams) => ( - - - - -